- 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.)
This commit is contained in:
parent
1b94ff5481
commit
d49fde64e8
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union.h 8.9 (Berkeley) 12/10/94
|
||||
* $Id: union.h,v 1.8 1997/02/22 09:40:40 peter Exp $
|
||||
* $Id: union.h,v 1.9 1997/11/18 15:07:34 phk Exp $
|
||||
*/
|
||||
|
||||
struct union_args {
|
||||
@ -94,6 +94,9 @@ struct union_node {
|
||||
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
|
||||
#define UN_CACHED 0x10 /* In union cache */
|
||||
|
||||
#define SETKLOCK(un) (un)->un_flags |= UN_KLOCK
|
||||
#define CLEARKLOCK(un) (un)->un_flags &= ~UN_KLOCK
|
||||
|
||||
extern int union_allocvp __P((struct vnode **, struct mount *,
|
||||
struct vnode *, struct vnode *,
|
||||
struct componentname *, struct vnode *,
|
||||
|
@ -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 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
|
||||
(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;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
|
||||
* $Id: union_vnops.c,v 1.47 1998/01/18 07:56:41 kato Exp $
|
||||
* $Id: union_vnops.c,v 1.48 1998/01/18 08:17:48 kato Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -58,9 +58,6 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define SETKLOCK(un) (un)->un_flags |= UN_KLOCK
|
||||
#define CLEARKLOCK(un) (un)->un_flags &= ~UN_KLOCK
|
||||
|
||||
static int union_abortop __P((struct vop_abortop_args *ap));
|
||||
static int union_access __P((struct vop_access_args *ap));
|
||||
static int union_advlock __P((struct vop_advlock_args *ap));
|
||||
@ -1548,11 +1545,13 @@ union_lock(ap)
|
||||
un = VTOUNION(vp);
|
||||
|
||||
if (un->un_uppervp != NULLVP) {
|
||||
if (((un->un_flags & (UN_ULOCK | UN_KLOCK)) == 0) &&
|
||||
if (((un->un_flags & UN_ULOCK) == 0) &&
|
||||
(vp->v_usecount != 0)) {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if ((un->un_flags & UN_KLOCK) == 0) {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
un->un_flags |= UN_ULOCK;
|
||||
}
|
||||
}
|
||||
@ -1590,6 +1589,10 @@ union_lock(ap)
|
||||
*
|
||||
* If UN_KLOCK isn't set, then the upper vnode is unlocked here.
|
||||
*/
|
||||
/*
|
||||
* FreeBSD: Do not cleark UN_KLOCK flag. UN_KLOCK flag is tested
|
||||
* in union_lock().
|
||||
*/
|
||||
static int
|
||||
union_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union.h 8.9 (Berkeley) 12/10/94
|
||||
* $Id: union.h,v 1.8 1997/02/22 09:40:40 peter Exp $
|
||||
* $Id: union.h,v 1.9 1997/11/18 15:07:34 phk Exp $
|
||||
*/
|
||||
|
||||
struct union_args {
|
||||
@ -94,6 +94,9 @@ struct union_node {
|
||||
#define UN_KLOCK 0x08 /* Keep upper node locked on vput */
|
||||
#define UN_CACHED 0x10 /* In union cache */
|
||||
|
||||
#define SETKLOCK(un) (un)->un_flags |= UN_KLOCK
|
||||
#define CLEARKLOCK(un) (un)->un_flags &= ~UN_KLOCK
|
||||
|
||||
extern int union_allocvp __P((struct vnode **, struct mount *,
|
||||
struct vnode *, struct vnode *,
|
||||
struct componentname *, struct vnode *,
|
||||
|
@ -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 @@ union_allocvp(vpp, mp, undvp, dvp, cnp, uppervp, lowervp, docache)
|
||||
(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;
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,7 @@
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* @(#)union_vnops.c 8.32 (Berkeley) 6/23/95
|
||||
* $Id: union_vnops.c,v 1.47 1998/01/18 07:56:41 kato Exp $
|
||||
* $Id: union_vnops.c,v 1.48 1998/01/18 08:17:48 kato Exp $
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -58,9 +58,6 @@
|
||||
} \
|
||||
}
|
||||
|
||||
#define SETKLOCK(un) (un)->un_flags |= UN_KLOCK
|
||||
#define CLEARKLOCK(un) (un)->un_flags &= ~UN_KLOCK
|
||||
|
||||
static int union_abortop __P((struct vop_abortop_args *ap));
|
||||
static int union_access __P((struct vop_access_args *ap));
|
||||
static int union_advlock __P((struct vop_advlock_args *ap));
|
||||
@ -1548,11 +1545,13 @@ union_lock(ap)
|
||||
un = VTOUNION(vp);
|
||||
|
||||
if (un->un_uppervp != NULLVP) {
|
||||
if (((un->un_flags & (UN_ULOCK | UN_KLOCK)) == 0) &&
|
||||
if (((un->un_flags & UN_ULOCK) == 0) &&
|
||||
(vp->v_usecount != 0)) {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
if (error)
|
||||
return (error);
|
||||
if ((un->un_flags & UN_KLOCK) == 0) {
|
||||
error = vn_lock(un->un_uppervp, flags, p);
|
||||
if (error)
|
||||
return (error);
|
||||
}
|
||||
un->un_flags |= UN_ULOCK;
|
||||
}
|
||||
}
|
||||
@ -1590,6 +1589,10 @@ union_lock(ap)
|
||||
*
|
||||
* If UN_KLOCK isn't set, then the upper vnode is unlocked here.
|
||||
*/
|
||||
/*
|
||||
* FreeBSD: Do not cleark UN_KLOCK flag. UN_KLOCK flag is tested
|
||||
* in union_lock().
|
||||
*/
|
||||
static int
|
||||
union_unlock(ap)
|
||||
struct vop_unlock_args /* {
|
||||
|
Loading…
Reference in New Issue
Block a user