diff options
author | kato <kato@FreeBSD.org> | 1998-01-18 07:56:41 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1998-01-18 07:56:41 +0000 |
commit | 5ff1564039736f2a608d963c03de2883d9430745 (patch) | |
tree | ce7597cb27c576d77d7ffb0fb869dae2916f8fe4 | |
parent | a909b80bf1b408bad3f554b9072f26ff3a3b94fb (diff) | |
download | FreeBSD-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.c | 40 | ||||
-rw-r--r-- | sys/fs/unionfs/union_vnops.c | 45 | ||||
-rw-r--r-- | sys/miscfs/union/union_vfsops.c | 40 | ||||
-rw-r--r-- | sys/miscfs/union/union_vnops.c | 45 |
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); |