aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2008-12-02 11:14:16 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2008-12-02 11:14:16 +0000
commitd6568724e10481f07d2ebf26fc8e72fb2e258842 (patch)
treed57df84f655910548dc7374f175a80aa821348aa
parentffdaeffe217161b6c59f7d80f4db866106dfc2fb (diff)
downloadsrc-d6568724e10481f07d2ebf26fc8e72fb2e258842.tar.gz
src-d6568724e10481f07d2ebf26fc8e72fb2e258842.zip
Shared lookup makes it possible to create several negative cache
entries for one name. Then, creating inode with that name would remove one entry, leaving others dormant. Reclaiming the vnode would uncover negative entries, causing false return of ENOENT from the calls like stat, that do not create inode. Prevent creation of the duplicated negative entries. Reported and debugged with: pho Reviewed by: jhb X-MFC: after shared lookup changes
Notes
Notes: svn path=/head/; revision=185557
-rw-r--r--sys/kern/vfs_cache.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index d6937b7ca64e..c7f25b99a7fb 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -474,7 +474,7 @@ cache_enter(dvp, vp, cnp)
struct vnode *vp;
struct componentname *cnp;
{
- struct namecache *ncp;
+ struct namecache *ncp, *n2;
struct nchashhead *ncpp;
u_int32_t hash;
int hold;
@@ -530,8 +530,6 @@ cache_enter(dvp, vp, cnp)
* 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 &&
@@ -541,7 +539,16 @@ cache_enter(dvp, vp, cnp)
return;
}
}
- }
+ } else {
+ TAILQ_FOREACH(n2, &ncneg, nc_dst) {
+ if (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) {