summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaichi GOTO <daichi@FreeBSD.org>2007-10-22 05:44:07 +0000
committerDaichi GOTO <daichi@FreeBSD.org>2007-10-22 05:44:07 +0000
commit2d21093e4dc154367107cda8a1cb9cc8f26bb067 (patch)
tree4bf273887a0a8ce90e9ea399e043a72778424f7f
parent48585fcd379f37adc7427d055f9485532850271a (diff)
Notes
-rw-r--r--sys/fs/nullfs/null_subr.c7
-rw-r--r--sys/fs/nullfs/null_vnops.c23
2 files changed, 25 insertions, 5 deletions
diff --git a/sys/fs/nullfs/null_subr.c b/sys/fs/nullfs/null_subr.c
index 66144c055913..496be3cd58a7 100644
--- a/sys/fs/nullfs/null_subr.c
+++ b/sys/fs/nullfs/null_subr.c
@@ -298,6 +298,7 @@ null_checkvp(vp, fil, lno)
char *fil;
int lno;
{
+ int interlock = 0;
struct null_node *a = VTONULL(vp);
#ifdef notyet
/*
@@ -321,6 +322,10 @@ null_checkvp(vp, fil, lno)
while (null_checkvp_barrier) /*WAIT*/ ;
panic("null_checkvp");
}
+ if (mtx_owned(VI_MTX(vp)) != 0) {
+ VI_UNLOCK(vp);
+ interlock = 1;
+ }
if (vrefcnt(a->null_lowervp) < 1) {
int i; u_long *p;
printf("vp = %p, unref'ed lowervp\n", (void *)vp);
@@ -331,6 +336,8 @@ null_checkvp(vp, fil, lno)
while (null_checkvp_barrier) /*WAIT*/ ;
panic ("null with unref'ed lowervp");
};
+ if (interlock != 0)
+ VI_LOCK(vp);
#ifdef notyet
printf("null %x/%d -> %x/%d [%s, %d]\n",
NULLTOV(a), vrefcnt(NULLTOV(a)),
diff --git a/sys/fs/nullfs/null_vnops.c b/sys/fs/nullfs/null_vnops.c
index fa87a2494c34..66ccc7f4b402 100644
--- a/sys/fs/nullfs/null_vnops.c
+++ b/sys/fs/nullfs/null_vnops.c
@@ -586,20 +586,33 @@ null_unlock(struct vop_unlock_args *ap)
{
struct vnode *vp = ap->a_vp;
int flags = ap->a_flags;
+ int mtxlkflag = 0;
struct thread *td = ap->a_td;
struct null_node *nn;
struct vnode *lvp;
int error;
- if ((flags & LK_INTERLOCK) != 0) {
- VI_UNLOCK(vp);
- ap->a_flags = flags &= ~LK_INTERLOCK;
+ if ((flags & LK_INTERLOCK) != 0)
+ mtxlkflag = 1;
+ else if (mtx_owned(VI_MTX(vp)) == 0) {
+ VI_LOCK(vp);
+ mtxlkflag = 2;
}
nn = VTONULL(vp);
- if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL)
+ if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) {
+ VI_LOCK_FLAGS(lvp, MTX_DUPOK);
+ flags |= LK_INTERLOCK;
+ vholdl(lvp);
+ VI_UNLOCK(vp);
error = VOP_UNLOCK(lvp, flags, td);
- else
+ vdrop(lvp);
+ if (mtxlkflag == 0)
+ VI_LOCK(vp);
+ } else {
+ if (mtxlkflag == 2)
+ VI_UNLOCK(vp);
error = vop_stdunlock(ap);
+ }
return (error);
}