diff options
author | jeff <jeff@FreeBSD.org> | 2008-03-24 04:22:58 +0000 |
---|---|---|
committer | jeff <jeff@FreeBSD.org> | 2008-03-24 04:22:58 +0000 |
commit | 3ad75daf19094d458a872196403a2d5a77437da1 (patch) | |
tree | c6f7407f603c44d5e2ec1d6d639ad4921c89c7e6 | |
parent | 1bf44343e2274c517fe62ccd58a5fecf8f64e5da (diff) | |
download | FreeBSD-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.c | 50 |
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); } |