summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authorbp <bp@FreeBSD.org>2000-09-17 07:26:42 +0000
committerbp <bp@FreeBSD.org>2000-09-17 07:26:42 +0000
commit02544af7d4181c17b4280094d740b15516c89895 (patch)
tree6acabed362022c7dc8884295f86728d8a26966b5 /sys/kern
parente785331769023a37dd8b665cd89d2937f9b417f6 (diff)
downloadFreeBSD-src-02544af7d4181c17b4280094d740b15516c89895.zip
FreeBSD-src-02544af7d4181c17b4280094d740b15516c89895.tar.gz
Add new flag PDIRUNLOCK to the component.cn_flags which should be set by
filesystem lookup() routine if it unlocks parent directory. This flag should be carefully tracked by filesystems if they want to work properly with nullfs and other stacked filesystems. VFS takes advantage of this flag to perform symantically correct usage of vrele() instead of vput() if parent directory already unlocked. If filesystem fails to track this flag then previous codepath in VFS left unchanged. Convert UFS code to set PDIRUNLOCK flag if necessary. Other filesystmes will be changed after some period of testing. Reviewed in general by: mckusick, dillon, adrian Obtained from: NetBSD
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/vfs_cache.c25
-rw-r--r--sys/kern/vfs_lookup.c9
2 files changed, 25 insertions, 9 deletions
diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c
index 5cc4f1c..976f85e 100644
--- a/sys/kern/vfs_cache.c
+++ b/sys/kern/vfs_cache.c
@@ -458,18 +458,24 @@ vfs_cache_lookup(ap)
vp = *vpp;
vpid = vp->v_id;
+ cnp->cn_flags &= ~PDIRUNLOCK;
if (dvp == vp) { /* lookup on "." */
VREF(vp);
error = 0;
} else if (flags & ISDOTDOT) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
error = vget(vp, LK_EXCLUSIVE, p);
- if (!error && lockparent && (flags & ISLASTCN))
- error = vn_lock(dvp, LK_EXCLUSIVE, p);
+ if (!error && lockparent && (flags & ISLASTCN)) {
+ if ((error = vn_lock(dvp, LK_EXCLUSIVE, p)) == 0)
+ cnp->cn_flags &= ~PDIRUNLOCK;
+ }
} else {
error = vget(vp, LK_EXCLUSIVE, p);
- if (!lockparent || error || !(flags & ISLASTCN))
+ if (!lockparent || error || !(flags & ISLASTCN)) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
}
/*
* Check that the capability number did not change
@@ -479,12 +485,17 @@ vfs_cache_lookup(ap)
if (vpid == vp->v_id)
return (0);
vput(vp);
- if (lockparent && dvp != vp && (flags & ISLASTCN))
+ if (lockparent && dvp != vp && (flags & ISLASTCN)) {
VOP_UNLOCK(dvp, 0, p);
+ cnp->cn_flags |= PDIRUNLOCK;
+ }
+ }
+ if (cnp->cn_flags & PDIRUNLOCK) {
+ error = vn_lock(dvp, LK_EXCLUSIVE, p);
+ if (error)
+ return (error);
+ cnp->cn_flags &= ~PDIRUNLOCK;
}
- error = vn_lock(dvp, LK_EXCLUSIVE, p);
- if (error)
- return (error);
return (VOP_CACHEDLOOKUP(dvp, vpp, cnp));
}
diff --git a/sys/kern/vfs_lookup.c b/sys/kern/vfs_lookup.c
index c9f43d4..4cd4b01 100644
--- a/sys/kern/vfs_lookup.c
+++ b/sys/kern/vfs_lookup.c
@@ -418,6 +418,7 @@ dirloop:
unionlookup:
ndp->ni_dvp = dp;
ndp->ni_vp = NULL;
+ cnp->cn_flags &= ~PDIRUNLOCK;
ASSERT_VOP_LOCKED(dp, "lookup");
if ((error = VOP_LOOKUP(dp, &ndp->ni_vp, cnp)) != 0) {
KASSERT(ndp->ni_vp == NULL, ("leaf should be empty"));
@@ -429,7 +430,10 @@ unionlookup:
(dp->v_mount->mnt_flag & MNT_UNION)) {
tdp = dp;
dp = dp->v_mount->mnt_vnodecovered;
- vput(tdp);
+ if (cnp->cn_flags & PDIRUNLOCK)
+ vrele(tdp);
+ else
+ vput(tdp);
VREF(dp);
vn_lock(dp, LK_EXCLUSIVE | LK_RETRY, p);
goto unionlookup;
@@ -557,7 +561,8 @@ nextname:
return (0);
bad2:
- if ((cnp->cn_flags & LOCKPARENT) && *ndp->ni_next == '\0')
+ if ((cnp->cn_flags & (LOCKPARENT | PDIRUNLOCK)) == LOCKPARENT &&
+ *ndp->ni_next == '\0')
VOP_UNLOCK(ndp->ni_dvp, 0, p);
vrele(ndp->ni_dvp);
bad:
OpenPOWER on IntegriCloud