The branch main has been updated by mjg:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=56244d35741a62e725786fc96e7d3d962677c0ad

commit 56244d35741a62e725786fc96e7d3d962677c0ad
Author:     Mateusz Guzik <[email protected]>
AuthorDate: 2022-03-11 15:51:39 +0000
Commit:     Mateusz Guzik <[email protected]>
CommitDate: 2022-03-24 11:22:12 +0000

    vfs: hoist degenerate path lookups out of the loop
---
 sys/kern/vfs_lookup.c | 110 +++++++++++++++++++++++++++++++++++---------------
 1 file changed, 77 insertions(+), 33 deletions(-)

diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index 5a0871c91fac..f4fabe55b06e 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -802,6 +802,57 @@ needs_exclusive_leaf(struct mount *mp, int flags)
 _Static_assert(MAXNAMLEN == NAME_MAX,
     "MAXNAMLEN and NAME_MAX have different values");
 
+static int __noinline
+vfs_lookup_degenerate(struct nameidata *ndp, struct vnode *dp, int wantparent)
+{
+       struct componentname *cnp;
+       struct mount *mp;
+       int error;
+
+       cnp = &ndp->ni_cnd;
+
+       cnp->cn_flags |= ISLASTCN;
+
+       mp = atomic_load_ptr(&dp->v_mount);
+       if (needs_exclusive_leaf(mp, cnp->cn_flags)) {
+               cnp->cn_lkflags &= ~LK_SHARED;
+               cnp->cn_lkflags |= LK_EXCLUSIVE;
+       }
+
+       vn_lock(dp,
+           compute_cn_lkflags(mp, cnp->cn_lkflags | LK_RETRY,
+           cnp->cn_flags));
+
+       if (dp->v_type != VDIR) {
+               error = ENOTDIR;
+               goto bad;
+       }
+       if (cnp->cn_nameiop != LOOKUP) {
+               error = EISDIR;
+               goto bad;
+       }
+       if (wantparent) {
+               ndp->ni_dvp = dp;
+               VREF(dp);
+       }
+       ndp->ni_vp = dp;
+
+       if (cnp->cn_flags & AUDITVNODE1)
+               AUDIT_ARG_VNODE1(dp);
+       else if (cnp->cn_flags & AUDITVNODE2)
+               AUDIT_ARG_VNODE2(dp);
+
+       if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
+               VOP_UNLOCK(dp);
+       /* XXX This should probably move to the top of function. */
+       if (cnp->cn_flags & SAVESTART)
+               panic("lookup: SAVESTART");
+       return (0);
+bad:
+       VOP_UNLOCK(dp);
+       return (error);
+}
+
 /*
  * Search a pathname.
  * This is a very central and rather complicated routine.
@@ -886,13 +937,31 @@ vfs_lookup(struct nameidata *ndp)
        rdonly = cnp->cn_flags & RDONLY;
        cnp->cn_flags &= ~ISSYMLINK;
        ndp->ni_dvp = NULL;
+
+       cnp->cn_lkflags = LK_SHARED;
+       dp = ndp->ni_startdir;
+       ndp->ni_startdir = NULLVP;
+
+       /*
+        * Leading slashes, if any, are supposed to be skipped by the caller.
+        */
+       MPASS(cnp->cn_nameptr[0] != '/');
+
+       /*
+        * Check for degenerate name (e.g. / or "") which is a way of talking
+        * about a directory, e.g. like "/." or ".".
+        */
+       if (__predict_false(cnp->cn_nameptr[0] == '\0')) {
+               error = vfs_lookup_degenerate(ndp, dp, wantparent);
+               if (error == 0)
+                       goto success_right_lock;
+               goto bad_unlocked;
+       }
+
        /*
         * We use shared locks until we hit the parent of the last cn then
         * we adjust based on the requesting flags.
         */
-       cnp->cn_lkflags = LK_SHARED;
-       dp = ndp->ni_startdir;
-       ndp->ni_startdir = NULLVP;
        vn_lock(dp,
            compute_cn_lkflags(dp->v_mount, cnp->cn_lkflags | LK_RETRY,
            cnp->cn_flags));
@@ -980,37 +1049,10 @@ dirloop:
        nameicap_tracker_add(ndp, dp);
 
        /*
-        * Check for degenerate name (e.g. / or "")
-        * which is a way of talking about a directory,
-        * e.g. like "/." or ".".
+        * Make sure degenerate names don't get here, their handling was
+        * previously found in this spot.
         */
-       if (cnp->cn_nameptr[0] == '\0') {
-               if (dp->v_type != VDIR) {
-                       error = ENOTDIR;
-                       goto bad;
-               }
-               if (cnp->cn_nameiop != LOOKUP) {
-                       error = EISDIR;
-                       goto bad;
-               }
-               if (wantparent) {
-                       ndp->ni_dvp = dp;
-                       VREF(dp);
-               }
-               ndp->ni_vp = dp;
-
-               if (cnp->cn_flags & AUDITVNODE1)
-                       AUDIT_ARG_VNODE1(dp);
-               else if (cnp->cn_flags & AUDITVNODE2)
-                       AUDIT_ARG_VNODE2(dp);
-
-               if (!(cnp->cn_flags & (LOCKPARENT | LOCKLEAF)))
-                       VOP_UNLOCK(dp);
-               /* XXX This should probably move to the top of function. */
-               if (cnp->cn_flags & SAVESTART)
-                       panic("lookup: SAVESTART");
-               goto success;
-       }
+       MPASS(cnp->cn_nameptr[0] != '\0');
 
        /*
         * Handle "..": five special cases.
@@ -1341,6 +1383,7 @@ success:
                        goto bad2;
                }
        }
+success_right_lock:
        if (ndp->ni_vp != NULL) {
                if ((cnp->cn_flags & ISDOTDOT) == 0)
                        nameicap_tracker_add(ndp, ndp->ni_vp);
@@ -1359,6 +1402,7 @@ bad2:
 bad:
        if (!dpunlocked)
                vput(dp);
+bad_unlocked:
        ndp->ni_vp = NULL;
        return (error);
 bad_eexist:

Reply via email to