tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

excising struct componentname from the namecache



In the long-term interests of making struct componentname go away
entirely, here's the next step in namei-related cleanup.

This patch: (1) moves the namecache's hash computation inside the
namecache, instead of being spread around all over everywhere; (2)
fixes the namecache to no longer require write access to cn_flags;
(3) reorganizes the calling conventions for cache_lookup (and
cache_raw_lookup) to be more robust; and (4) avoids passing struct
componentname into the namecache at all.

Note that the interface to cache_lookup is not as tidy (especially
since for the time being, it requires access to cn_nameiop) but this
should improve in the future as the special-case handling for
directory ops is pried apart from the primary lookup logic.

These four pieces are available as separate patches, but since nobody
seems to be interested in that, the following is all of them rolled
together.

diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/cd9660/cd9660_lookup.c
--- a/sys/fs/cd9660/cd9660_lookup.c     Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/cd9660/cd9660_lookup.c     Mon Oct 15 05:06:00 2012 -0400
@@ -151,8 +151,10 @@
         * check the name cache to see if the directory/name pair
         * we are looking for is known already.
         */
-       if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
-               return (error);
+       if (cache_lookup(vdp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
+               return *vpp == NULLVP ? ENOENT : 0;
+       }
 
        len = cnp->cn_namelen;
        name = cnp->cn_nameptr;
@@ -336,7 +338,7 @@
        /*
         * Insert name into cache (as non-existent) if appropriate.
         */
-       cache_enter(vdp, *vpp, cnp);
+       cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
        return (nameiop == CREATE || nameiop == RENAME) ? EROFS : ENOENT;
 
 found:
@@ -399,7 +401,7 @@
        /*
         * Insert name into cache if appropriate.
         */
-       cache_enter(vdp, *vpp, cnp);
+       cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
        return 0;
 }
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/efs/efs_vnops.c
--- a/sys/fs/efs/efs_vnops.c    Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/efs/efs_vnops.c    Mon Oct 15 05:06:00 2012 -0400
@@ -73,9 +73,10 @@
        if (err)
                return (err);
 
-       err = cache_lookup(ap->a_dvp, ap->a_vpp, cnp);
-       if (err != -1)
-               return (err);
+       if (cache_lookup(ap->a_dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, ap->a_vpp)) {
+               return *ap->a_vpp == NULLVP ? ENOENT : 0;
+       }
 
        /*
         * Handle the three lookup types: '.', '..', and everything else.
@@ -103,7 +104,8 @@
                    EFS_VTOI(ap->a_dvp), ap->a_cnp, &ino);
                if (err) {
                        if (err == ENOENT && nameiop != CREATE)
-                               cache_enter(ap->a_dvp, NULL, cnp);
+                               cache_enter(ap->a_dvp, NULL, cnp->cn_nameptr,
+                                           cnp->cn_namelen, cnp->cn_flags);
                        if (err == ENOENT && (nameiop == CREATE ||
                            nameiop == RENAME)) {
                                err = VOP_ACCESS(ap->a_dvp, VWRITE,
@@ -120,7 +122,8 @@
                *ap->a_vpp = vp;
        }
 
-       cache_enter(ap->a_dvp, *ap->a_vpp, cnp);
+       cache_enter(ap->a_dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                   cnp->cn_flags);
 
        return 0;
 }
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/msdosfs/msdosfs_lookup.c
--- a/sys/fs/msdosfs/msdosfs_lookup.c   Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/msdosfs/msdosfs_lookup.c   Mon Oct 15 05:06:00 2012 -0400
@@ -146,8 +146,10 @@
         * check the name cache to see if the directory/name pair
         * we are looking for is known already.
         */
-       if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
-               return (error);
+       if (cache_lookup(vdp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
+               return *vpp == NULLVP ? ENOENT: 0;
+       }
 
        /*
         * If they are going after the . or .. entry in the root directory,
@@ -400,7 +402,8 @@
         * for 'FOO'.
         */
        if (nameiop != CREATE)
-               cache_enter(vdp, *vpp, cnp);
+               cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 #endif
 
        return (ENOENT);
@@ -553,7 +556,7 @@
        /*
         * Insert name into cache if appropriate.
         */
-       cache_enter(vdp, *vpp, cnp);
+       cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
 
        return 0;
 }
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/nilfs/nilfs_vnops.c
--- a/sys/fs/nilfs/nilfs_vnops.c        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/nilfs/nilfs_vnops.c        Mon Oct 15 05:06:00 2012 -0400
@@ -652,10 +652,11 @@
 
        DPRINTF(LOOKUP, ("\tlooking up cnp->cn_nameptr '%s'\n",
            cnp->cn_nameptr));
-       /* look in the nami cache; returns 0 on success!! */
-       error = cache_lookup(dvp, vpp, cnp);
-       if (error >= 0)
-               return error;
+       /* look in the namecache */
+       if (cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
+               return *vpp == NULLVP ? ENOENT : 0;
+       }
 
        DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
 
@@ -761,7 +762,8 @@
         * might be seen as negative caching.
         */
        if (nameiop != CREATE)
-               cache_enter(dvp, *vpp, cnp);
+               cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 
        DPRINTFIF(LOOKUP, error, ("nilfs_lookup returing error %d\n", error));
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/ntfs/ntfs_vnops.c
--- a/sys/fs/ntfs/ntfs_vnops.c  Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/ntfs/ntfs_vnops.c  Mon Oct 15 05:06:00 2012 -0400
@@ -682,8 +682,10 @@
         * check the name cache to see if the directory/name pair
         * we are looking for is known already.
         */
-       if ((error = cache_lookup(ap->a_dvp, ap->a_vpp, cnp)) >= 0)
-               return (error);
+       if (cache_lookup(ap->a_dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, ap->a_vpp)) {
+               return *ap->a_vpp == NULLVP ? ENOENT : 0;
+       }
 
        if(cnp->cn_namelen == 1 && cnp->cn_nameptr[0] == '.') {
                dprintf(("ntfs_lookup: faking . directory in %llu\n",
@@ -725,7 +727,8 @@
                    (unsigned long long)VTONT(*ap->a_vpp)->i_number));
        }
 
-       cache_enter(dvp, *ap->a_vpp, cnp);
+       cache_enter(dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                   cnp->cn_flags);
 
        return error;
 }
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/puffs/puffs_msgif.c
--- a/sys/fs/puffs/puffs_msgif.c        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/puffs/puffs_msgif.c        Mon Oct 15 05:06:00 2012 -0400
@@ -915,7 +915,7 @@
                        rv = EINVAL;
                        break;
                }
-               cache_purge1(vp, NULL, PURGE_CHILDREN);
+               cache_purge1(vp, NULL, 0, PURGE_CHILDREN);
                break;
 
        case PUFFS_INVAL_PAGECACHE_NODE_RANGE:
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/puffs/puffs_node.c
--- a/sys/fs/puffs/puffs_node.c Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/puffs/puffs_node.c Mon Oct 15 05:06:00 2012 -0400
@@ -247,7 +247,8 @@
        *vpp = vp;
 
        if (PUFFS_USE_NAMECACHE(pmp))
-               cache_enter(dvp, vp, cnp);
+               cache_enter(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 
        return 0;
 }
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/puffs/puffs_vnops.c
--- a/sys/fs/puffs/puffs_vnops.c        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/puffs/puffs_vnops.c        Mon Oct 15 05:06:00 2012 -0400
@@ -526,9 +526,16 @@
         * Check if someone fed it into the cache
         */
        if (!isdot && PUFFS_USE_NAMECACHE(pmp)) {
-               error = cache_lookup(dvp, ap->a_vpp, cnp);
-
-               if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
+               int found, iswhiteout;
+
+               found = cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                                    cnp->cn_nameiop, cnp->cn_flags,
+                                    &iswhiteout, ap->a_vpp);
+               if (iswhiteout) {
+                       cnp->cn_flags |= ISWHITEOUT;
+               }
+
+               if (found && *ap->a_vpp != NULLVP && PUFFS_USE_FS_TTL(pmp)) {
                        cvp = *ap->a_vpp;
                        cpn = VPTOPP(cvp);
 
@@ -540,7 +547,7 @@
                                 * successful lookup. 
                                 */
                                *ap->a_vpp = NULL;
-                               error = -1;
+                               found = 0;
                        }
                }
 
@@ -548,11 +555,20 @@
                 * Do not use negative caching, since the filesystem
                 * provides no TTL for it.
                 */
-               if ((error == ENOENT) && PUFFS_USE_FS_TTL(pmp))
-                       error = -1;
-
-               if (error >= 0)
-                       return error;
+               if (found && *ap->a_vpp == NULLVP && PUFFS_USE_FS_TTL(pmp))
+                       found = 0;
+
+               if (found) {
+                       return *ap->a_vpp == NULLVP ? ENOENT : 0;
+               }
+
+               /*
+                * This is what would have been left in ERROR before
+                * the rearrangement of cache_lookup(). What with all
+                * the macros, I am not sure if this is a dead value
+                * below or not.
+                */
+               error = -1;
        }
 
        if (isdot) {
@@ -606,7 +622,8 @@
                        } else {
                                if (PUFFS_USE_NAMECACHE(pmp) &&
                                    !PUFFS_USE_FS_TTL(pmp))
-                                       cache_enter(dvp, NULL, cnp);
+                                       cache_enter(dvp, NULL, cnp->cn_nameptr,
+                                               cnp->cn_namelen, cnp->cn_flags);
                        }
                }
                goto out;
@@ -682,7 +699,8 @@
        *ap->a_vpp = vp;
 
        if (PUFFS_USE_NAMECACHE(pmp))
-               cache_enter(dvp, vp, cnp);
+               cache_enter(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 
        /* XXX */
        if ((lookup_msg->pvnr_cn.pkcn_flags & REQUIREDIR) == 0)
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/smbfs/smbfs_vnops.c
--- a/sys/fs/smbfs/smbfs_vnops.c        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/smbfs/smbfs_vnops.c        Mon Oct 15 05:06:00 2012 -0400
@@ -596,7 +596,8 @@
        if (error)
                goto out;
 
-       cache_enter(dvp, *ap->a_vpp, cnp);
+       cache_enter(dvp, *ap->a_vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                   cnp->cn_flags);
 
   out:
        VN_KNOTE(dvp, NOTE_WRITE);
@@ -1202,29 +1203,25 @@
         * the time the cache entry has been created. If it has,
         * the cache entry has to be ignored.
         */
-       if ((error = cache_lookup(dvp, vpp, cnp)) >= 0) {
+       if (cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags,
+                        NULL, vpp)) {
                struct vattr vattr;
                struct vnode *newvp;
-               int err2;
 
-               if (error && error != ENOENT) {
-                       *vpp = NULLVP;
-                       return error;
-               }
-
-               err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
-               if (err2 != 0) {
-                       if (error == 0) {
+               error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
+               if (error != 0) {
+                       if (*vpp != NULLVP) {
                                if (*vpp != dvp)
                                        vput(*vpp);
                                else
                                        vrele(*vpp);
                        }
                        *vpp = NULLVP;
-                       return err2;
+                       return error;
                }
 
-               if (error == ENOENT) {
+               if (*vpp == NULLVP) {
                        if (!VOP_GETATTR(dvp, &vattr, cnp->cn_cred)
                            && vattr.va_mtime.tv_sec == VTOSMB(dvp)->n_nctime)
                                return ENOENT;
@@ -1297,7 +1294,8 @@
                 * Insert name into cache (as non-existent) if appropriate.
                 */
                if (nameiop != CREATE)
-                       cache_enter(dvp, *vpp, cnp);
+                       cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                                   cnp->cn_flags);
 
                return (ENOENT);
        }
@@ -1352,11 +1350,13 @@
        KASSERT(error == 0);
        if (cnp->cn_nameiop != DELETE || !islastcn) {
                VTOSMB(*vpp)->n_ctime = VTOSMB(*vpp)->n_mtime.tv_sec;
-               cache_enter(dvp, *vpp, cnp);
+               cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 #ifdef notdef
        } else if (error == ENOENT && cnp->cn_nameiop != CREATE) {
                VTOSMB(*vpp)->n_nctime = VTOSMB(*vpp)->n_mtime.tv_sec;
-               cache_enter(dvp, *vpp, cnp);
+               cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 #endif
        }
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/tmpfs/tmpfs_vnops.c
--- a/sys/fs/tmpfs/tmpfs_vnops.c        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/tmpfs/tmpfs_vnops.c        Mon Oct 15 05:06:00 2012 -0400
@@ -133,6 +133,7 @@
        const bool lastcn = (cnp->cn_flags & ISLASTCN) != 0;
        tmpfs_node_t *dnode, *tnode;
        tmpfs_dirent_t *de;
+       int cachefound, iswhiteout;
        int error;
 
        KASSERT(VOP_ISLOCKED(dvp));
@@ -160,9 +161,18 @@
         * Avoid doing a linear scan of the directory if the requested
         * directory/name couple is already in the cache.
         */
-       error = cache_lookup(dvp, vpp, cnp);
-       if (error >= 0) {
-               /* Both cache-hit or an error case. */
+       cachefound = cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                                 cnp->cn_nameiop, cnp->cn_flags,
+                                 &iswhiteout, vpp);
+       if (iswhiteout) {
+               cnp->cn_flags |= ISWHITEOUT;
+       }
+       if (cachefound && *vpp == NULLVP) {
+               /* Negative cache hit. */
+               error = ENOENT;
+               goto out;
+       } else if (cachefound) {
+               error = 0;
                goto out;
        }
 
@@ -278,7 +288,8 @@
         * not improve the performance).
         */
        if (cnp->cn_nameiop != CREATE) {
-               cache_enter(dvp, *vpp, cnp);
+               cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
        }
 out:
        KASSERT((*vpp && VOP_ISLOCKED(*vpp)) || error);
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/udf/udf_vnops.c
--- a/sys/fs/udf/udf_vnops.c    Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/udf/udf_vnops.c    Mon Oct 15 05:06:00 2012 -0400
@@ -687,10 +687,11 @@
 
        DPRINTF(LOOKUP, ("\tlooking up cnp->cn_nameptr '%s'\n",
            cnp->cn_nameptr));
-       /* look in the nami cache; returns 0 on success!! */
-       error = cache_lookup(dvp, vpp, cnp);
-       if (error >= 0)
-               return error;
+       /* look in the namecache */
+       if (cache_lookup(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
+               return *vpp == NULLVP ? ENOENT : 0;
+       }
 
        DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
 
@@ -796,7 +797,8 @@
         * might be seen as negative caching.
         */
        if (nameiop != CREATE)
-               cache_enter(dvp, *vpp, cnp);
+               cache_enter(dvp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
 
        DPRINTFIF(LOOKUP, error, ("udf_lookup returing error %d\n", error));
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/union/union.h
--- a/sys/fs/union/union.h      Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/union/union.h      Mon Oct 15 05:06:00 2012 -0400
@@ -126,7 +126,6 @@
        struct vnode            *un_dirvp;      /* v: Parent dir of uppervp */
        struct vnode            *un_pvp;        /* v: Parent vnode */
        char                    *un_path;       /* v: saved component name */
-       int                     un_hash;        /* v: saved un_path hash */
        int                     un_openl;       /* v: # of opens on lowervp */
        unsigned int            un_flags;       /* v: node flags */
        unsigned int            un_cflags;      /* c: cache flags */
diff -r cba39a555764 -r 42d43ac83fe1 sys/fs/union/union_subr.c
--- a/sys/fs/union/union_subr.c Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/fs/union/union_subr.c Mon Oct 15 05:06:00 2012 -0400
@@ -105,7 +105,7 @@
 static kmutex_t uhash_lock;
 
 void union_updatevp(struct union_node *, struct vnode *, struct vnode *);
-static int union_do_lookup(struct vnode *, struct componentname *, 
kauth_cred_t,    const char *, u_long);
+static int union_do_lookup(struct vnode *, struct componentname *, 
kauth_cred_t,    const char *);
 int union_vn_close(struct vnode *, int, kauth_cred_t, struct lwp *);
 static void union_dircache_r(struct vnode *, struct vnode ***, int *);
 struct vnode *union_dircache(struct vnode *, struct lwp *);
@@ -451,7 +451,6 @@
                if (lowervp != un->un_lowervp) {
                        union_newlower(un, lowervp);
                        if (cnp && (lowervp != NULLVP)) {
-                               un->un_hash = cnp->cn_hash;
                                un->un_path = malloc(cnp->cn_namelen+1,
                                                M_TEMP, M_WAITOK);
                                memcpy(un->un_path, cnp->cn_nameptr,
@@ -572,14 +571,12 @@
        union_newsize(*vpp, uppersz, lowersz);
 
        if (dvp && cnp && (lowervp != NULLVP)) {
-               un->un_hash = cnp->cn_hash;
                un->un_path = malloc(cnp->cn_namelen+1, M_TEMP, M_WAITOK);
                memcpy(un->un_path, cnp->cn_nameptr, cnp->cn_namelen);
                un->un_path[cnp->cn_namelen] = '\0';
                vref(dvp);
                un->un_dirvp = dvp;
        } else {
-               un->un_hash = 0;
                un->un_path = 0;
                un->un_dirvp = 0;
        }
@@ -778,10 +775,9 @@
  */
 static int
 union_do_lookup(struct vnode *dvp, struct componentname *cnp, kauth_cred_t 
cred,
-    const char *path, u_long hash)
+    const char *path)
 {
        int error;
-       const char *cp;
        struct vnode *vp;
 
        cnp->cn_nameiop = CREATE;
@@ -789,13 +785,6 @@
        cnp->cn_cred = cred;
        cnp->cn_nameptr = path;
        cnp->cn_namelen = strlen(path);
-       if (hash == 0) {
-               cp = NULL;
-               cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
-               KASSERT(*cp == 0);
-       } else {
-               cnp->cn_hash = hash;
-       }
 
        error = VOP_LOOKUP(dvp, &vp, cnp);
 
@@ -847,7 +836,7 @@
        vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
 
        error = union_do_lookup(dvp, &cn,
-           (um->um_op == UNMNT_ABOVE ? cnp->cn_cred : um->um_cred), pnbuf, 0);
+           (um->um_op == UNMNT_ABOVE ? cnp->cn_cred : um->um_cred), pnbuf);
        if (error) {
                VOP_UNLOCK(dvp);
                PNBUF_PUT(pnbuf);
@@ -891,7 +880,7 @@
 
        error = union_do_lookup(dvp, &cn,
            (um->um_op == UNMNT_ABOVE ? cnp->cn_cred : um->um_cred),
-           un->un_path, un->un_hash);
+           un->un_path);
        if (error)
                return error;
 
@@ -924,7 +913,7 @@
        vn_lock(un->un_dirvp, LK_EXCLUSIVE | LK_RETRY);
 
        error = union_do_lookup(un->un_dirvp, &cn, l->l_cred,
-           un->un_path, un->un_hash);
+           un->un_path);
        if (error) {
                VOP_UNLOCK(un->un_dirvp);
                return error;
@@ -1197,7 +1186,6 @@
                        cn.cn_cred = cred;
                        cn.cn_nameptr = dp->d_name;
                        cn.cn_namelen = dp->d_namlen;
-                       cn.cn_hash = 0;
                        error = VOP_LOOKUP(un->un_uppervp, &tvp, &cn);
                        if (error == ENOENT && (cn.cn_flags & ISWHITEOUT)) {
                                error = 0;
diff -r cba39a555764 -r 42d43ac83fe1 sys/kern/vfs_cache.c
--- a/sys/kern/vfs_cache.c      Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/kern/vfs_cache.c      Mon Oct 15 05:06:00 2012 -0400
@@ -109,6 +109,16 @@
 };
 
 /*
+ * The type for the hash code. While the hash function generates a
+ * u32, the hash code has historically been passed around as a u_long,
+ * and the value is modified by xor'ing a uintptr_t, so it's not
+ * entirely clear what the best type is. For now I'll leave it
+ * unchanged as u_long.
+ */
+
+typedef u_long nchash_t;
+
+/*
  * Structures associated with name cacheing.
  */
 
@@ -119,8 +129,8 @@
 static LIST_HEAD(nchashhead, namecache) *nchashtbl __read_mostly;
 static u_long  nchash __read_mostly;
 
-#define        NCHASH(cnp, dvp)        \
-       (((cnp)->cn_hash ^ ((uintptr_t)(dvp) >> 3)) & nchash)
+#define        NCHASH2(hash, dvp)      \
+       (((hash) ^ ((uintptr_t)(dvp) >> 3)) & nchash)
 
 static LIST_HEAD(ncvhashhead, namecache) *ncvhashtbl __read_mostly;
 static u_long  ncvhash __read_mostly;
@@ -151,7 +161,7 @@
 
 static void cache_invalidate(struct namecache *);
 static struct namecache *cache_lookup_entry(
-    const struct vnode *, const struct componentname *);
+    const struct vnode *, const char *, size_t);
 static void cache_thread(void *);
 static void cache_invalidate(struct namecache *);
 static void cache_disassociate(struct namecache *);
@@ -160,6 +170,21 @@
 static void cache_dtor(void *, void *);
 
 /*
+ * Compute the hash for an entry.
+ *
+ * (This is for now a wrapper around namei_hash, whose interface is
+ * for the time being slightly inconvenient.)
+ */
+static nchash_t
+cache_hash(const char *name, size_t namelen)
+{
+       const char *endptr;
+
+       endptr = name + namelen;
+       return namei_hash(name, &endptr);
+}
+
+/*
  * Invalidate a cache entry and enqueue it for garbage collection.
  */
 static void
@@ -257,18 +282,20 @@
  * at least one of the per-CPU locks must be held.
  */
 static struct namecache *
-cache_lookup_entry(const struct vnode *dvp, const struct componentname *cnp)
+cache_lookup_entry(const struct vnode *dvp, const char *name, size_t namelen)
 {
        struct nchashhead *ncpp;
        struct namecache *ncp;
+       nchash_t hash;
 
        KASSERT(dvp != NULL);
-       ncpp = &nchashtbl[NCHASH(cnp, dvp)];
+       hash = cache_hash(name, namelen);
+       ncpp = &nchashtbl[NCHASH2(hash, dvp)];
 
        LIST_FOREACH(ncp, ncpp, nc_hash) {
                if (ncp->nc_dvp != dvp ||
-                   ncp->nc_nlen != cnp->cn_namelen ||
-                   memcmp(ncp->nc_name, cnp->cn_nameptr, (u_int)ncp->nc_nlen))
+                   ncp->nc_nlen != namelen ||
+                   memcmp(ncp->nc_name, name, (u_int)ncp->nc_nlen))
                        continue;
                mutex_enter(&ncp->nc_lock);
                if (__predict_true(ncp->nc_dvp == dvp)) {
@@ -288,47 +315,86 @@
  * holding long names (which would either waste space, or
  * add greatly to the complexity).
  *
- * Lookup is called with ni_dvp pointing to the directory to search,
- * ni_ptr pointing to the name of the entry being sought, ni_namelen
- * tells the length of the name, and ni_hash contains a hash of
- * the name. If the lookup succeeds, the vnode is locked, stored in ni_vp
- * and a status of zero is returned. If the locking fails for whatever
- * reason, the vnode is unlocked and the error is returned to caller.
- * If the lookup determines that the name does not exist (negative cacheing),
- * a status of ENOENT is returned. If the lookup fails, a status of -1
- * is returned.
+ * Lookup is called with DVP pointing to the directory to search,
+ * and CNP providing the name of the entry being sought: cn_nameptr
+ * is the name, cn_namelen is its length, and cn_flags is the flags
+ * word from the namei operation.
+ *
+ * DVP must be locked.
+ *
+ * There are three possible non-error return states:
+ *    1. Nothing was found in the cache. Nothing is known about
+ *       the requested name.
+ *    2. A negative entry was found in the cache, meaning that the
+ *       requested name definitely does not exist.
+ *    3. A positive entry was found in the cache, meaning that the
+ *       requested name does exist and that we are providing the
+ *       vnode.
+ * In these cases the results are:
+ *    1. 0 returned; VN is set to NULL.
+ *    2. 1 returned; VN is set to NULL.
+ *    3. 1 returned; VN is set to the vnode found.
+ *
+ * The additional result argument ISWHT is set to zero, unless a
+ * negative entry is found that was entered as a whiteout, in which
+ * case ISWHT is set to one.
+ *
+ * The ISWHT_RET argument pointer may be null. In this case an
+ * assertion is made that the whiteout flag is not set. File systems
+ * that do not support whiteouts can/should do this.
+ *
+ * Filesystems that do support whiteouts should add ISWHITEOUT to
+ * cnp->cn_flags if ISWHT comes back nonzero.
+ *
+ * When a vnode is returned, it is locked, as per the vnode lookup
+ * locking protocol.
+ *
+ * There is no way for this function to fail, in the sense of
+ * generating an error that requires aborting the namei operation.
+ *
+ * (Prior to October 2012, this function returned an integer status,
+ * and a vnode, and mucked with the flags word in CNP for whiteouts.
+ * The integer status was -1 for "nothing found", ENOENT for "a
+ * negative entry found", 0 for "a positive entry found", and possibly
+ * other errors, and the value of VN might or might not have been set
+ * depending on what error occurred.)
  */
 int
-cache_lookup(struct vnode *dvp, struct vnode **vpp, struct componentname *cnp)
+cache_lookup(struct vnode *dvp, const char *name, size_t namelen,
+            uint32_t nameiop, uint32_t cnflags,
+            int *iswht_ret, struct vnode **vn_ret)
 {
        struct namecache *ncp;
        struct vnode *vp;
        struct nchcpu *cpup;
        int error;
 
+       /* Establish default result values */
+       if (iswht_ret != NULL) {
+               *iswht_ret = 0;
+       }
+       *vn_ret = NULL;
+
        if (__predict_false(!doingcache)) {
-               cnp->cn_flags &= ~MAKEENTRY;
-               *vpp = NULL;
-               return -1;
+               return 0;
        }
 
        cpup = curcpu()->ci_data.cpu_nch;
        mutex_enter(&cpup->cpu_lock);
-       if (__predict_false(cnp->cn_namelen > NCHNAMLEN)) {
+       if (__predict_false(namelen > NCHNAMLEN)) {
                COUNT(cpup->cpu_stats, ncs_long);
-               cnp->cn_flags &= ~MAKEENTRY;
                mutex_exit(&cpup->cpu_lock);
-               *vpp = NULL;
-               return -1;
+               /* found nothing */
+               return 0;
        }
-       ncp = cache_lookup_entry(dvp, cnp);
+       ncp = cache_lookup_entry(dvp, name, namelen);
        if (__predict_false(ncp == NULL)) {
                COUNT(cpup->cpu_stats, ncs_miss);
                mutex_exit(&cpup->cpu_lock);
-               *vpp = NULL;
-               return -1;
+               /* found nothing */
+               return 0;
        }
-       if ((cnp->cn_flags & MAKEENTRY) == 0) {
+       if ((cnflags & MAKEENTRY) == 0) {
                COUNT(cpup->cpu_stats, ncs_badhits);
                /*
                 * Last component and we are renaming or deleting,
@@ -338,20 +404,27 @@
                cache_invalidate(ncp);
                mutex_exit(&ncp->nc_lock);
                mutex_exit(&cpup->cpu_lock);
-               *vpp = NULL;
-               return -1;
-       } else if (ncp->nc_vp == NULL) {
-               /*
-                * Restore the ISWHITEOUT flag saved earlier.
-                */
-               KASSERT((ncp->nc_flags & ~ISWHITEOUT) == 0);
-               cnp->cn_flags |= ncp->nc_flags;
-               if (__predict_true(cnp->cn_nameiop != CREATE ||
-                   (cnp->cn_flags & ISLASTCN) == 0)) {
+               /* found nothing */
+               return 0;
+       }
+       if (ncp->nc_vp == NULL) {
+               if (iswht_ret != NULL) {
+                       /*
+                        * Restore the ISWHITEOUT flag saved earlier.
+                        */
+                       KASSERT((ncp->nc_flags & ~ISWHITEOUT) == 0);
+                       *iswht_ret = (ncp->nc_flags & ISWHITEOUT) != 0;
+               } else {
+                       KASSERT(ncp->nc_flags == 0);
+               }
+
+               if (__predict_true(nameiop != CREATE ||
+                   (cnflags & ISLASTCN) == 0)) {
                        COUNT(cpup->cpu_stats, ncs_neghits);
                        mutex_exit(&ncp->nc_lock);
                        mutex_exit(&cpup->cpu_lock);
-                       return ENOENT;
+                       /* found neg entry; vn is already null from above */
+                       return 1;
                } else {
                        COUNT(cpup->cpu_stats, ncs_badhits);
                        /*
@@ -363,8 +436,8 @@
                        cache_invalidate(ncp);
                        mutex_exit(&ncp->nc_lock);
                        mutex_exit(&cpup->cpu_lock);
-                       *vpp = NULL;
-                       return -1;
+                       /* found nothing */
+                       return 0;
                }
        }
 
@@ -384,8 +457,8 @@
                         * XXX badhits?
                         */
                        COUNT(cpup->cpu_stats, ncs_falsehits);
-                       *vpp = NULL;
-                       return -1;
+                       /* found nothing */
+                       return 0;
                }
        }
 
@@ -399,7 +472,7 @@
 
        if (vp == dvp) {        /* lookup on "." */
                error = 0;
-       } else if (cnp->cn_flags & ISDOTDOT) {
+       } else if (cnflags & ISDOTDOT) {
                VOP_UNLOCK(dvp);
                error = vn_lock(vp, LK_EXCLUSIVE);
                vn_lock(dvp, LK_EXCLUSIVE | LK_RETRY);
@@ -411,61 +484,73 @@
         * Check that the lock succeeded.
         */
        if (error) {
-               /* Unlocked, but only for stats. */
+               /* We don't have the right lock, but this is only for stats. */
                COUNT(cpup->cpu_stats, ncs_badhits);
+
                vrele(vp);
-               *vpp = NULL;
-               return -1;
+               /* found nothing */
+               return 0;
        }
 
-       /* Unlocked, but only for stats. */
+       /* We don't have the right lock, but this is only for stats. */
        COUNT(cpup->cpu_stats, ncs_goodhits);
-       *vpp = vp;
-       return 0;
+
+       /* found it */
+       *vn_ret = vp;
+       return 1;
 }
 
 int
-cache_lookup_raw(struct vnode *dvp, struct vnode **vpp,
-    struct componentname *cnp)
+cache_lookup_raw(struct vnode *dvp, const char *name, size_t namelen,
+                uint32_t cnflags,
+                int *iswht_ret, struct vnode **vn_ret)
 {
        struct namecache *ncp;
        struct vnode *vp;
        struct nchcpu *cpup;
        int error;
 
+       /* Establish default results. */
+       if (iswht_ret != NULL) {
+               *iswht_ret = 0;
+       }
+       *vn_ret = NULL;
+
        if (__predict_false(!doingcache)) {
-               cnp->cn_flags &= ~MAKEENTRY;
-               *vpp = NULL;
-               return (-1);
+               /* found nothing */
+               return 0;
        }
 
        cpup = curcpu()->ci_data.cpu_nch;
        mutex_enter(&cpup->cpu_lock);
-       if (__predict_false(cnp->cn_namelen > NCHNAMLEN)) {
+       if (__predict_false(namelen > NCHNAMLEN)) {
                COUNT(cpup->cpu_stats, ncs_long);
-               cnp->cn_flags &= ~MAKEENTRY;
                mutex_exit(&cpup->cpu_lock);
-               *vpp = NULL;
-               return -1;
+               /* found nothing */
+               return 0;
        }
-       ncp = cache_lookup_entry(dvp, cnp);
+       ncp = cache_lookup_entry(dvp, name, namelen);
        if (__predict_false(ncp == NULL)) {
                COUNT(cpup->cpu_stats, ncs_miss);
                mutex_exit(&cpup->cpu_lock);
-               *vpp = NULL;
-               return -1;
+               /* found nothing */
+               return 0;
        }
        vp = ncp->nc_vp;
        if (vp == NULL) {
                /*
                 * Restore the ISWHITEOUT flag saved earlier.
                 */
-               KASSERT((ncp->nc_flags & ~ISWHITEOUT) == 0);
-               cnp->cn_flags |= ncp->nc_flags;
+               if (iswht_ret != NULL) {
+                       KASSERT((ncp->nc_flags & ~ISWHITEOUT) == 0);
+                       /*cnp->cn_flags |= ncp->nc_flags;*/
+                       *iswht_ret = (ncp->nc_flags & ISWHITEOUT) != 0;
+               }
                COUNT(cpup->cpu_stats, ncs_neghits);
                mutex_exit(&ncp->nc_lock);
                mutex_exit(&cpup->cpu_lock);
-               return ENOENT;
+               /* found negative entry; vn is already null from above */
+               return 1;
        }
        if (vtryget(vp)) {
                mutex_exit(&ncp->nc_lock);
@@ -482,15 +567,17 @@
                         * XXX badhits?
                         */
                        COUNT(cpup->cpu_stats, ncs_falsehits);
-                       *vpp = NULL;
-                       return -1;
+                       /* found nothing */
+                       return 0;
                }
        }
 
        /* Unlocked, but only for stats. */
        COUNT(cpup->cpu_stats, ncs_goodhits); /* XXX can be "badhits" */
-       *vpp = vp;
-       return 0;
+
+       /* found it */
+       *vn_ret = vp;
+       return 1;
 }
 
 /*
@@ -584,16 +671,18 @@
  * Add an entry to the cache
  */
 void
-cache_enter(struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
+cache_enter(struct vnode *dvp, struct vnode *vp,
+           const char *name, size_t namelen, uint32_t cnflags)
 {
        struct namecache *ncp;
        struct namecache *oncp;
        struct nchashhead *ncpp;
        struct ncvhashhead *nvcpp;
+       nchash_t hash;
 
        /* First, check whether we can/should add a cache entry. */
-       if ((cnp->cn_flags & MAKEENTRY) == 0 ||
-           __predict_false(cnp->cn_namelen > NCHNAMLEN || !doingcache)) {
+       if ((cnflags & MAKEENTRY) == 0 ||
+           __predict_false(namelen > NCHNAMLEN || !doingcache)) {
                return;
        }
 
@@ -612,7 +701,7 @@
         * Concurrent lookups in the same directory may race for a
         * cache entry.  if there's a duplicated entry, free it.
         */
-       oncp = cache_lookup_entry(dvp, cnp);
+       oncp = cache_lookup_entry(dvp, name, namelen);
        if (oncp) {
                cache_invalidate(oncp);
                mutex_exit(&oncp->nc_lock);
@@ -629,7 +718,7 @@
                 * For negative hits, save the ISWHITEOUT flag so we can
                 * restore it later when the cache entry is used again.
                 */
-               ncp->nc_flags = cnp->cn_flags & ISWHITEOUT;
+               ncp->nc_flags = cnflags & ISWHITEOUT;
        }
 
        /* Fill in cache info. */
@@ -641,11 +730,12 @@
                ncp->nc_vlist.le_prev = NULL;
                ncp->nc_vlist.le_next = NULL;
        }
-       KASSERT(cnp->cn_namelen <= NCHNAMLEN);
-       ncp->nc_nlen = cnp->cn_namelen;
-       memcpy(ncp->nc_name, cnp->cn_nameptr, (unsigned)ncp->nc_nlen);
+       KASSERT(namelen <= NCHNAMLEN);
+       ncp->nc_nlen = namelen;
+       memcpy(ncp->nc_name, name, (unsigned)ncp->nc_nlen);
        TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
-       ncpp = &nchashtbl[NCHASH(cnp, dvp)];
+       hash = cache_hash(name, namelen);
+       ncpp = &nchashtbl[NCHASH2(hash, dvp)];
 
        /*
         * Flush updates before making visible in table.  No need for a
@@ -810,7 +900,7 @@
  * hide entries that would now be invalid
  */
 void
-cache_purge1(struct vnode *vp, const struct componentname *cnp, int flags)
+cache_purge1(struct vnode *vp, const char *name, size_t namelen, int flags)
 {
        struct namecache *ncp, *ncnext;
 
@@ -835,8 +925,8 @@
                        cache_disassociate(ncp);
                }
        }
-       if (cnp != NULL) {
-               ncp = cache_lookup_entry(vp, cnp);
+       if (name != NULL) {
+               ncp = cache_lookup_entry(vp, name, namelen);
                if (ncp) {
                        cache_invalidate(ncp);
                        mutex_exit(&ncp->nc_lock);
diff -r cba39a555764 -r 42d43ac83fe1 sys/kern/vfs_getcwd.c
--- a/sys/kern/vfs_getcwd.c     Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/kern/vfs_getcwd.c     Mon Oct 15 05:06:00 2012 -0400
@@ -130,7 +130,6 @@
        cn.cn_cred = cred;
        cn.cn_nameptr = "..";
        cn.cn_namelen = 2;
-       cn.cn_hash = 0;
        cn.cn_consume = 0;
 
        /*
diff -r cba39a555764 -r 42d43ac83fe1 sys/kern/vfs_lookup.c
--- a/sys/kern/vfs_lookup.c     Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/kern/vfs_lookup.c     Mon Oct 15 05:06:00 2012 -0400
@@ -195,7 +195,7 @@
 ////////////////////////////////////////////////////////////
 
 /*
- * Determine the namei hash (for cn_hash) for name.
+ * Determine the namei hash (for the namecache) for name.
  * If *ep != NULL, hash from name to ep-1.
  * If *ep == NULL, hash from name until the first NUL or '/', and
  * return the location of this termination character in *ep.
@@ -222,6 +222,22 @@
        return (hash + (hash >> 5));
 }
 
+/*
+ * Find the end of the first path component in NAME and return its
+ * length.
+ */
+static size_t
+namei_getcomponent(const char *name)
+{
+       size_t pos;
+
+       pos = 0;
+       while (name[pos] != '\0' && name[pos] != '/') {
+               pos++;
+       }
+       return pos;
+}
+
 ////////////////////////////////////////////////////////////
 
 /*
@@ -806,7 +822,6 @@
        /*
         * Search a new directory.
         *
-        * The cn_hash value is for use by vfs_cache.
         * The last component of the filename is left accessible via
         * cnp->cn_nameptr for callers that need the name. Callers needing
         * the name set the SAVENAME flag. When done, they assume
@@ -816,9 +831,8 @@
         * is held and locked.
         */
        cnp->cn_consume = 0;
-       cp = NULL;
-       cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
-       cnp->cn_namelen = cp - cnp->cn_nameptr;
+       cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr);
+       cp = cnp->cn_nameptr + cnp->cn_namelen;
        if (cnp->cn_namelen > KERNEL_NAME_MAX) {
                return ENAMETOOLONG;
        }
@@ -1558,9 +1572,8 @@
        ndp->ni_dvp = NULL;
 
        cnp->cn_consume = 0;
-       cp = NULL;
-       cnp->cn_hash = namei_hash(cnp->cn_nameptr, &cp);
-       cnp->cn_namelen = cp - cnp->cn_nameptr;
+       cnp->cn_namelen = namei_getcomponent(cnp->cn_nameptr);
+       cp = cnp->cn_nameptr + cnp->cn_namelen;
        KASSERT(cnp->cn_namelen <= KERNEL_NAME_MAX);
        ndp->ni_pathlen -= cnp->cn_namelen;
        ndp->ni_next = cp;
@@ -1656,8 +1669,8 @@
        int rdonly;                     /* lookup read-only flag bit */
        int error = 0;
 #ifdef DEBUG
-       uint32_t newhash;               /* DEBUG: check name hash */
-       const char *cp;                 /* DEBUG: check name ptr/len */
+       size_t newlen;                  /* DEBUG: check name len */
+       const char *cp;                 /* DEBUG: check name ptr */
 #endif /* DEBUG */
 
        (void)dummy;
@@ -1677,12 +1690,16 @@
         * responsibility for freeing the pathname buffer.
         */
 #ifdef DEBUG
+#if 0
        cp = NULL;
        newhash = namei_hash(cnp->cn_nameptr, &cp);
        if ((uint32_t)newhash != (uint32_t)cnp->cn_hash)
                panic("relookup: bad hash");
-       if (cnp->cn_namelen != cp - cnp->cn_nameptr)
+#endif
+       newlen = nami_getcomponent(cnp->cn_nameptr);
+       if (cnp->cn_namelen != newlen)
                panic("relookup: bad len");
+       cp = cnp->cn_nameptr + cnp->cn_namelen;
        while (*cp == '/')
                cp++;
        if (*cp != 0)
diff -r cba39a555764 -r 42d43ac83fe1 sys/nfs/nfs_vnops.c
--- a/sys/nfs/nfs_vnops.c       Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/nfs/nfs_vnops.c       Mon Oct 15 05:06:00 2012 -0400
@@ -279,7 +279,7 @@
        if (!timespecisset(&dnp->n_nctime))
                dnp->n_nctime = dnp->n_vattr->va_mtime;
 
-       cache_enter(dvp, vp, cnp);
+       cache_enter(dvp, vp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
 }
 
 /*
@@ -780,6 +780,7 @@
        long len;
        nfsfh_t *fhp;
        struct nfsnode *np;
+       int cachefound;
        int error = 0, attrflag, fhsize;
        const int v3 = NFS_ISV3(dvp);
 
@@ -817,39 +818,35 @@
         * the time the cache entry has been created. If it has,
         * the cache entry has to be ignored.
         */
-       error = cache_lookup_raw(dvp, vpp, cnp);
+       cachefound = cache_lookup_raw(dvp, cnp->cn_nameptr, cnp->cn_namelen,
+                                     cnp->cn_flags, NULL, vpp);
        KASSERT(dvp != *vpp);
        KASSERT((cnp->cn_flags & ISWHITEOUT) == 0);
-       if (error >= 0) {
+       if (cachefound) {
                struct vattr vattr;
-               int err2;
 
-               if (error && error != ENOENT) {
+               error = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
+               if (error != 0) {
+                       if (*vpp != NULLVP)
+                               vrele(*vpp);
                        *vpp = NULLVP;
                        return error;
                }
 
-               err2 = VOP_ACCESS(dvp, VEXEC, cnp->cn_cred);
-               if (err2 != 0) {
-                       if (error == 0)
-                               vrele(*vpp);
-                       *vpp = NULLVP;
-                       return err2;
-               }
-
                if (VOP_GETATTR(dvp, &vattr, cnp->cn_cred)
                    || timespeccmp(&vattr.va_mtime,
                    &VTONFS(dvp)->n_nctime, !=)) {
-                       if (error == 0) {
+                       if (*vpp != NULLVP) {
                                vrele(*vpp);
                                *vpp = NULLVP;
                        }
-                       cache_purge1(dvp, NULL, PURGE_CHILDREN);
+                       cache_purge1(dvp, NULL, 0, PURGE_CHILDREN);
                        timespecclear(&np->n_nctime);
                        goto dorpc;
                }
 
-               if (error == ENOENT) {
+               if (*vpp == NULLVP) {
+                       /* namecache gave us a negative result */
                        goto noentry;
                }
 
@@ -877,7 +874,7 @@
                        KASSERT(newvp->v_type != VNON);
                        return (0);
                }
-               cache_purge1(newvp, NULL, PURGE_PARENTS);
+               cache_purge1(newvp, NULL, 0, PURGE_PARENTS);
                vput(newvp);
                *vpp = NULLVP;
        }
@@ -1581,7 +1578,7 @@
        error = nfs_mknodrpc(dvp, ap->a_vpp, cnp, ap->a_vap);
        VN_KNOTE(dvp, NOTE_WRITE);
        if (error == 0 || error == EEXIST)
-               cache_purge1(dvp, cnp, 0);
+               cache_purge1(dvp, cnp->cn_nameptr, cnp->cn_namelen, 0);
        return (error);
 }
 
@@ -1708,13 +1705,13 @@
                if (cnp->cn_flags & MAKEENTRY)
                        nfs_cache_enter(dvp, newvp, cnp);
                else
-                       cache_purge1(dvp, cnp, 0);
+                       cache_purge1(dvp, cnp->cn_nameptr, cnp->cn_namelen, 0);
                *ap->a_vpp = newvp;
        } else {
                if (newvp)
                        vput(newvp);
                if (error == EEXIST)
-                       cache_purge1(dvp, cnp, 0);
+                       cache_purge1(dvp, cnp->cn_nameptr, cnp->cn_namelen, 0);
        }
        VTONFS(dvp)->n_flag |= NMODIFIED;
        if (!wccflag)
@@ -1904,11 +1901,13 @@
                if (fvp->v_type == VDIR)
                        cache_purge(fvp);
                else
-                       cache_purge1(fdvp, fcnp, 0);
+                       cache_purge1(fdvp, fcnp->cn_nameptr, fcnp->cn_namelen,
+                                    0);
                if (tvp != NULL && tvp->v_type == VDIR)
                        cache_purge(tvp);
                else
-                       cache_purge1(tdvp, tcnp, 0);
+                       cache_purge1(tdvp, tcnp->cn_nameptr, tcnp->cn_namelen,
+                                    0);
        }
 out:
        if (tdvp == tvp)
@@ -2069,7 +2068,7 @@
            cnp->cn_cred, curlwp);
 
        if (error == 0) {
-               cache_purge1(dvp, cnp, 0);
+               cache_purge1(dvp, cnp->cn_nameptr, cnp->cn_namelen, 0);
        }
        VOP_UNLOCK(vp);
        VN_KNOTE(vp, NOTE_LINK);
@@ -2145,7 +2144,7 @@
        if (rexmit && error == EEXIST)
                error = 0;
        if (error == 0 || error == EEXIST)
-               cache_purge1(dvp, cnp, 0);
+               cache_purge1(dvp, cnp->cn_nameptr, cnp->cn_namelen, 0);
        if (error == 0 && newvp == NULL) {
                struct nfsnode *np = NULL;
 
@@ -2777,18 +2776,12 @@
                                        newvp = NFSTOV(np);
                                }
                                if (!error) {
-                                   const char *xcp;
-
                                    nfs_loadattrcache(&newvp, &fattr, 0, 0);
                                    if (bigenough) {
                                        dp->d_type =
                                           IFTODT(VTTOIF(np->n_vattr->va_type));
                                        if (cnp->cn_namelen <= NCHNAMLEN) {
                                            ndp->ni_vp = newvp;
-                                           xcp = cnp->cn_nameptr +
-                                               cnp->cn_namelen;
-                                           cnp->cn_hash =
-                                              namei_hash(cnp->cn_nameptr, 
&xcp);
                                            nfs_cache_enter(ndp->ni_dvp,
                                                ndp->ni_vp, cnp);
                                        }
diff -r cba39a555764 -r 42d43ac83fe1 sys/rump/include/rump/rump_namei.h
--- a/sys/rump/include/rump/rump_namei.h        Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/rump/include/rump/rump_namei.h        Mon Oct 15 05:06:00 2012 -0400
@@ -1,4 +1,4 @@
-/*     $NetBSD: rump_namei.h,v 1.18 2012/10/13 17:47:11 dholland Exp $ */
+/*     $NetBSD: gennameih.awk,v 1.5 2009/12/23 14:17:19 pooka Exp $    */
 
 
 /*
diff -r cba39a555764 -r 42d43ac83fe1 sys/rump/librump/rumpvfs/rump_vfs.c
--- a/sys/rump/librump/rumpvfs/rump_vfs.c       Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/rump/librump/rumpvfs/rump_vfs.c       Mon Oct 15 05:06:00 2012 -0400
@@ -184,7 +184,6 @@
 {
        struct rumpcn *rcn;
        struct componentname *cnp;
-       const char *cp = NULL;
 
        rcn = kmem_zalloc(sizeof(*rcn), KM_SLEEP);
        cnp = &rcn->rcn_cn;
@@ -197,7 +196,6 @@
        cnp->cn_flags = flags & (MODMASK | PARAMASK);
 
        cnp->cn_namelen = namelen;
-       cnp->cn_hash = namei_hash(name, &cp);
 
        cnp->cn_cred = creds;
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/sys/namei.h
--- a/sys/sys/namei.h   Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/sys/namei.h   Mon Oct 15 05:06:00 2012 -0400
@@ -1,4 +1,4 @@
-/*     $NetBSD: namei.h,v 1.82 2012/10/13 17:47:11 dholland Exp $      */
+/*     $NetBSD: gennameih.awk,v 1.5 2009/12/23 14:17:19 pooka Exp $    */
 
 
 /*
@@ -127,7 +127,6 @@
                 */
                const char      *cn_nameptr;    /* pointer to looked up name */
                size_t          cn_namelen;     /* length of looked up comp */
-               u_long          cn_hash;        /* hash val of looked up name */
                size_t          cn_consume;     /* chars to consume in lookup */
        } ni_cnd;
 };
@@ -268,15 +267,17 @@
 int    lookup_for_nfsd(struct nameidata *, struct vnode *, int neverfollow);
 int    lookup_for_nfsd_index(struct nameidata *, struct vnode *);
 int    relookup(struct vnode *, struct vnode **, struct componentname *, int);
-void   cache_purge1(struct vnode *, const struct componentname *, int);
+void   cache_purge1(struct vnode *, const char *, size_t, int);
 #define        PURGE_PARENTS   1
 #define        PURGE_CHILDREN  2
-#define        cache_purge(vp) cache_purge1((vp), NULL, 
PURGE_PARENTS|PURGE_CHILDREN)
-int    cache_lookup(struct vnode *, struct vnode **, struct componentname *);
-int    cache_lookup_raw(struct vnode *, struct vnode **,
-                        struct componentname *);
+#define        cache_purge(vp) 
cache_purge1((vp),NULL,0,PURGE_PARENTS|PURGE_CHILDREN)
+int    cache_lookup(struct vnode *, const char *, size_t, uint32_t, uint32_t,
+                       int *, struct vnode **);
+int    cache_lookup_raw(struct vnode *, const char *, size_t, uint32_t,
+                       int *, struct vnode **);
 int    cache_revlookup(struct vnode *, struct vnode **, char **, char *);
-void   cache_enter(struct vnode *, struct vnode *, struct componentname *);
+void   cache_enter(struct vnode *, struct vnode *,
+                       const char *, size_t, uint32_t);
 void   nchinit(void);
 void   nchreinit(void);
 void   cache_cpu_init(struct cpu_info *);
diff -r cba39a555764 -r 42d43ac83fe1 sys/sys/namei.src
--- a/sys/sys/namei.src Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/sys/namei.src Mon Oct 15 05:06:00 2012 -0400
@@ -119,7 +119,6 @@
                 */
                const char      *cn_nameptr;    /* pointer to looked up name */
                size_t          cn_namelen;     /* length of looked up comp */
-               u_long          cn_hash;        /* hash val of looked up name */
                size_t          cn_consume;     /* chars to consume in lookup */
        } ni_cnd;
 };
@@ -260,15 +259,17 @@
 int    lookup_for_nfsd(struct nameidata *, struct vnode *, int neverfollow);
 int    lookup_for_nfsd_index(struct nameidata *, struct vnode *);
 int    relookup(struct vnode *, struct vnode **, struct componentname *, int);
-void   cache_purge1(struct vnode *, const struct componentname *, int);
+void   cache_purge1(struct vnode *, const char *, size_t, int);
 #define        PURGE_PARENTS   1
 #define        PURGE_CHILDREN  2
-#define        cache_purge(vp) cache_purge1((vp), NULL, 
PURGE_PARENTS|PURGE_CHILDREN)
-int    cache_lookup(struct vnode *, struct vnode **, struct componentname *);
-int    cache_lookup_raw(struct vnode *, struct vnode **,
-                        struct componentname *);
+#define        cache_purge(vp) 
cache_purge1((vp),NULL,0,PURGE_PARENTS|PURGE_CHILDREN)
+int    cache_lookup(struct vnode *, const char *, size_t, uint32_t, uint32_t,
+                       int *, struct vnode **);
+int    cache_lookup_raw(struct vnode *, const char *, size_t, uint32_t,
+                       int *, struct vnode **);
 int    cache_revlookup(struct vnode *, struct vnode **, char **, char *);
-void   cache_enter(struct vnode *, struct vnode *, struct componentname *);
+void   cache_enter(struct vnode *, struct vnode *,
+                       const char *, size_t, uint32_t);
 void   nchinit(void);
 void   nchreinit(void);
 void   cache_cpu_init(struct cpu_info *);
diff -r cba39a555764 -r 42d43ac83fe1 sys/ufs/ext2fs/ext2fs_lookup.c
--- a/sys/ufs/ext2fs/ext2fs_lookup.c    Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/ufs/ext2fs/ext2fs_lookup.c    Mon Oct 15 05:06:00 2012 -0400
@@ -325,8 +325,10 @@
         * check the name cache to see if the directory/name pair
         * we are looking for is known already.
         */
-       if ((error = cache_lookup(vdp, vpp, cnp)) >= 0)
-               return (error);
+       if (cache_lookup(vdp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, NULL, vpp)) {
+               return *vpp == NULLVP ? ENOENT : 0;
+       }
 
        /*
         * Suppress search for slots unless creating
@@ -539,7 +541,8 @@
         * Insert name into cache (as non-existent) if appropriate.
         */
        if (nameiop != CREATE) {
-               cache_enter(vdp, *vpp, cnp);
+               cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
        }
        return ENOENT;
 
@@ -699,7 +702,7 @@
        /*
         * Insert name into cache if appropriate.
         */
-       cache_enter(vdp, *vpp, cnp);
+       cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
        return 0;
 }
 
diff -r cba39a555764 -r 42d43ac83fe1 sys/ufs/ufs/ufs_lookup.c
--- a/sys/ufs/ufs/ufs_lookup.c  Sun Oct 14 23:09:40 2012 -0400
+++ b/sys/ufs/ufs/ufs_lookup.c  Mon Oct 15 05:06:00 2012 -0400
@@ -153,6 +153,7 @@
        int dirblksiz = ump->um_dirblksiz;
        ino_t foundino;
        struct ufs_lookup_results *results;
+       int iswhiteout;                 /* temp result from cache_lookup() */
 
        flags = cnp->cn_flags;
 
@@ -186,8 +187,25 @@
         * check the name cache to see if the directory/name pair
         * we are looking for is known already.
         */
-       if ((error = cache_lookup(vdp, vpp, cnp)) >= 0) {
-               return (error);
+       if (cache_lookup(vdp, cnp->cn_nameptr, cnp->cn_namelen,
+                        cnp->cn_nameiop, cnp->cn_flags, &iswhiteout, vpp)) {
+               if (iswhiteout) {
+                       cnp->cn_flags |= ISWHITEOUT;
+               }
+               return *vpp == NULLVP ? ENOENT : 0;
+       }
+       if (iswhiteout) {
+               /*
+                * The namecache set iswhiteout without finding a
+                * cache entry. As of this writing (20121014), this
+                * can happen if there was a whiteout entry that has
+                * been invalidated by the lookup. It is not clear if
+                * it is correct to set ISWHITEOUT in this case or
+                * not; however, doing so retains the prior behavior,
+                * so we'll go with that until some clearer answer
+                * appears. XXX
+                */
+               cnp->cn_flags |= ISWHITEOUT;
        }
 
        fstrans_start(vdp->v_mount, FSTRANS_SHARED);
@@ -497,7 +515,8 @@
         * Insert name into cache (as non-existent) if appropriate.
         */
        if (nameiop != CREATE) {
-               cache_enter(vdp, *vpp, cnp);
+               cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen,
+                           cnp->cn_flags);
        }
        error = ENOENT;
        goto out;
@@ -661,7 +680,7 @@
        /*
         * Insert name into cache if appropriate.
         */
-       cache_enter(vdp, *vpp, cnp);
+       cache_enter(vdp, *vpp, cnp->cn_nameptr, cnp->cn_namelen, cnp->cn_flags);
        error = 0;
 
 out:


-- 
David A. Holland
dholland%netbsd.org@localhost



Home | Main Index | Thread Index | Old Index