Index: sys/kern/vfs_cache.c =================================================================== --- sys/kern/vfs_cache.c +++ sys/kern/vfs_cache.c @@ -2958,10 +2958,6 @@ cache_fpl_unhandled(fpl); return (false); } - if ((cnp->cn_flags & LOCKLEAF) == 0) { - cache_fpl_unhandled(fpl); - return (false); - } if (cnp->cn_nameiop != LOOKUP) { cache_fpl_unhandled(fpl); return (false); @@ -3033,7 +3029,6 @@ tvp_seqc = fpl->tvp_seqc; VNPASS(cache_fplookup_vnode_supported(dvp), dvp); - MPASS((cnp->cn_flags & LOCKLEAF) != 0); tvs = vget_prep_smr(tvp); if (tvs == VGET_NONE) { @@ -3048,13 +3043,19 @@ cache_fpl_smr_exit(fpl); - error = vget_finish(tvp, cnp->cn_lkflags, tvs); + if ((cnp->cn_flags & LOCKLEAF) != 0) + error = vget_finish(tvp, cnp->cn_lkflags, tvs); + else + error = vget_finish_ref(tvp, tvs); if (error != 0) { return (cache_fpl_unhandled(fpl)); } if (!seqc_consistent(&tvp->v_seqc, tvp_seqc)) { - vput(tvp); + if ((cnp->cn_flags & LOCKLEAF) != 0) + vput(tvp); + else + vrele(tvp); return (cache_fpl_unhandled(fpl)); } Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -2954,7 +2954,7 @@ int vget_finish(struct vnode *vp, int flags, enum vgetstate vs) { - int error, old; + int error; if ((flags & LK_INTERLOCK) != 0) ASSERT_VI_LOCKED(vp, __func__); @@ -2971,6 +2971,17 @@ vp); return (error); } + return (vget_finish_ref(vp, vs)); +} + +int +vget_finish_ref(struct vnode *vp, enum vgetstate vs) +{ + int old; + + VNPASS(vs == VGET_HOLDCNT || vs == VGET_USECOUNT, vp); + VNPASS(vp->v_holdcnt > 0, vp); + VNPASS(vs == VGET_HOLDCNT || vp->v_usecount > 0, vp); if (vs == VGET_USECOUNT) return (0); Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -689,6 +689,7 @@ enum vgetstate vget_prep_smr(struct vnode *vp); enum vgetstate vget_prep(struct vnode *vp); int vget_finish(struct vnode *vp, int flags, enum vgetstate vs); +int vget_finish_ref(struct vnode *vp, enum vgetstate vs); void vget_abort(struct vnode *vp, enum vgetstate vs); void vgone(struct vnode *vp); void vhold(struct vnode *);