diff --git a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c --- a/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c +++ b/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_ctldir.c @@ -1216,6 +1216,9 @@ size_t len; int locked; int error; +#if __FreeBSD_version >= 1400093 + bool unlocked; +#endif vp = ap->a_vp; node = vp->v_data; @@ -1223,17 +1226,31 @@ if (*ap->a_buflen < len) return (SET_ERROR(ENOMEM)); + locked = VOP_ISLOCKED(vp); /* * Prevent unmounting of the snapshot while the vnode lock * is not held. That is not strictly required, but allows * us to assert that an uncovered snapshot vnode is never * "leaked". */ +#if __FreeBSD_version >= 1400093 + error = vn_busy_mountedhere(vp, &unlocked, &mp); + if (__predict_false(unlocked)) { + vn_lock(vp, locked | LK_RETRY); + if (VN_IS_DOOMED(vp)) { + vfs_unbusy(mp); + mp = NULL; + } + } +#else mp = vp->v_mountedhere; - if (mp == NULL) +#endif + if (__predict_false(mp == NULL)) return (SET_ERROR(ENOENT)); +#if __FreeBSD_version < 1400093 error = vfs_busy(mp, 0); KASSERT(error == 0, ("vfs_busy(mp, 0) failed with %d", error)); +#endif /* * We can vput the vnode as we can now depend on the reference owned @@ -1241,7 +1258,6 @@ * the reference may go after vfs_unbusy() which has to be called * before we can lock the vnode again. */ - locked = VOP_ISLOCKED(vp); #if __FreeBSD_version >= 1300045 enum vgetstate vs = vget_prep(vp); #else