summaryrefslogtreecommitdiffstats
path: root/sys/kern/vfs_cache.c
diff options
context:
space:
mode:
authorkan <kan@FreeBSD.org>2009-04-11 20:23:08 +0000
committerkan <kan@FreeBSD.org>2009-04-11 20:23:08 +0000
commitcae135c4892f809b3e59f64a6973447bcd1fc8e3 (patch)
tree2ac324866c519ce6ae282937a2676fc634355796 /sys/kern/vfs_cache.c
parentdc6531d9b1b6ce55370a4cee6183aa644690daf2 (diff)
downloadFreeBSD-src-cae135c4892f809b3e59f64a6973447bcd1fc8e3.zip
FreeBSD-src-cae135c4892f809b3e59f64a6973447bcd1fc8e3.tar.gz
Fix v_cache_dd handling for negative entries. v_cache_dd pointer was
not populated in parent directory if negative entry was being created, yet entry itself was added to the nc_neg list. It was possible for parent vnode to get discarded later, leaving negative entry pointing to now unused memory block. Reported by: dho Revewed by: kib
Diffstat (limited to 'sys/kern/vfs_cache.c')
-rw-r--r--sys/kern/vfs_cache.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 8210126..3c81b01 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -678,14 +678,19 @@ cache_enter(dvp, vp, cnp)
}
}
- /*
- * See if we are trying to add .. entry, but some other lookup
- * has populated v_cache_dd pointer already.
- */
- if (flag == NCF_ISDOTDOT && dvp->v_cache_dd != NULL) {
- CACHE_WUNLOCK();
- cache_free(ncp);
- return;
+ if (flag == NCF_ISDOTDOT) {
+ /*
+ * See if we are trying to add .. entry, but some other lookup
+ * has populated v_cache_dd pointer already.
+ */
+ if (dvp->v_cache_dd != NULL) {
+ CACHE_WUNLOCK();
+ cache_free(ncp);
+ return;
+ }
+ KASSERT(vp == NULL || vp->v_type == VDIR,
+ ("wrong vnode type %p", vp));
+ dvp->v_cache_dd = ncp;
}
numcache++;
@@ -694,11 +699,7 @@ cache_enter(dvp, vp, cnp)
if (cnp->cn_flags & ISWHITEOUT)
ncp->nc_flag |= NCF_WHITE;
} else if (vp->v_type == VDIR) {
- if (flag == NCF_ISDOTDOT) {
- KASSERT(dvp->v_cache_dd == NULL,
- ("dangling v_cache_dd"));
- dvp->v_cache_dd = ncp;
- } else {
+ if (flag != NCF_ISDOTDOT) {
if ((n2 = vp->v_cache_dd) != NULL &&
(n2->nc_flag & NCF_ISDOTDOT) != 0)
cache_zap(n2);
OpenPOWER on IntegriCloud