summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2005-03-29 10:02:48 +0000
committerjeff <jeff@FreeBSD.org>2005-03-29 10:02:48 +0000
commitb82462f0081a350485e15d373e6c0db663abaeb1 (patch)
treeb4bb1fccff70f1efd918e08b1f5c94352b548c8b /sys
parent2059b48294bea78c7f475d3982eb36101387d76c (diff)
downloadFreeBSD-src-b82462f0081a350485e15d373e6c0db663abaeb1.zip
FreeBSD-src-b82462f0081a350485e15d373e6c0db663abaeb1.tar.gz
- Dont clear OWEINACT in vbusy(), we still owe an inactive call if someone
vhold()s us. - Avoid an extra mutex acquire and release in the common case of vgonel() by checking for OWEINACT at the start of the function. - Fix the case where we set OWEINACT in vput(). LK_EXCLUPGRADE drops our shared lock if it fails. Sponsored by: Isilon Systems, Inc.
Diffstat (limited to 'sys')
-rw-r--r--sys/kern/vfs_subr.c27
1 files changed, 16 insertions, 11 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 69929c2..97165dc 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -1905,6 +1905,7 @@ vput(vp)
struct vnode *vp;
{
struct thread *td = curthread; /* XXX */
+ int error;
KASSERT(vp != NULL, ("vput: null vp"));
ASSERT_VOP_LOCKED(vp, "vput");
@@ -1912,6 +1913,7 @@ vput(vp)
/* Skip this v_writecount check if we're going to panic below. */
VNASSERT(vp->v_writecount < vp->v_usecount || vp->v_usecount < 1, vp,
("vput: missed vn_close"));
+ error = 0;
if (vp->v_usecount > 1 || ((vp->v_iflag & VI_DOINGINACT) &&
vp->v_usecount == 1)) {
@@ -1927,10 +1929,15 @@ vput(vp)
panic("vput: negative ref cnt");
}
v_incr_usecount(vp, -1);
- if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE &&
- VOP_LOCK(vp, LK_EXCLUPGRADE, td) != 0)
- vp->v_iflag |= VI_OWEINACT;
- else
+ vp->v_iflag |= VI_OWEINACT;
+ if (VOP_ISLOCKED(vp, td) != LK_EXCLUSIVE) {
+ error = VOP_LOCK(vp, LK_EXCLUPGRADE|LK_INTERLOCK, td);
+ VI_LOCK(vp);
+ }
+ /*
+ * OWEINACT may be cleared while we're sleeping in EXCLUPGRADE.
+ */
+ if (!error && vp->v_iflag & VI_OWEINACT)
vinactive(vp, td);
VOP_UNLOCK(vp, 0, td);
if (VSHOULDFREE(vp))
@@ -2205,6 +2212,7 @@ vgone(struct vnode *vp)
void
vgonel(struct vnode *vp, struct thread *td)
{
+ int oweinact;
int active;
int doomed;
@@ -2226,6 +2234,7 @@ vgonel(struct vnode *vp, struct thread *td)
doomed = (vp->v_iflag & VI_DOOMED);
vp->v_iflag |= VI_DOOMED;
vp->v_vxthread = curthread;
+ oweinact = (vp->v_iflag & VI_OWEINACT);
VI_UNLOCK(vp);
/*
@@ -2241,17 +2250,13 @@ vgonel(struct vnode *vp, struct thread *td)
* If purging an active vnode, it must be closed and
* deactivated before being reclaimed.
*/
- if (active) {
+ if (active)
VOP_CLOSE(vp, FNONBLOCK, NOCRED, td);
+ if (oweinact || active) {
VI_LOCK(vp);
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.
@@ -2744,7 +2749,7 @@ vbusy(struct vnode *vp)
freevnodes--;
mtx_unlock(&vnode_free_list_mtx);
- vp->v_iflag &= ~(VI_FREE|VI_AGE|VI_OWEINACT);
+ vp->v_iflag &= ~(VI_FREE|VI_AGE);
}
/*
OpenPOWER on IntegriCloud