summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordaichi <daichi@FreeBSD.org>2007-10-14 13:57:11 +0000
committerdaichi <daichi@FreeBSD.org>2007-10-14 13:57:11 +0000
commit87bd60ac749cd353222114cf1806314cb01658ce (patch)
tree6b2a9b364ef37d6b33c519bf47550f4dd477b098
parentb4e293afdf72162137b2dba22113a5ee64c72c99 (diff)
downloadFreeBSD-src-87bd60ac749cd353222114cf1806314cb01658ce.zip
FreeBSD-src-87bd60ac749cd353222114cf1806314cb01658ce.tar.gz
This changes give nullfs correctly work with latest unionfs.
Submitted by: Masanori Ozawa <ozawa@ongs.co.jp> (unionfs developer) Reviewed by: jeff, kensmith Approved by: re (kensmith) MFC after: 1 week
-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 66144c0..496be3c 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 fa87a24..66ccc7f 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);
}
OpenPOWER on IntegriCloud