mirror of
https://github.com/freebsd/freebsd-src
synced 2024-09-30 21:54:50 +00:00
Improve and revise fixes for locking violation.
Obtained from: NetBSD/pc98
This commit is contained in:
parent
d76f78c43c
commit
afc2a5581f
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=32598
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue