diff options
author | John Baldwin <jhb@FreeBSD.org> | 2008-08-23 15:13:39 +0000 |
---|---|---|
committer | John Baldwin <jhb@FreeBSD.org> | 2008-08-23 15:13:39 +0000 |
commit | 969bf150dfc7e1a09194d586925a53a1a3ebe5e3 (patch) | |
tree | 51575aaf4ef8534a1b81dad22155e1e1b4b55567 /sys/kern/vfs_cache.c | |
parent | 78d22f42a8cbf28d830117e7432990e1dc8a61e0 (diff) | |
download | src-969bf150dfc7e1a09194d586925a53a1a3ebe5e3.tar.gz src-969bf150dfc7e1a09194d586925a53a1a3ebe5e3.zip |
Notes
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r-- | sys/kern/vfs_cache.c | 42 |
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)) { |