summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-03-24 06:08:58 +0000
committerjeff <jeff@FreeBSD.org>2005-03-24 06:08:58 +0000
commitbf2e6f43e88a9251233204f4226aba4d6956c835 (patch)
tree2df5784df43150e6fcbe16525ec1f58a050bb8d0
parentc6119ea3e7de11dd5cac183431854137e44b2066 (diff)
downloadFreeBSD-src-bf2e6f43e88a9251233204f4226aba4d6956c835.zip
FreeBSD-src-bf2e6f43e88a9251233204f4226aba4d6956c835.tar.gz
- If vput() is called with a shared lock it must upgrade to an exclusive
before it can call VOP_INACTIVE(). This must use the EXCLUPGRADE path because we may violate some lock order with another locked vnode if we drop and reacquire the lock. If EXCLUPGRADE fails, we mark the vnode with VI_OWEINACT. This case should be very rare. - Clear VI_OWEINACT in vinactive() and vbusy(). - If VI_OWEINACT is set in vgone() do the VOP_INACTIVE call here as well. Sponsored by: Isilon Systems, Inc.
-rw-r--r--sys/kern/vfs_subr.c15
-rw-r--r--sys/sys/vnode.h1
2 files changed, 13 insertions, 3 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 18ca28f..9668b58 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1927,7 +1927,11 @@ vput(vp)
if (vp->v_usecount == 1) {
v_incr_usecount(vp, -1);
- vinactive(vp, td);
+ if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE &&
+ VOP_LOCK(vp, LK_EXCLUPGRADE, td) != 0)
+ vp->v_iflag |= VI_OWEINACT;
+ else
+ vinactive(vp, td);
VOP_UNLOCK(vp, 0, td);
if (VSHOULDFREE(vp))
vfree(vp);
@@ -2003,7 +2007,7 @@ vinactive(struct vnode *vp, struct thread *td)
VI_LOCK(vp);
VNASSERT(vp->v_iflag & VI_DOINGINACT, vp,
("vinactive: lost VI_DOINGINACT"));
- vp->v_iflag &= ~VI_DOINGINACT;
+ vp->v_iflag &= ~(VI_DOINGINACT|VI_OWEINACT);
}
/*
@@ -2250,6 +2254,11 @@ vgonel(struct vnode *vp, struct thread *td)
if ((vp->v_iflag & VI_DOINGINACT) == 0)
vinactive(vp, td);
VI_UNLOCK(vp);
+ } else {
+ VI_LOCK(vp);
+ if (vp->v_iflag & VI_OWEINACT)
+ vinactive(vp, td);
+ VI_UNLOCK(vp);
}
/*
* Reclaim the vnode.
@@ -2742,7 +2751,7 @@ vbusy(struct vnode *vp)
freevnodes--;
mtx_unlock(&vnode_free_list_mtx);
- vp->v_iflag &= ~(VI_FREE|VI_AGE);
+ vp->v_iflag &= ~(VI_FREE|VI_AGE|VI_OWEINACT);
}
/*
diff --git a/sys/sys/vnode.h b/sys/sys/vnode.h
index 45e1880..4f3cf38 100644
--- a/sys/sys/vnode.h
+++ b/sys/sys/vnode.h
@@ -244,6 +244,7 @@ struct xvnode {
#define VI_FREE 0x0100 /* This vnode is on the freelist */
#define VI_OBJDIRTY 0x0400 /* object might be dirty */
#define VI_DOINGINACT 0x0800 /* VOP_INACTIVE is in progress */
+#define VI_OWEINACT 0x1000 /* Need to call inactive */
#define VV_ROOT 0x0001 /* root of its filesystem */
#define VV_ISTTY 0x0002 /* vnode represents a tty */
OpenPOWER on IntegriCloud