diff options
author | phk <phk@FreeBSD.org> | 1997-04-13 06:29:13 +0000 |
---|---|---|
committer | phk <phk@FreeBSD.org> | 1997-04-13 06:29:13 +0000 |
commit | 4292ccaf6dc17167b3168e3ddf5b1a5e6c818486 (patch) | |
tree | 35ae49f1acf641744a886c2216a878b83b576229 /sys/fs/unionfs/union_vnops.c | |
parent | 69934522f723a52b4a83a27a0996b92a17c0a9a2 (diff) | |
download | FreeBSD-src-4292ccaf6dc17167b3168e3ddf5b1a5e6c818486.zip FreeBSD-src-4292ccaf6dc17167b3168e3ddf5b1a5e6c818486.tar.gz |
The function union_fsync tries to lock overlaying vnode object when
dolock is not set (that is, targetvp == overlaying vnode object).
Current code use FIXUP macro to do this, and never unlocks overlaying
vnode object in union_fsync. So, the vnode object will be locked
twice and never unlocked.
PR: 3271
Submitted by: kato
Diffstat (limited to 'sys/fs/unionfs/union_vnops.c')
-rw-r--r-- | sys/fs/unionfs/union_vnops.c | 17 |
1 files changed, 14 insertions, 3 deletions
diff --git a/sys/fs/unionfs/union_vnops.c b/sys/fs/unionfs/union_vnops.c index 7909706..b97cc79 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.19 1997/02/22 09:40:42 peter Exp $ + * $Id: union_vnops.c,v 1.20 1997/03/23 03:37:00 bde Exp $ */ #include <sys/param.h> @@ -917,17 +917,28 @@ union_fsync(ap) int error = 0; struct proc *p = ap->a_p; struct vnode *targetvp = OTHERVP(ap->a_vp); + struct union_node *un; + int isupperlocked = 0; if (targetvp != NULLVP) { int dolock = (targetvp == LOWERVP(ap->a_vp)); + un = VTOUNION(ap->a_vp); if (dolock) vn_lock(targetvp, LK_EXCLUSIVE | LK_RETRY, p); - else - FIXUP(VTOUNION(ap->a_vp), 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; + } error = VOP_FSYNC(targetvp, ap->a_cred, ap->a_waitfor, p); if (dolock) VOP_UNLOCK(targetvp, 0, p); + else if (isupperlocked) { + VOP_UNLOCK(targetvp, 0, p); + un->un_flags &= ~UN_ULOCK; + } } return (error); |