summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjeff <jeff@FreeBSD.org>2008-03-24 04:22:58 +0000
committerjeff <jeff@FreeBSD.org>2008-03-24 04:22:58 +0000
commit3ad75daf19094d458a872196403a2d5a77437da1 (patch)
treec6f7407f603c44d5e2ec1d6d639ad4921c89c7e6
parent1bf44343e2274c517fe62ccd58a5fecf8f64e5da (diff)
downloadFreeBSD-src-3ad75daf19094d458a872196403a2d5a77437da1.zip
FreeBSD-src-3ad75daf19094d458a872196403a2d5a77437da1.tar.gz
- Greatly simplify vget() by removing the guarantee that any new
references to a vnode with VI_OWEINACT set will force the vinactive() call. The kernel makes no guarantees about which reference was the last to close a file or when the actual inactive processing will happen. The previous code was designed to preserve existing semantics in the face of shared locks, however, this was unnecessary. Discussed with: mckusick
-rw-r--r--sys/kern/vfs_subr.c50
1 files changed, 18 insertions, 32 deletions
diff --git a/sys/kern/vfs_subr.c b/sys/kern/vfs_subr.c
index 27e8f04..b3bd6f6 100644
--- a/sys/kern/vfs_subr.c
+++ b/sys/kern/vfs_subr.c
@@ -2030,57 +2030,43 @@ v_decr_useonly(struct vnode *vp)
/*
* Grab a particular vnode from the free list, increment its
- * reference count and lock it. The vnode lock bit is set if the
- * vnode is being eliminated in vgone. The process is awakened
- * when the transition is completed, and an error returned to
- * indicate that the vnode is no longer usable (possibly having
- * been changed to a new filesystem type).
+ * reference count and lock it. VI_DOOMED is set if the vnode
+ * is being destroyed. Only callers who specify LK_RETRY will
+ * see doomed vnodes. If inactive processing was delayed in
+ * vput try to do it here.
*/
int
vget(struct vnode *vp, int flags, struct thread *td)
{
- int oweinact;
- int oldflags;
int error;
error = 0;
- oldflags = flags;
- oweinact = 0;
VFS_ASSERT_GIANT(vp->v_mount);
if ((flags & LK_INTERLOCK) == 0)
VI_LOCK(vp);
- /*
- * If the inactive call was deferred because vput() was called
- * with a shared lock, we have to do it here before another thread
- * gets a reference to data that should be dead.
- */
- if (vp->v_iflag & VI_OWEINACT) {
- if (flags & LK_NOWAIT) {
- VI_UNLOCK(vp);
- return (EBUSY);
- }
- flags &= ~LK_TYPE_MASK;
- flags |= LK_EXCLUSIVE;
- oweinact = 1;
- }
vholdl(vp);
if ((error = vn_lock(vp, flags | LK_INTERLOCK)) != 0) {
vdrop(vp);
return (error);
}
+ if (vp->v_iflag & VI_DOOMED && (flags & LK_RETRY) == 0)
+ panic("vget: vn_lock failed to return ENOENT\n");
VI_LOCK(vp);
/* Upgrade our holdcnt to a usecount. */
v_upgrade_usecount(vp);
- if (vp->v_iflag & VI_DOOMED && (flags & LK_RETRY) == 0)
- panic("vget: vn_lock failed to return ENOENT\n");
- if (oweinact) {
- if (vp->v_iflag & VI_OWEINACT)
+ /*
+ * We don't guarantee that any particular close will
+ * trigger inactive processing so just make a best effort
+ * here at preventing a reference to a removed file. If
+ * we don't succeed no harm is done.
+ */
+ if (vp->v_iflag & VI_OWEINACT) {
+ if (VOP_ISLOCKED(vp) == LK_EXCLUSIVE &&
+ (flags & LK_NOWAIT) == 0)
vinactive(vp, td);
- VI_UNLOCK(vp);
- if ((oldflags & LK_TYPE_MASK) == 0)
- VOP_UNLOCK(vp, 0);
- } else
- VI_UNLOCK(vp);
+ vp->v_iflag &= ~VI_OWEINACT;
+ }
+ VI_UNLOCK(vp);
return (0);
}
OpenPOWER on IntegriCloud