Index: sys/fs/tmpfs/tmpfs_vnops.c =================================================================== --- sys/fs/tmpfs/tmpfs_vnops.c +++ sys/fs/tmpfs/tmpfs_vnops.c @@ -1283,6 +1283,27 @@ return (0); } +static int +tmpfs_need_inactive(struct vop_need_inactive_args *ap) +{ + struct vnode *vp; + struct tmpfs_node *node; + struct vm_object *obj; + + vp = ap->a_vp; + node = VP_TO_TMPFS_NODE(vp); + if (node->tn_links == 0) + goto need; + if (vp->v_type == VREG) { + obj = vp->v_object; + if ((obj->flags & OBJ_TMPFS_DIRTY) != 0) + goto need; + } + return (0); +need: + return (1); +} + int tmpfs_reclaim(struct vop_reclaim_args *v) { @@ -1584,6 +1605,7 @@ .vop_readdir = tmpfs_readdir, .vop_readlink = tmpfs_readlink, .vop_inactive = tmpfs_inactive, + .vop_need_inactive = tmpfs_need_inactive, .vop_reclaim = tmpfs_reclaim, .vop_print = tmpfs_print, .vop_pathconf = tmpfs_pathconf, Index: sys/kern/vfs_default.c =================================================================== --- sys/kern/vfs_default.c +++ sys/kern/vfs_default.c @@ -120,6 +120,7 @@ .vop_getpages_async = vop_stdgetpages_async, .vop_getwritemount = vop_stdgetwritemount, .vop_inactive = VOP_NULL, + .vop_need_inactive = vop_stdneed_inactive, .vop_ioctl = vop_stdioctl, .vop_kqfilter = vop_stdkqfilter, .vop_islocked = vop_stdislocked, @@ -1157,6 +1158,13 @@ return (error); } +int +vop_stdneed_inactive(struct vop_need_inactive_args *ap) +{ + + return (1); +} + static int vop_stdioctl(struct vop_ioctl_args *ap) { Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -2841,7 +2841,8 @@ static void vputx(struct vnode *vp, int func) { - int error; + struct vm_object *obj; + int do_inact, error; KASSERT(vp != NULL, ("vputx: null vp")); if (func == VPUTX_VUNREF) @@ -2888,6 +2889,24 @@ CTR2(KTR_VFS, "%s: return vnode %p to the freelist", __func__, vp); + do_inact = VOP_NEED_INACTIVE(vp); + if (!do_inact) { + /* + * v_object association is protected by the vnode lock which we don't + * necessarily have. However, objects are type stable and this check + * is harmless if incorrect. + */ + if ((obj = vp->v_object) != NULL && (vp->v_vflag & VV_NOSYNC) == 0 && + (obj->flags & OBJ_MIGHTBEDIRTY) != 0) + do_inact++; + } + if (!do_inact) { + if (func == VPUTX_VPUT) + VOP_UNLOCK(vp, 0); + vdropl(vp); + return; + } + /* * We must call VOP_INACTIVE with the node locked. Mark * as VI_DOINGINACT to avoid recursion. @@ -4338,6 +4357,7 @@ .vop_close = sync_close, /* close */ .vop_fsync = sync_fsync, /* fsync */ .vop_inactive = sync_inactive, /* inactive */ + .vop_need_inactive = vop_stdneed_inactive, /* need_inactive */ .vop_reclaim = sync_reclaim, /* reclaim */ .vop_lock1 = vop_stdlock, /* lock */ .vop_unlock = vop_stdunlock, /* unlock */ Index: sys/kern/vnode_if.src =================================================================== --- sys/kern/vnode_if.src +++ sys/kern/vnode_if.src @@ -358,6 +358,11 @@ IN struct thread *td; }; +%% need_inactive vp - - - + +vop_need_inactive { + IN struct vnode *vp; +}; %% reclaim vp E E E %! reclaim post vop_reclaim_post Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -752,6 +752,7 @@ int vop_stdgetwritemount(struct vop_getwritemount_args *); int vop_stdgetpages(struct vop_getpages_args *); int vop_stdinactive(struct vop_inactive_args *); +int vop_stdneed_inactive(struct vop_need_inactive_args *); int vop_stdislocked(struct vop_islocked_args *); int vop_stdkqfilter(struct vop_kqfilter_args *); int vop_stdlock(struct vop_lock1_args *);