svn commit: r185894 - in stable/6/sys: . kern

John Baldwin jhb at FreeBSD.org
Wed Dec 10 14:50:12 PST 2008


Author: jhb
Date: Wed Dec 10 22:50:11 2008
New Revision: 185894
URL: http://svn.freebsd.org/changeset/base/185894

Log:
  MFC: Check for duplicate attempts to add the same positive entry to the
  name cache.  If a duplicate attempt is made, just do nothing.  This fixes
  a race with shared locking in pathname lockups.

Modified:
  stable/6/sys/   (props changed)
  stable/6/sys/kern/vfs_cache.c

Modified: stable/6/sys/kern/vfs_cache.c
==============================================================================
--- stable/6/sys/kern/vfs_cache.c	Wed Dec 10 22:17:09 2008	(r185893)
+++ stable/6/sys/kern/vfs_cache.c	Wed Dec 10 22:50:11 2008	(r185894)
@@ -511,8 +511,39 @@ cache_enter(dvp, vp, cnp)
 
 	hold = 0;
 	zap = 0;
+
+	/*
+	 * Calculate the hash key and setup as much of the new
+	 * namecache entry as possible before acquiring the lock.
+	 */
 	ncp = cache_alloc(cnp->cn_namelen);
+	ncp->nc_vp = vp;
+	ncp->nc_dvp = dvp;
+	len = ncp->nc_nlen = cnp->cn_namelen;
+	hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
+	bcopy(cnp->cn_nameptr, ncp->nc_name, len);
+	hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
 	CACHE_LOCK();
+
+	/*
+	 * See if this vnode is already in the cache with this name.
+	 * This can happen with concurrent lookups of the same path
+	 * name.
+	 */
+	if (vp) {
+		struct namecache *n2;
+
+		TAILQ_FOREACH(n2, &vp->v_cache_dst, nc_dst) {
+			if (n2->nc_dvp == dvp &&
+			    n2->nc_nlen == cnp->cn_namelen &&
+			    !bcmp(n2->nc_name, cnp->cn_nameptr, n2->nc_nlen)) {
+				CACHE_UNLOCK();
+				cache_free(ncp);
+				return;
+			}
+		}
+	}	
+
 	numcache++;
 	if (!vp) {
 		numneg++;
@@ -524,16 +555,9 @@ cache_enter(dvp, vp, cnp)
 	}
 
 	/*
-	 * Set the rest of the namecache entry elements, calculate it's
-	 * hash key and insert it into the appropriate chain within
-	 * the cache entries table.
+	 * Insert the new namecache entry into the appropriate chain
+	 * within the cache entries table.
 	 */
-	ncp->nc_vp = vp;
-	ncp->nc_dvp = dvp;
-	len = ncp->nc_nlen = cnp->cn_namelen;
-	hash = fnv_32_buf(cnp->cn_nameptr, len, FNV1_32_INIT);
-	bcopy(cnp->cn_nameptr, ncp->nc_name, len);
-	hash = fnv_32_buf(&dvp, sizeof(dvp), hash);
 	ncpp = NCHHASH(hash);
 	LIST_INSERT_HEAD(ncpp, ncp, nc_hash);
 	if (LIST_EMPTY(&dvp->v_cache_src)) {


More information about the svn-src-stable-6 mailing list