summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkato <kato@FreeBSD.org>1998-01-18 07:56:41 +0000
committerkato <kato@FreeBSD.org>1998-01-18 07:56:41 +0000
commit5ff1564039736f2a608d963c03de2883d9430745 (patch)
treece7597cb27c576d77d7ffb0fb869dae2916f8fe4
parenta909b80bf1b408bad3f554b9072f26ff3a3b94fb (diff)
downloadFreeBSD-src-5ff1564039736f2a608d963c03de2883d9430745.zip
FreeBSD-src-5ff1564039736f2a608d963c03de2883d9430745.tar.gz
Improve and revise fixes for locking violation.
Obtained from: NetBSD/pc98
-rw-r--r--sys/fs/unionfs/union_vfsops.c40
-rw-r--r--sys/fs/unionfs/union_vnops.c45
-rw-r--r--sys/miscfs/union/union_vfsops.c40
-rw-r--r--sys/miscfs/union/union_vnops.c45
4 files changed, 104 insertions, 66 deletions
diff --git a/sys/fs/unionfs/union_vfsops.c b/sys/fs/unionfs/union_vfsops.c
index 753afd6..90da301 100644
--- a/sys/fs/unionfs/union_vfsops.c
+++ b/sys/fs/unionfs/union_vfsops.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
- * $Id: union_vfsops.c,v 1.21 1997/10/12 20:24:57 phk Exp $
+ * $Id: union_vfsops.c,v 1.22 1997/11/18 15:07:35 phk Exp $
*/
/*
@@ -132,12 +132,9 @@ union_mount(mp, path, data, ndp, p)
/*
* Unlock lower node to avoid deadlock.
- * (XXX) VOP_ISLOCKED is needed?
*/
- if ((lowerrootvp->v_op == union_vnodeop_p) && VOP_ISLOCKED(lowerrootvp)) {
+ if (lowerrootvp->v_op == union_vnodeop_p)
VOP_UNLOCK(lowerrootvp, 0, p);
- islowerunlocked = 1;
- }
/*
* Find upper node.
@@ -146,11 +143,7 @@ union_mount(mp, path, data, ndp, p)
UIO_USERSPACE, args.target, p);
error = namei(ndp);
- /*
- * Re-lock vnode.
- * (XXX) VOP_ISLOCKED is needed?
- */
- if (islowerunlocked && !VOP_ISLOCKED(lowerrootvp))
+ if (lowerrootvp->v_op == union_vnodeop_p)
vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
goto bad;
@@ -404,27 +397,24 @@ union_root(mp, vpp)
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
+ int lockadj = 0;
+
+ if (um->um_lowervp && um->um_op != UNMNT_BELOW &&
+ VOP_ISLOCKED(um->um_lowervp)) {
+ VREF(um->um_lowervp);
+ VOP_UNLOCK(um->um_lowervp, 0, p);
+ lockadj = 1;
+ }
/*
* Return locked reference to root.
*/
VREF(um->um_uppervp);
if ((um->um_op == UNMNT_BELOW) &&
- VOP_ISLOCKED(um->um_uppervp)) {
+ VOP_ISLOCKED(um->um_uppervp)) {
loselock = 1;
} else {
- if (VOP_ISLOCKED(um->um_uppervp)) {
- /*
- * XXX
- * Should we check type of node?
- */
-#ifdef DIAGNOSTIC
- printf("union_root: multi union mount?");
-#endif
- vrele(um->um_uppervp);
- return EDEADLK;
- } else
- vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
+ vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
loselock = 0;
}
if (um->um_lowervp)
@@ -448,6 +438,10 @@ union_root(mp, vpp)
if (loselock)
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
}
+ if (lockadj) {
+ vn_lock(um->um_lowervp, LK_EXCLUSIVE | LK_RETRY, p);
+ vrele(um->um_lowervp);
+ }
return (error);
}
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c
index 83dcb3e..434b6a0 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.45 1997/10/16 20:32:30 phk Exp $
+ * $Id: union_vnops.c,v 1.46 1997/10/26 20:55:26 phk Exp $
*/
#include <sys/param.h>
@@ -244,6 +244,13 @@ union_lookup(ap)
lowervp = NULLVP;
iswhiteout = 0;
+ if (cnp->cn_flags & ISDOTDOT) {
+ if (upperdvp != NULL)
+ VREF(upperdvp);
+ if (lowerdvp != NULL)
+ VREF(lowerdvp);
+ }
+
/*
* do the lookup in the upper level.
* if that level comsumes additional pathnames,
@@ -305,7 +312,8 @@ union_lookup(ap)
*ap->a_vpp = uppervp;
if (!lockparent)
cnp->cn_flags &= ~LOCKPARENT;
- return (uerror);
+ error = uerror;
+ goto out;
}
if (uerror == ENOENT || uerror == EJUSTRETURN) {
if (cnp->cn_flags & ISWHITEOUT) {
@@ -371,7 +379,8 @@ union_lookup(ap)
*ap->a_vpp = lowervp;
if (!lockparent)
cnp->cn_flags &= ~LOCKPARENT;
- return (lerror);
+ error = lerror;
+ goto out;
}
} else {
lerror = ENOENT;
@@ -416,7 +425,8 @@ union_lookup(ap)
/* case 1. */
if ((uerror != 0) && (lerror != 0)) {
- return (uerror);
+ error = uerror;
+ goto out;
}
/* case 2. */
@@ -433,7 +443,8 @@ union_lookup(ap)
vput(lowervp);
lowervp = NULLVP;
}
- return (uerror);
+ error = uerror;
+ goto out;
}
}
}
@@ -463,6 +474,14 @@ union_lookup(ap)
#endif
}
+out:
+ if (cnp->cn_flags & ISDOTDOT) {
+ if (upperdvp != NULL)
+ vrele(upperdvp);
+ if (lowerdvp != NULL)
+ vrele(lowerdvp);
+ }
+
return (error);
}
@@ -1015,12 +1034,18 @@ union_fsync(ap)
un = VTOUNION(ap->a_vp);
if (dolock)
vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
- else if ((un->un_flags & UN_ULOCK) == 0 &&
- VOP_ISLOCKED(targetvp) == 0) {
- isupperlocked = 1;
- vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
- un->un_flags |= UN_ULOCK;
+ else {
+ un = VTOUNION(ap->a_vp);
+ if ((un->un_flags & UN_ULOCK) == 0 &&
+ targetvp->v_data != NULL &&
+ ((struct lock *)targetvp->v_data)->lk_lockholder
+ == curproc->p_pid &&
+ VOP_ISLOCKED(targetvp) != 0)
+ return 0; /* XXX */
+
+ FIXUP(un, p);
}
+
error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
if (dolock)
VOP_UNLOCK(targetvp, 0, p);
diff --git a/sys/miscfs/union/union_vfsops.c b/sys/miscfs/union/union_vfsops.c
index 753afd6..90da301 100644
--- a/sys/miscfs/union/union_vfsops.c
+++ b/sys/miscfs/union/union_vfsops.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)union_vfsops.c 8.20 (Berkeley) 5/20/95
- * $Id: union_vfsops.c,v 1.21 1997/10/12 20:24:57 phk Exp $
+ * $Id: union_vfsops.c,v 1.22 1997/11/18 15:07:35 phk Exp $
*/
/*
@@ -132,12 +132,9 @@ union_mount(mp, path, data, ndp, p)
/*
* Unlock lower node to avoid deadlock.
- * (XXX) VOP_ISLOCKED is needed?
*/
- if ((lowerrootvp->v_op == union_vnodeop_p) && VOP_ISLOCKED(lowerrootvp)) {
+ if (lowerrootvp->v_op == union_vnodeop_p)
VOP_UNLOCK(lowerrootvp, 0, p);
- islowerunlocked = 1;
- }
/*
* Find upper node.
@@ -146,11 +143,7 @@ union_mount(mp, path, data, ndp, p)
UIO_USERSPACE, args.target, p);
error = namei(ndp);
- /*
- * Re-lock vnode.
- * (XXX) VOP_ISLOCKED is needed?
- */
- if (islowerunlocked && !VOP_ISLOCKED(lowerrootvp))
+ if (lowerrootvp->v_op == union_vnodeop_p)
vn_lock(lowerrootvp, LK_EXCLUSIVE | LK_RETRY, p);
if (error)
goto bad;
@@ -404,27 +397,24 @@ union_root(mp, vpp)
struct union_mount *um = MOUNTTOUNIONMOUNT(mp);
int error;
int loselock;
+ int lockadj = 0;
+
+ if (um->um_lowervp && um->um_op != UNMNT_BELOW &&
+ VOP_ISLOCKED(um->um_lowervp)) {
+ VREF(um->um_lowervp);
+ VOP_UNLOCK(um->um_lowervp, 0, p);
+ lockadj = 1;
+ }
/*
* Return locked reference to root.
*/
VREF(um->um_uppervp);
if ((um->um_op == UNMNT_BELOW) &&
- VOP_ISLOCKED(um->um_uppervp)) {
+ VOP_ISLOCKED(um->um_uppervp)) {
loselock = 1;
} else {
- if (VOP_ISLOCKED(um->um_uppervp)) {
- /*
- * XXX
- * Should we check type of node?
- */
-#ifdef DIAGNOSTIC
- printf("union_root: multi union mount?");
-#endif
- vrele(um->um_uppervp);
- return EDEADLK;
- } else
- vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
+ vn_lock(um->um_uppervp, LK_EXCLUSIVE | LK_RETRY, p);
loselock = 0;
}
if (um->um_lowervp)
@@ -448,6 +438,10 @@ union_root(mp, vpp)
if (loselock)
VTOUNION(*vpp)->un_flags &= ~UN_ULOCK;
}
+ if (lockadj) {
+ vn_lock(um->um_lowervp, LK_EXCLUSIVE | LK_RETRY, p);
+ vrele(um->um_lowervp);
+ }
return (error);
}
diff --git a/sys/miscfs/union/union_vnops.c b/sys/miscfs/union/union_vnops.c
index 83dcb3e..434b6a0 100644
--- a/sys/miscfs/union/union_vnops.c
+++ b/sys/miscfs/union/union_vnops.c
@@ -35,7 +35,7 @@
* SUCH DAMAGE.
*
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
- * $Id: union_vnops.c,v 1.45 1997/10/16 20:32:30 phk Exp $
+ * $Id: union_vnops.c,v 1.46 1997/10/26 20:55:26 phk Exp $
*/
#include <sys/param.h>
@@ -244,6 +244,13 @@ union_lookup(ap)
lowervp = NULLVP;
iswhiteout = 0;
+ if (cnp->cn_flags & ISDOTDOT) {
+ if (upperdvp != NULL)
+ VREF(upperdvp);
+ if (lowerdvp != NULL)
+ VREF(lowerdvp);
+ }
+
/*
* do the lookup in the upper level.
* if that level comsumes additional pathnames,
@@ -305,7 +312,8 @@ union_lookup(ap)
*ap->a_vpp = uppervp;
if (!lockparent)
cnp->cn_flags &= ~LOCKPARENT;
- return (uerror);
+ error = uerror;
+ goto out;
}
if (uerror == ENOENT || uerror == EJUSTRETURN) {
if (cnp->cn_flags & ISWHITEOUT) {
@@ -371,7 +379,8 @@ union_lookup(ap)
*ap->a_vpp = lowervp;
if (!lockparent)
cnp->cn_flags &= ~LOCKPARENT;
- return (lerror);
+ error = lerror;
+ goto out;
}
} else {
lerror = ENOENT;
@@ -416,7 +425,8 @@ union_lookup(ap)
/* case 1. */
if ((uerror != 0) && (lerror != 0)) {
- return (uerror);
+ error = uerror;
+ goto out;
}
/* case 2. */
@@ -433,7 +443,8 @@ union_lookup(ap)
vput(lowervp);
lowervp = NULLVP;
}
- return (uerror);
+ error = uerror;
+ goto out;
}
}
}
@@ -463,6 +474,14 @@ union_lookup(ap)
#endif
}
+out:
+ if (cnp->cn_flags & ISDOTDOT) {
+ if (upperdvp != NULL)
+ vrele(upperdvp);
+ if (lowerdvp != NULL)
+ vrele(lowerdvp);
+ }
+
return (error);
}
@@ -1015,12 +1034,18 @@ union_fsync(ap)
un = VTOUNION(ap->a_vp);
if (dolock)
vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
- else if ((un->un_flags & UN_ULOCK) == 0 &&
- VOP_ISLOCKED(targetvp) == 0) {
- isupperlocked = 1;
- vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p);
- un->un_flags |= UN_ULOCK;
+ else {
+ un = VTOUNION(ap->a_vp);
+ if ((un->un_flags & UN_ULOCK) == 0 &&
+ targetvp->v_data != NULL &&
+ ((struct lock *)targetvp->v_data)->lk_lockholder
+ == curproc->p_pid &&
+ VOP_ISLOCKED(targetvp) != 0)
+ return 0; /* XXX */
+
+ FIXUP(un, p);
}
+
error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p);
if (dolock)
VOP_UNLOCK(targetvp, 0, p);
OpenPOWER on IntegriCloud