diff --git a/include/sys/zfs_ioctl_impl.h b/include/sys/zfs_ioctl_impl.h index a59cfa1673..6a0b188ea6 100644 --- a/include/sys/zfs_ioctl_impl.h +++ b/include/sys/zfs_ioctl_impl.h @@ -82,7 +82,9 @@ void zfs_ioctl_register(const char *, zfs_ioc_t, zfs_ioc_func_t *, void zfs_ioctl_init_os(void); +boolean_t zfs_vfs_held(zfsvfs_t *); int zfs_vfs_ref(zfsvfs_t **); +void zfs_vfs_rele(zfsvfs_t *); long zfsdev_ioctl_common(uint_t, zfs_cmd_t *); int zfsdev_attach(void); diff --git a/module/os/linux/zfs/zfs_ioctl_os.c b/module/os/linux/zfs/zfs_ioctl_os.c index 2960832a59..f31fd7ac96 100644 --- a/module/os/linux/zfs/zfs_ioctl_os.c +++ b/module/os/linux/zfs/zfs_ioctl_os.c @@ -65,6 +65,12 @@ #include #include +boolean_t +zfs_vfs_held(zfsvfs_t *zfsvfs) +{ + return (zfsvfs->z_sb != NULL); +} + int zfs_vfs_ref(zfsvfs_t **zfvp) { @@ -75,6 +81,12 @@ zfs_vfs_ref(zfsvfs_t **zfvp) return (0); } +void +zfs_vfs_rele(zfsvfs_t *zfsvfs) +{ + deactivate_super(zfsvfs->z_sb); +} + static int zfsdev_state_init(struct file *filp) { diff --git a/module/zfs/zfs_ioctl.c b/module/zfs/zfs_ioctl.c index a993d02e13..92df28b1fd 100644 --- a/module/zfs/zfs_ioctl.c +++ b/module/zfs/zfs_ioctl.c @@ -1442,8 +1442,8 @@ zfsvfs_rele(zfsvfs_t *zfsvfs, void *tag) { rrm_exit(&zfsvfs->z_teardown_lock, tag); - if (zfsvfs->z_sb) { - deactivate_super(zfsvfs->z_sb); + if (zfs_vfs_held(zfsvfs)) { + zfs_vfs_rele(zfsvfs); } else { dmu_objset_disown(zfsvfs->z_os, B_TRUE, zfsvfs); zfsvfs_free(zfsvfs); @@ -4133,7 +4133,7 @@ zfs_ioc_rollback(const char *fsname, nvlist_t *innvl, nvlist_t *outnvl) resume_err = zfs_resume_fs(zfsvfs, ds); error = error ? error : resume_err; } - deactivate_super(zfsvfs->z_sb); + zfs_vfs_rele(zfsvfs); } else if ((zv = zvol_suspend(fsname)) != NULL) { error = dsl_dataset_rollback(fsname, target, zvol_tag(zv), outnvl); @@ -4866,7 +4866,7 @@ zfs_ioc_recv_impl(char *tofs, char *tosnap, char *origin, nvlist_t *recvprops, error = zfs_resume_fs(zfsvfs, ds); } error = error ? error : end_err; - deactivate_super(zfsvfs->z_sb); + zfs_vfs_rele(zfsvfs); } else if ((zv = zvol_suspend(tofs)) != NULL) { error = dmu_recv_end(&drc, zvol_tag(zv)); zvol_resume(zv); @@ -5784,7 +5784,7 @@ zfs_ioc_userspace_upgrade(zfs_cmd_t *zc) } if (error == 0) error = dmu_objset_userspace_upgrade(zfsvfs->z_os); - deactivate_super(zfsvfs->z_sb); + zfs_vfs_rele(zfsvfs); } else { /* XXX kind of reading contents without owning */ error = dmu_objset_hold_flags(zc->zc_name, B_TRUE, FTAG, &os);