diff options
author | jeff <jeff@FreeBSD.org> | 2005-03-24 06:08:58 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2005-03-24 06:08:58 +0000 |
commit | bf2e6f43e88a9251233204f4226aba4d6956c835 (patch) | |
tree | 2df5784df43150e6fcbe16525ec1f58a050bb8d0 /sys/kern | |
parent | c6119ea3e7de11dd5cac183431854137e44b2066 (diff) | |
download | FreeBSD-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.
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_subr.c | 15 |
1 files changed, 12 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); } /* |