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