Improve and revise fixes for locking violation.

Obtained from:	NetBSD/pc98
This commit is contained in:
KATO Takenori 1998-01-18 07:56:41 +00:00
parent d76f78c43c
commit afc2a5581f
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=32598
4 changed files with 104 additions and 66 deletions

View file

@ -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);
}

View file

@ -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);

View file

@ -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);
}

View file

@ -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);