aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authorJohn Baldwin <jhb@FreeBSD.org>2008-08-23 15:13:39 +0000
committerJohn Baldwin <jhb@FreeBSD.org>2008-08-23 15:13:39 +0000
commit969bf150dfc7e1a09194d586925a53a1a3ebe5e3 (patch)
tree51575aaf4ef8534a1b81dad22155e1e1b4b55567 /sys/kern/vfs_cache.c
parent78d22f42a8cbf28d830117e7432990e1dc8a61e0 (diff)
downloadsrc-969bf150dfc7e1a09194d586925a53a1a3ebe5e3.tar.gz
src-969bf150dfc7e1a09194d586925a53a1a3ebe5e3.zip
Notes
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c42
1 files changed, 33 insertions, 9 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index e916500ea013..96d2f2944c10 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -500,8 +500,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++;
@@ -513,16 +544,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)) {