Module Name:    src
Committed By:   dholland
Date:           Mon Nov  5 17:24:12 UTC 2012

Modified Files:
        src/sys/fs/adosfs: adlookup.c
        src/sys/fs/cd9660: cd9660_lookup.c
        src/sys/fs/efs: efs_vnops.c
        src/sys/fs/filecorefs: filecore_lookup.c
        src/sys/fs/msdosfs: msdosfs_lookup.c
        src/sys/fs/nilfs: nilfs_vnops.c
        src/sys/fs/ntfs: ntfs_vnops.c
        src/sys/fs/puffs: puffs_vnops.c
        src/sys/fs/smbfs: smbfs_vnops.c
        src/sys/fs/tmpfs: tmpfs_vnops.c
        src/sys/fs/udf: udf_vnops.c
        src/sys/fs/union: union.h union_subr.c
        src/sys/kern: vfs_cache.c vfs_getcwd.c vfs_lookup.c
        src/sys/nfs: nfs_vnops.c
        src/sys/rump/librump/rumpvfs: rump_vfs.c
        src/sys/sys: namei.src
        src/sys/ufs/chfs: chfs_vnops.c
        src/sys/ufs/ext2fs: ext2fs_lookup.c
        src/sys/ufs/ufs: ufs_lookup.c

Log Message:
Disentangle the namecache from the internals of namei.

 - Move the namecache's hash computation to inside the namecache code,
instead of being spread out all over the place. Remove cn_hash from
struct componentname and delete all uses of it.

 - It is no longer necessary (if it ever was) for cache_lookup and
cache_lookup_raw to clear MAKEENTRY from cnp->cn_flags for the cases
that cache_enter already checks for.

 - Rearrange the interface of cache_lookup (and cache_lookup_raw) to
make it somewhat simpler, to exclude certain nonexistent error
conditions, and (most importantly) to make it not require write access
to cnp->cn_flags.

This change requires a kernel bump.


To generate a diff of this commit:
cvs rdiff -u -r1.16 -r1.17 src/sys/fs/adosfs/adlookup.c
cvs rdiff -u -r1.20 -r1.21 src/sys/fs/cd9660/cd9660_lookup.c
cvs rdiff -u -r1.26 -r1.27 src/sys/fs/efs/efs_vnops.c
cvs rdiff -u -r1.14 -r1.15 src/sys/fs/filecorefs/filecore_lookup.c
cvs rdiff -u -r1.24 -r1.25 src/sys/fs/msdosfs/msdosfs_lookup.c
cvs rdiff -u -r1.18 -r1.19 src/sys/fs/nilfs/nilfs_vnops.c
cvs rdiff -u -r1.52 -r1.53 src/sys/fs/ntfs/ntfs_vnops.c
cvs rdiff -u -r1.174 -r1.175 src/sys/fs/puffs/puffs_vnops.c
cvs rdiff -u -r1.80 -r1.81 src/sys/fs/smbfs/smbfs_vnops.c
cvs rdiff -u -r1.98 -r1.99 src/sys/fs/tmpfs/tmpfs_vnops.c
cvs rdiff -u -r1.72 -r1.73 src/sys/fs/udf/udf_vnops.c
cvs rdiff -u -r1.23 -r1.24 src/sys/fs/union/union.h
cvs rdiff -u -r1.55 -r1.56 src/sys/fs/union/union_subr.c
cvs rdiff -u -r1.89 -r1.90 src/sys/kern/vfs_cache.c
cvs rdiff -u -r1.47 -r1.48 src/sys/kern/vfs_getcwd.c
cvs rdiff -u -r1.196 -r1.197 src/sys/kern/vfs_lookup.c
cvs rdiff -u -r1.295 -r1.296 src/sys/nfs/nfs_vnops.c
cvs rdiff -u -r1.67 -r1.68 src/sys/rump/librump/rumpvfs/rump_vfs.c
cvs rdiff -u -r1.27 -r1.28 src/sys/sys/namei.src
cvs rdiff -u -r1.11 -r1.12 src/sys/ufs/chfs/chfs_vnops.c
cvs rdiff -u -r1.70 -r1.71 src/sys/ufs/ext2fs/ext2fs_lookup.c
cvs rdiff -u -r1.118 -r1.119 src/sys/ufs/ufs/ufs_lookup.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/fs/adosfs/adlookup.c
diff -u src/sys/fs/adosfs/adlookup.c:1.16 src/sys/fs/adosfs/adlookup.c:1.17
--- src/sys/fs/adosfs/adlookup.c:1.16	Sun Jul 22 00:53:18 2012
+++ src/sys/fs/adosfs/adlookup.c	Mon Nov  5 17:24:09 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: adlookup.c,v 1.16 2012/07/22 00:53:18 rmind Exp $	*/
+/*	$NetBSD: adlookup.c,v 1.17 2012/11/05 17:24:09 dholland Exp $	*/
 
 /*
  * Copyright (c) 1994 Christian E. Hopps
@@ -32,7 +32,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: adlookup.c,v 1.16 2012/07/22 00:53:18 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: adlookup.c,v 1.17 2012/11/05 17:24:09 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -110,8 +110,9 @@ adosfs_lookup(void *v)
 	 * 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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	/*
 	 * fake a '.'

Index: src/sys/fs/cd9660/cd9660_lookup.c
diff -u src/sys/fs/cd9660/cd9660_lookup.c:1.20 src/sys/fs/cd9660/cd9660_lookup.c:1.21
--- src/sys/fs/cd9660/cd9660_lookup.c:1.20	Sun Jul 22 00:53:18 2012
+++ src/sys/fs/cd9660/cd9660_lookup.c	Mon Nov  5 17:24:09 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: cd9660_lookup.c,v 1.20 2012/07/22 00:53:18 rmind Exp $	*/
+/*	$NetBSD: cd9660_lookup.c,v 1.21 2012/11/05 17:24:09 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.20 2012/07/22 00:53:18 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: cd9660_lookup.c,v 1.21 2012/11/05 17:24:09 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -151,8 +151,9 @@ cd9660_lookup(void *v)
 	 * 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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	len = cnp->cn_namelen;
 	name = cnp->cn_nameptr;

Index: src/sys/fs/efs/efs_vnops.c
diff -u src/sys/fs/efs/efs_vnops.c:1.26 src/sys/fs/efs/efs_vnops.c:1.27
--- src/sys/fs/efs/efs_vnops.c:1.26	Sun Jul 22 00:53:19 2012
+++ src/sys/fs/efs/efs_vnops.c	Mon Nov  5 17:24:09 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: efs_vnops.c,v 1.26 2012/07/22 00:53:19 rmind Exp $	*/
+/*	$NetBSD: efs_vnops.c,v 1.27 2012/11/05 17:24:09 dholland Exp $	*/
 
 /*
  * Copyright (c) 2006 Stephen M. Rumble <rum...@ephemeral.org>
@@ -17,7 +17,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.26 2012/07/22 00:53:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: efs_vnops.c,v 1.27 2012/11/05 17:24:09 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -73,9 +73,9 @@ efs_lookup(void *v)
 	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, NULL, ap->a_vpp)) {
+		return *ap->a_vpp == NULLVP ? ENOENT : 0;
+	}
 
 	/*
 	 * Handle the three lookup types: '.', '..', and everything else.

Index: src/sys/fs/filecorefs/filecore_lookup.c
diff -u src/sys/fs/filecorefs/filecore_lookup.c:1.14 src/sys/fs/filecorefs/filecore_lookup.c:1.15
--- src/sys/fs/filecorefs/filecore_lookup.c:1.14	Sun Jul 22 00:53:19 2012
+++ src/sys/fs/filecorefs/filecore_lookup.c	Mon Nov  5 17:24:09 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: filecore_lookup.c,v 1.14 2012/07/22 00:53:19 rmind Exp $	*/
+/*	$NetBSD: filecore_lookup.c,v 1.15 2012/11/05 17:24:09 dholland Exp $	*/
 
 /*-
  * Copyright (c) 1989, 1993, 1994 The Regents of the University of California.
@@ -66,7 +66,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: filecore_lookup.c,v 1.14 2012/07/22 00:53:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: filecore_lookup.c,v 1.15 2012/11/05 17:24:09 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/namei.h>
@@ -169,8 +169,9 @@ filecore_lookup(void *v)
 	 * 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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	name = cnp->cn_nameptr;
 	namelen = cnp->cn_namelen;

Index: src/sys/fs/msdosfs/msdosfs_lookup.c
diff -u src/sys/fs/msdosfs/msdosfs_lookup.c:1.24 src/sys/fs/msdosfs/msdosfs_lookup.c:1.25
--- src/sys/fs/msdosfs/msdosfs_lookup.c:1.24	Sun Jul 22 00:53:19 2012
+++ src/sys/fs/msdosfs/msdosfs_lookup.c	Mon Nov  5 17:24:10 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: msdosfs_lookup.c,v 1.24 2012/07/22 00:53:19 rmind Exp $	*/
+/*	$NetBSD: msdosfs_lookup.c,v 1.25 2012/11/05 17:24:10 dholland Exp $	*/
 
 /*-
  * Copyright (C) 1994, 1995, 1997 Wolfgang Solfrank.
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.24 2012/07/22 00:53:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: msdosfs_lookup.c,v 1.25 2012/11/05 17:24:10 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -146,8 +146,9 @@ msdosfs_lookup(void *v)
 	 * 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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT: 0;
+	}
 
 	/*
 	 * If they are going after the . or .. entry in the root directory,

Index: src/sys/fs/nilfs/nilfs_vnops.c
diff -u src/sys/fs/nilfs/nilfs_vnops.c:1.18 src/sys/fs/nilfs/nilfs_vnops.c:1.19
--- src/sys/fs/nilfs/nilfs_vnops.c:1.18	Sun Jul 22 00:53:19 2012
+++ src/sys/fs/nilfs/nilfs_vnops.c	Mon Nov  5 17:24:10 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: nilfs_vnops.c,v 1.18 2012/07/22 00:53:19 rmind Exp $ */
+/* $NetBSD: nilfs_vnops.c,v 1.19 2012/11/05 17:24:10 dholland Exp $ */
 
 /*
  * Copyright (c) 2008, 2009 Reinoud Zandijk
@@ -28,7 +28,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.18 2012/07/22 00:53:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nilfs_vnops.c,v 1.19 2012/11/05 17:24:10 dholland Exp $");
 #endif /* not lint */
 
 
@@ -652,10 +652,10 @@ nilfs_lookup(void *v)
 
 	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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
 

Index: src/sys/fs/ntfs/ntfs_vnops.c
diff -u src/sys/fs/ntfs/ntfs_vnops.c:1.52 src/sys/fs/ntfs/ntfs_vnops.c:1.53
--- src/sys/fs/ntfs/ntfs_vnops.c:1.52	Sun Jul 22 00:53:19 2012
+++ src/sys/fs/ntfs/ntfs_vnops.c	Mon Nov  5 17:24:10 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ntfs_vnops.c,v 1.52 2012/07/22 00:53:19 rmind Exp $	*/
+/*	$NetBSD: ntfs_vnops.c,v 1.53 2012/11/05 17:24:10 dholland Exp $	*/
 
 /*
  * Copyright (c) 1992, 1993
@@ -36,7 +36,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.52 2012/07/22 00:53:19 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ntfs_vnops.c,v 1.53 2012/11/05 17:24:10 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -682,8 +682,9 @@ ntfs_lookup(void *v)
 	 * 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, 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",

Index: src/sys/fs/puffs/puffs_vnops.c
diff -u src/sys/fs/puffs/puffs_vnops.c:1.174 src/sys/fs/puffs/puffs_vnops.c:1.175
--- src/sys/fs/puffs/puffs_vnops.c:1.174	Fri Aug 10 16:49:35 2012
+++ src/sys/fs/puffs/puffs_vnops.c	Mon Nov  5 17:24:10 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: puffs_vnops.c,v 1.174 2012/08/10 16:49:35 manu Exp $	*/
+/*	$NetBSD: puffs_vnops.c,v 1.175 2012/11/05 17:24:10 dholland Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007  Antti Kantee.  All Rights Reserved.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.174 2012/08/10 16:49:35 manu Exp $");
+__KERNEL_RCSID(0, "$NetBSD: puffs_vnops.c,v 1.175 2012/11/05 17:24:10 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -526,9 +526,14 @@ puffs_vnop_lookup(void *v)
 	 * Check if someone fed it into the cache
 	 */
 	if (!isdot && PUFFS_USE_NAMECACHE(pmp)) {
-		error = cache_lookup(dvp, ap->a_vpp, cnp);
+		int found, iswhiteout;
 
-		if ((error == 0) && PUFFS_USE_FS_TTL(pmp)) {
+		found = cache_lookup(dvp, cnp, &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 +545,7 @@ puffs_vnop_lookup(void *v)
 				 * successful lookup. 
 				 */
 				*ap->a_vpp = NULL;
-				error = -1;
+				found = 0;
 			}
 		}
 
@@ -548,11 +553,20 @@ puffs_vnop_lookup(void *v)
 		 * Do not use negative caching, since the filesystem
 		 * provides no TTL for it.
 		 */
-		if ((error == ENOENT) && PUFFS_USE_FS_TTL(pmp))
-			error = -1;
+		if (found && *ap->a_vpp == NULLVP && PUFFS_USE_FS_TTL(pmp))
+			found = 0;
 
-		if (error >= 0)
-			return error;
+		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) {

Index: src/sys/fs/smbfs/smbfs_vnops.c
diff -u src/sys/fs/smbfs/smbfs_vnops.c:1.80 src/sys/fs/smbfs/smbfs_vnops.c:1.81
--- src/sys/fs/smbfs/smbfs_vnops.c:1.80	Sun Jul 22 00:53:20 2012
+++ src/sys/fs/smbfs/smbfs_vnops.c	Mon Nov  5 17:24:10 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: smbfs_vnops.c,v 1.80 2012/07/22 00:53:20 rmind Exp $	*/
+/*	$NetBSD: smbfs_vnops.c,v 1.81 2012/11/05 17:24:10 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2003 The NetBSD Foundation, Inc.
@@ -64,7 +64,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.80 2012/07/22 00:53:20 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: smbfs_vnops.c,v 1.81 2012/11/05 17:24:10 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1202,29 +1202,23 @@ smbfs_lookup(void *v)
 	 * 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, 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;

Index: src/sys/fs/tmpfs/tmpfs_vnops.c
diff -u src/sys/fs/tmpfs/tmpfs_vnops.c:1.98 src/sys/fs/tmpfs/tmpfs_vnops.c:1.99
--- src/sys/fs/tmpfs/tmpfs_vnops.c:1.98	Sun Jul 22 00:53:21 2012
+++ src/sys/fs/tmpfs/tmpfs_vnops.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: tmpfs_vnops.c,v 1.98 2012/07/22 00:53:21 rmind Exp $	*/
+/*	$NetBSD: tmpfs_vnops.c,v 1.99 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*
  * Copyright (c) 2005, 2006, 2007 The NetBSD Foundation, Inc.
@@ -35,7 +35,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.98 2012/07/22 00:53:21 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: tmpfs_vnops.c,v 1.99 2012/11/05 17:24:11 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/dirent.h>
@@ -133,6 +133,7 @@ tmpfs_lookup(void *v)
 	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,16 @@ tmpfs_lookup(void *v)
 	 * 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, &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;
 	}
 

Index: src/sys/fs/udf/udf_vnops.c
diff -u src/sys/fs/udf/udf_vnops.c:1.72 src/sys/fs/udf/udf_vnops.c:1.73
--- src/sys/fs/udf/udf_vnops.c:1.72	Sun Jul 22 00:53:21 2012
+++ src/sys/fs/udf/udf_vnops.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: udf_vnops.c,v 1.72 2012/07/22 00:53:21 rmind Exp $ */
+/* $NetBSD: udf_vnops.c,v 1.73 2012/11/05 17:24:11 dholland Exp $ */
 
 /*
  * Copyright (c) 2006, 2008 Reinoud Zandijk
@@ -32,7 +32,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.72 2012/07/22 00:53:21 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: udf_vnops.c,v 1.73 2012/11/05 17:24:11 dholland Exp $");
 #endif /* not lint */
 
 
@@ -687,10 +687,10 @@ udf_lookup(void *v)
 
 	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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	DPRINTF(LOOKUP, ("\tNOT found in cache\n"));
 

Index: src/sys/fs/union/union.h
diff -u src/sys/fs/union/union.h:1.23 src/sys/fs/union/union.h:1.24
--- src/sys/fs/union/union.h:1.23	Wed Nov 23 19:39:11 2011
+++ src/sys/fs/union/union.h	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: union.h,v 1.23 2011/11/23 19:39:11 hannken Exp $	*/
+/*	$NetBSD: union.h,v 1.24 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*
  * Copyright (c) 1994 The Regents of the University of California.
@@ -126,7 +126,6 @@ struct union_node {
 	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 */

Index: src/sys/fs/union/union_subr.c
diff -u src/sys/fs/union/union_subr.c:1.55 src/sys/fs/union/union_subr.c:1.56
--- src/sys/fs/union/union_subr.c:1.55	Fri Nov 25 11:19:10 2011
+++ src/sys/fs/union/union_subr.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: union_subr.c,v 1.55 2011/11/25 11:19:10 hannken Exp $	*/
+/*	$NetBSD: union_subr.c,v 1.56 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*
  * Copyright (c) 1994
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.55 2011/11/25 11:19:10 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: union_subr.c,v 1.56 2012/11/05 17:24:11 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -105,7 +105,7 @@ static u_long uhash_mask;		/* size of ha
 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 @@ found:
 		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 @@ found:
 	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 @@ union_copyup(struct union_node *un, int 
  */
 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 @@ union_do_lookup(struct vnode *dvp, struc
 	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 @@ union_mkshadow(struct union_mount *um, s
 	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 @@ union_mkwhiteout(struct union_mount *um,
 
 	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 @@ union_vn_create(struct vnode **vpp, stru
 	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 @@ union_check_rmdir(struct union_node *un,
 			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;

Index: src/sys/kern/vfs_cache.c
diff -u src/sys/kern/vfs_cache.c:1.89 src/sys/kern/vfs_cache.c:1.90
--- src/sys/kern/vfs_cache.c:1.89	Sun Jul 22 00:53:18 2012
+++ src/sys/kern/vfs_cache.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_cache.c,v 1.89 2012/07/22 00:53:18 rmind Exp $	*/
+/*	$NetBSD: vfs_cache.c,v 1.90 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
@@ -58,7 +58,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.89 2012/07/22 00:53:18 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_cache.c,v 1.90 2012/11/05 17:24:11 dholland Exp $");
 
 #include "opt_ddb.h"
 #include "opt_revcache.h"
@@ -109,6 +109,16 @@ struct nchcpu {
 };
 
 /*
+ * 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 TAILQ_HEAD(, namecache) nclruhead
 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;
@@ -160,6 +170,21 @@ static int cache_ctor(void *, void *, in
 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 struct componentname *cnp)
+{
+	const char *endptr;
+
+	endptr = cnp->cn_nameptr + cnp->cn_namelen;
+	return namei_hash(cnp->cn_nameptr, &endptr);
+}
+
+/*
  * Invalidate a cache entry and enqueue it for garbage collection.
  */
 static void
@@ -261,9 +286,11 @@ cache_lookup_entry(const struct vnode *d
 {
 	struct nchashhead *ncpp;
 	struct namecache *ncp;
+	nchash_t hash;
 
 	KASSERT(dvp != NULL);
-	ncpp = &nchashtbl[NCHASH(cnp, dvp)];
+	hash = cache_hash(cnp);
+	ncpp = &nchashtbl[NCHASH2(hash, dvp)];
 
 	LIST_FOREACH(ncp, ncpp, nc_hash) {
 		if (ncp->nc_dvp != dvp ||
@@ -288,45 +315,83 @@ cache_lookup_entry(const struct vnode *d
  * 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 struct componentname *cnp,
+	     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)) {
 		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);
 	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) {
 		COUNT(cpup->cpu_stats, ncs_badhits);
@@ -338,20 +403,28 @@ cache_lookup(struct vnode *dvp, struct v
 		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;
+		/* 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);
+			/*cnp->cn_flags |= ncp->nc_flags;*/
+			*iswht_ret = (ncp->nc_flags & ISWHITEOUT) != 0;
+		} else {
+			KASSERT(ncp->nc_flags == 0);
+		}
+
 		if (__predict_true(cnp->cn_nameiop != CREATE ||
 		    (cnp->cn_flags & 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_lookup(struct vnode *dvp, struct v
 			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 @@ cache_lookup(struct vnode *dvp, struct v
 			 * XXX badhits?
 			 */
 			COUNT(cpup->cpu_stats, ncs_falsehits);
-			*vpp = NULL;
-			return -1;
+			/* found nothing */
+			return 0;
 		}
 	}
 
@@ -411,61 +484,72 @@ cache_lookup(struct vnode *dvp, struct v
 	 * 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 struct componentname *cnp,
+		 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)) {
 		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);
 	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 +566,17 @@ cache_lookup_raw(struct vnode *dvp, stru
 			 * 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;
 }
 
 /*
@@ -590,6 +676,7 @@ cache_enter(struct vnode *dvp, struct vn
 	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 ||
@@ -645,7 +732,8 @@ cache_enter(struct vnode *dvp, struct vn
 	ncp->nc_nlen = cnp->cn_namelen;
 	memcpy(ncp->nc_name, cnp->cn_nameptr, (unsigned)ncp->nc_nlen);
 	TAILQ_INSERT_TAIL(&nclruhead, ncp, nc_lru);
-	ncpp = &nchashtbl[NCHASH(cnp, dvp)];
+	hash = cache_hash(cnp);
+	ncpp = &nchashtbl[NCHASH2(hash, dvp)];
 
 	/*
 	 * Flush updates before making visible in table.  No need for a

Index: src/sys/kern/vfs_getcwd.c
diff -u src/sys/kern/vfs_getcwd.c:1.47 src/sys/kern/vfs_getcwd.c:1.48
--- src/sys/kern/vfs_getcwd.c:1.47	Tue Nov 30 10:30:02 2010
+++ src/sys/kern/vfs_getcwd.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/* $NetBSD: vfs_getcwd.c,v 1.47 2010/11/30 10:30:02 dholland Exp $ */
+/* $NetBSD: vfs_getcwd.c,v 1.48 2012/11/05 17:24:11 dholland Exp $ */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.47 2010/11/30 10:30:02 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_getcwd.c,v 1.48 2012/11/05 17:24:11 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -130,7 +130,6 @@ getcwd_scandir(struct vnode **lvpp, stru
 	cn.cn_cred = cred;
 	cn.cn_nameptr = "..";
 	cn.cn_namelen = 2;
-	cn.cn_hash = 0;
 	cn.cn_consume = 0;
 
 	/*

Index: src/sys/kern/vfs_lookup.c
diff -u src/sys/kern/vfs_lookup.c:1.196 src/sys/kern/vfs_lookup.c:1.197
--- src/sys/kern/vfs_lookup.c:1.196	Sat Oct 13 17:46:50 2012
+++ src/sys/kern/vfs_lookup.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: vfs_lookup.c,v 1.196 2012/10/13 17:46:50 dholland Exp $	*/
+/*	$NetBSD: vfs_lookup.c,v 1.197 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*
  * Copyright (c) 1982, 1986, 1989, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.196 2012/10/13 17:46:50 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: vfs_lookup.c,v 1.197 2012/11/05 17:24:11 dholland Exp $");
 
 #include "opt_magiclinks.h"
 
@@ -195,7 +195,7 @@ symlink_magic(struct proc *p, char *cp, 
 ////////////////////////////////////////////////////////////
 
 /*
- * 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 @@ namei_hash(const char *name, const char 
 	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 @@ lookup_parsepath(struct namei_state *sta
 	/*
 	 * 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 @@ lookup_parsepath(struct namei_state *sta
 	 * 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 @@ do_lookup_for_nfsd_index(struct namei_st
 	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 @@ relookup(struct vnode *dvp, struct vnode
 	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 @@ relookup(struct vnode *dvp, struct vnode
 	 * 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)

Index: src/sys/nfs/nfs_vnops.c
diff -u src/sys/nfs/nfs_vnops.c:1.295 src/sys/nfs/nfs_vnops.c:1.296
--- src/sys/nfs/nfs_vnops.c:1.295	Sun Jul 22 00:53:21 2012
+++ src/sys/nfs/nfs_vnops.c	Mon Nov  5 17:24:11 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: nfs_vnops.c,v 1.295 2012/07/22 00:53:21 rmind Exp $	*/
+/*	$NetBSD: nfs_vnops.c,v 1.296 2012/11/05 17:24:11 dholland Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -39,7 +39,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.295 2012/07/22 00:53:21 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: nfs_vnops.c,v 1.296 2012/11/05 17:24:11 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_nfs.h"
@@ -780,6 +780,7 @@ nfs_lookup(void *v)
 	long len;
 	nfsfh_t *fhp;
 	struct nfsnode *np;
+	int cachefound;
 	int error = 0, attrflag, fhsize;
 	const int v3 = NFS_ISV3(dvp);
 
@@ -817,30 +818,24 @@ nfs_lookup(void *v)
 	 * 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, 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) {
-			*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)
 				vrele(*vpp);
 			*vpp = NULLVP;
-			return err2;
+			return error;
 		}
 
 		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;
 			}
@@ -849,7 +844,8 @@ nfs_lookup(void *v)
 			goto dorpc;
 		}
 
-		if (error == ENOENT) {
+		if (*vpp == NULLVP) {
+			/* namecache gave us a negative result */
 			goto noentry;
 		}
 
@@ -2777,18 +2773,12 @@ nfs_readdirplusrpc(struct vnode *vp, str
 					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);
 					}

Index: src/sys/rump/librump/rumpvfs/rump_vfs.c
diff -u src/sys/rump/librump/rumpvfs/rump_vfs.c:1.67 src/sys/rump/librump/rumpvfs/rump_vfs.c:1.68
--- src/sys/rump/librump/rumpvfs/rump_vfs.c:1.67	Mon Jul  4 11:31:37 2011
+++ src/sys/rump/librump/rumpvfs/rump_vfs.c	Mon Nov  5 17:24:12 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: rump_vfs.c,v 1.67 2011/07/04 11:31:37 mrg Exp $	*/
+/*	$NetBSD: rump_vfs.c,v 1.68 2012/11/05 17:24:12 dholland Exp $	*/
 
 /*
  * Copyright (c) 2008 Antti Kantee.  All Rights Reserved.
@@ -29,7 +29,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.67 2011/07/04 11:31:37 mrg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rump_vfs.c,v 1.68 2012/11/05 17:24:12 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/buf.h>
@@ -184,7 +184,6 @@ rump_makecn(u_long nameiop, u_long flags
 {
 	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 @@ rump_makecn(u_long nameiop, u_long flags
 	cnp->cn_flags = flags & (MODMASK | PARAMASK);
 
 	cnp->cn_namelen = namelen;
-	cnp->cn_hash = namei_hash(name, &cp);
 
 	cnp->cn_cred = creds;
 

Index: src/sys/sys/namei.src
diff -u src/sys/sys/namei.src:1.27 src/sys/sys/namei.src:1.28
--- src/sys/sys/namei.src:1.27	Sat Oct 13 17:46:50 2012
+++ src/sys/sys/namei.src	Mon Nov  5 17:24:09 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: namei.src,v 1.27 2012/10/13 17:46:50 dholland Exp $	*/
+/*	$NetBSD: namei.src,v 1.28 2012/11/05 17:24:09 dholland Exp $	*/
 
 /*
  * Copyright (c) 1985, 1989, 1991, 1993
@@ -119,7 +119,6 @@ struct nameidata {
 		 */
 		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;
 };
@@ -264,9 +263,10 @@ void	cache_purge1(struct vnode *, const 
 #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 *);
+int	cache_lookup(struct vnode *, const struct componentname *,
+			int *, struct vnode **);
+int	cache_lookup_raw(struct vnode *, const struct componentname *,
+			int *, struct vnode **);
 int	cache_revlookup(struct vnode *, struct vnode **, char **, char *);
 void	cache_enter(struct vnode *, struct vnode *, struct componentname *);
 void	nchinit(void);

Index: src/sys/ufs/chfs/chfs_vnops.c
diff -u src/sys/ufs/chfs/chfs_vnops.c:1.11 src/sys/ufs/chfs/chfs_vnops.c:1.12
--- src/sys/ufs/chfs/chfs_vnops.c:1.11	Fri Oct 19 12:44:39 2012
+++ src/sys/ufs/chfs/chfs_vnops.c	Mon Nov  5 17:24:12 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: chfs_vnops.c,v 1.11 2012/10/19 12:44:39 ttoth Exp $	*/
+/*	$NetBSD: chfs_vnops.c,v 1.12 2012/11/05 17:24:12 dholland Exp $	*/
 
 /*-
  * Copyright (c) 2010 Department of Software Engineering,
@@ -86,8 +86,8 @@ chfs_lookup(void *v)
 
 	/* 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) {
+	if (cache_lookup(dvp, cnp, NULL, vpp)) {
+		error = *vpp == NULLVP ? ENOENT : 0;
 		goto out;
 	}
 

Index: src/sys/ufs/ext2fs/ext2fs_lookup.c
diff -u src/sys/ufs/ext2fs/ext2fs_lookup.c:1.70 src/sys/ufs/ext2fs/ext2fs_lookup.c:1.71
--- src/sys/ufs/ext2fs/ext2fs_lookup.c:1.70	Sun Jul 22 00:53:22 2012
+++ src/sys/ufs/ext2fs/ext2fs_lookup.c	Mon Nov  5 17:24:12 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ext2fs_lookup.c,v 1.70 2012/07/22 00:53:22 rmind Exp $	*/
+/*	$NetBSD: ext2fs_lookup.c,v 1.71 2012/11/05 17:24:12 dholland Exp $	*/
 
 /*
  * Modified for NetBSD 1.2E
@@ -48,7 +48,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.70 2012/07/22 00:53:22 rmind Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ext2fs_lookup.c,v 1.71 2012/11/05 17:24:12 dholland Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -325,8 +325,9 @@ ext2fs_lookup(void *v)
 	 * 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, NULL, vpp)) {
+		return *vpp == NULLVP ? ENOENT : 0;
+	}
 
 	/*
 	 * Suppress search for slots unless creating

Index: src/sys/ufs/ufs/ufs_lookup.c
diff -u src/sys/ufs/ufs/ufs_lookup.c:1.118 src/sys/ufs/ufs/ufs_lookup.c:1.119
--- src/sys/ufs/ufs/ufs_lookup.c:1.118	Sun Oct 14 23:57:32 2012
+++ src/sys/ufs/ufs/ufs_lookup.c	Mon Nov  5 17:24:12 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: ufs_lookup.c,v 1.118 2012/10/14 23:57:32 dholland Exp $	*/
+/*	$NetBSD: ufs_lookup.c,v 1.119 2012/11/05 17:24:12 dholland Exp $	*/
 
 /*
  * Copyright (c) 1989, 1993
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.118 2012/10/14 23:57:32 dholland Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ufs_lookup.c,v 1.119 2012/11/05 17:24:12 dholland Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_ffs.h"
@@ -153,6 +153,7 @@ ufs_lookup(void *v)
 	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,24 @@ ufs_lookup(void *v)
 	 * 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, &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);

Reply via email to