summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2008-12-02 11:14:16 +0000
committerkib <kib@FreeBSD.org>2008-12-02 11:14:16 +0000
commitade687809e3b9101f41cc7ab57fee5e8056b7381 (patch)
treed57df84f655910548dc7374f175a80aa821348aa /sys
parent294fd952b08d1539c3c5e977e156c2cb45f0878a (diff)
downloadFreeBSD-src-ade687809e3b9101f41cc7ab57fee5e8056b7381.zip
FreeBSD-src-ade687809e3b9101f41cc7ab57fee5e8056b7381.tar.gz
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
Diffstat (limited to 'sys')
-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 d6937b7..c7f25b9 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) {
OpenPOWER on IntegriCloud