Index: sys/fs/nullfs/null_vnops.c =================================================================== --- sys/fs/nullfs/null_vnops.c +++ sys/fs/nullfs/null_vnops.c @@ -668,7 +668,7 @@ * We prevent it from being recycled by holding the vnode * here. */ - vholdl(lvp); + vholdnz(lvp); error = VOP_LOCK(lvp, flags); /* @@ -710,31 +710,16 @@ null_unlock(struct vop_unlock_args *ap) { struct vnode *vp = ap->a_vp; - int flags = ap->a_flags; - int mtxlkflag = 0; struct null_node *nn; struct vnode *lvp; int error; - if ((flags & LK_INTERLOCK) != 0) - mtxlkflag = 1; - else if (mtx_owned(VI_MTX(vp)) == 0) { - VI_LOCK(vp); - mtxlkflag = 2; - } nn = VTONULL(vp); if (nn != NULL && (lvp = NULLVPTOLOWERVP(vp)) != NULL) { - VI_LOCK_FLAGS(lvp, MTX_DUPOK); - flags |= LK_INTERLOCK; - vholdl(lvp); - VI_UNLOCK(vp); - error = VOP_UNLOCK(lvp, flags); + vholdnz(lvp); + error = VOP_UNLOCK(lvp, 0); vdrop(lvp); - if (mtxlkflag == 0) - VI_LOCK(vp); } else { - if (mtxlkflag == 2) - VI_UNLOCK(vp); error = vop_stdunlock(ap); } @@ -845,10 +830,8 @@ VI_LOCK(vp); xp = VTONULL(vp); if (xp && (lowervp = xp->null_lowervp)) { - VI_LOCK_FLAGS(lowervp, MTX_DUPOK); + vholdnz(lowervp); VI_UNLOCK(vp); - vholdl(lowervp); - VI_UNLOCK(lowervp); VOP_GETWRITEMOUNT(lowervp, ap->a_mpp); vdrop(lowervp); } else { Index: sys/kern/vfs_subr.c =================================================================== --- sys/kern/vfs_subr.c +++ sys/kern/vfs_subr.c @@ -3022,6 +3022,19 @@ VI_UNLOCK(vp); } +void +vholdnz(struct vnode *vp) +{ + + CTR2(KTR_VFS, "%s: vp %p", __func__, vp); +#ifdef INVARIANTS + int old = atomic_fetchadd_int(&vp->v_holdcnt, 1); + VNASSERT(old > 0, vp, ("%s: wrong hold count", __func__)); +#else + refcount_acquire(&vp->v_holdcnt); +#endif +} + /* * Drop the hold count of the vnode. If this is the last reference to * the vnode we place it on the free list unless it has been vgone'd Index: sys/sys/vnode.h =================================================================== --- sys/sys/vnode.h +++ sys/sys/vnode.h @@ -657,6 +657,7 @@ #define vhold(vp) _vhold((vp), 0) #define vholdl(vp) _vhold((vp), 1) void _vhold(struct vnode *, bool); +void vholdnz(struct vnode *); void vinactive(struct vnode *, struct thread *); int vinvalbuf(struct vnode *vp, int save, int slpflag, int slptimeo); int vtruncbuf(struct vnode *vp, off_t length, int blksize);