tech-kern archive

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

Re: excising struct componentname from the namecache



On Mon, Oct 15, 2012 at 11:10 AM, David Holland
<dholland-tech%netbsd.org@localhost> wrote:
> 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.

Can you fix zfs, too ? Or I can fix it after your commit.

http://nxr.netbsd.org/xref/src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c#zfs_lookup
http://nxr.netbsd.org/xref/src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c#1367
http://nxr.netbsd.org/xref/src/external/cddl/osnet/dist/uts/common/fs/zfs/zfs_vnops.c#1371

>
> 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
>



-- 


Regards.

Adam


Home | Main Index | Thread Index | Old Index