svn commit: r183732 - in stable/7/sys: . kern
John Baldwin
jhb at FreeBSD.org
Thu Oct 9 20:40:12 UTC 2008
Author: jhb
Date: Thu Oct 9 20:40:11 2008
New Revision: 183732
URL: http://svn.freebsd.org/changeset/base/183732
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.
Approved by: re (kib)
Modified:
stable/7/sys/ (props changed)
stable/7/sys/kern/vfs_cache.c
Modified: stable/7/sys/kern/vfs_cache.c
==============================================================================
--- stable/7/sys/kern/vfs_cache.c Thu Oct 9 20:09:56 2008 (r183731)
+++ stable/7/sys/kern/vfs_cache.c Thu Oct 9 20:40:11 2008 (r183732)
@@ -496,8 +496,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++;
@@ -509,16 +540,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-all
mailing list