diff options
author | kato <kato@FreeBSD.org> | 1998-01-20 10:02:54 +0000 |
---|---|---|
committer | kato <kato@FreeBSD.org> | 1998-01-20 10:02:54 +0000 |
commit | d49fde64e88ed0930d98ea5752325d23d452a74c (patch) | |
tree | f94a3f25ebb61ec2c816446513a36a8e80e7c635 /sys/fs/unionfs/union_subr.c | |
parent | 1b94ff548145fb10224df86f77d684ccfa34e93a (diff) | |
download | FreeBSD-src-d49fde64e88ed0930d98ea5752325d23d452a74c.zip FreeBSD-src-d49fde64e88ed0930d98ea5752325d23d452a74c.tar.gz |
- Move SETKLOC and CLEARKLOCK macros into uion.h.
- Set UN_ULOCK in union_lock() when UN_KLOCK is set. Caller expects
that vnode is locked correctly, and may call another function which
expects locked vnode and may unlock the vnode.
- Do not assume the behavior of inside functions in FreeBSD's
vfs_suber.c is same as 4.4BSD-Lite2. Vnode may be locked in
vget() even though flag is zero. (Locked vnode is, of course,
unlocked before returning from vget.)
Diffstat (limited to 'sys/fs/unionfs/union_subr.c')
-rw-r--r-- | sys/fs/unionfs/union_subr.c | 19 |
1 files changed, 18 insertions, 1 deletions
diff --git a/sys/fs/unionfs/union_subr.c b/sys/fs/unionfs/union_subr.c index 3b17f9c..87ba491 100644 --- a/sys/fs/unionfs/union_subr.c +++ b/sys/fs/unionfs/union_subr.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * @(#)union_subr.c 8.20 (Berkeley) 5/20/95 - * $Id: union_subr.c,v 1.22 1997/11/18 15:07:35 phk Exp $ + * $Id: union_subr.c,v 1.23 1997/12/27 02:56:26 bde Exp $ */ #include <sys/param.h> @@ -307,6 +307,7 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache) int hash; int vflag; int try; + int klocked; if (uppervp == NULLVP && lowervp == NULLVP) panic("union: unidentifiable allocation"); @@ -362,11 +363,27 @@ loop: (un->un_uppervp == uppervp || un->un_uppervp == NULLVP) && (UNIONTOV(un)->v_mount == mp)) { + /* + * Do not assume that vget() does not + * lock the vnode even though flags + * argument is 0. + */ + if ((un->un_uppervp != NULLVP) && + ((un->un_flags & UN_KLOCK) == 0)) { + SETKLOCK(un); + klocked = 1; + } else { + klocked = 0; + } if (vget(UNIONTOV(un), 0, cnp ? cnp->cn_proc : NULL)) { + if (klocked) + CLEARKLOCK(un); union_list_unlock(hash); goto loop; } + if (klocked) + CLEARKLOCK(un); break; } } |