summaryrefslogtreecommitdiffstats
path: root/sys/fs/unionfs/union_vnops.c
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>1997-04-14 05:13:55 +0000
committerkato <kato@FreeBSD.org>1997-04-14 05:13:55 +0000
commit49921c887d0a1bd605725a6b38d7f6c7d7078a5f (patch)
treef426c39e57af1e1038d97fb55b67f5d296c74ef4 /sys/fs/unionfs/union_vnops.c
parent05ac2f5194eb187a3d330758891fa194e5a285e0 (diff)
downloadFreeBSD-src-49921c887d0a1bd605725a6b38d7f6c7d7078a5f.zip
FreeBSD-src-49921c887d0a1bd605725a6b38d7f6c7d7078a5f.tar.gz
Fix locking violation when accessing `..'.
Obtained from: NetBSD
Diffstat (limited to 'sys/fs/unionfs/union_vnops.c')
-rw-r--r--sys/fs/unionfs/union_vnops.c40
1 files changed, 39 insertions, 1 deletions
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 9658eb1..e05372f 100644
--- a/sys/fs/unionfs/union_vnops.c
+++ b/sys/fs/unionfs/union_vnops.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
- * $Id: union_vnops.c,v 1.21 1997/04/13 06:29:13 phk Exp $
+ * $Id: union_vnops.c,v 1.22 1997/04/13 13:12:12 kato Exp $
*/
#include <sys/param.h>
@@ -245,8 +245,40 @@ union_lookup(ap)
*/
if (upperdvp != NULLVP) {
FIXUP(dun, p);
+ /*
+ * If we're doing `..' in the underlying filesystem,
+ * we must drop our lock on the union node before
+ * going up the tree in the lower file system--if we block
+ * on the lowervp lock, and that's held by someone else
+ * coming down the tree and who's waiting for our lock,
+ * we would be hosed.
+ */
+ if (cnp->cn_flags & ISDOTDOT) {
+ /* retain lock on underlying VP: */
+ dun->un_flags |= UN_KLOCK;
+ VOP_UNLOCK(dvp, 0, p);
+ }
uerror = union_lookup1(um->um_uppervp, &upperdvp,
&uppervp, cnp);
+ if (cnp->cn_flags & ISDOTDOT) {
+ if (dun->un_uppervp == upperdvp) {
+ /*
+ * We got the underlying bugger back locked...
+ * now take back the union node lock. Since we
+ * hold the uppervp lock, we can diddle union
+ * locking flags at will. :)
+ */
+ dun->un_flags |= UN_ULOCK;
+ }
+ /*
+ * If upperdvp got swapped out, it means we did
+ * some mount point magic, and we do not have
+ * dun->un_uppervp locked currently--so we get it
+ * locked here (don't set the UN_ULOCK flag).
+ */
+ VOP_LOCK(dvp, 0, p);
+ }
+
/*if (uppervp == upperdvp)
dun->un_flags |= UN_KLOCK;*/
@@ -292,6 +324,12 @@ union_lookup(ap)
saved_cred = cnp->cn_cred;
cnp->cn_cred = um->um_cred;
}
+ /*
+ * We shouldn't have to worry about locking interactions
+ * between the lower layer and our union layer (w.r.t.
+ * `..' processing) because we don't futz with lowervp
+ * locks in the union-node instantiation code path.
+ */
lerror = union_lookup1(um->um_lowervp, &lowerdvp,
&lowervp, cnp);
if (um->um_op == UNMNT_BELOW)
OpenPOWER on IntegriCloud