linux/super: flatten zpl_mount_impl into zpl_get_tree

Target of opportunity; with no other callers, there's no need for it to
be a static function.

Sponsored-by: TrueNAS
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <rob.norris@truenas.com>
Closes #18339
This commit is contained in:
Rob Norris 2026-03-16 19:27:07 +11:00 committed by Brian Behlendorf
parent 5ebb9ff914
commit 96a0b20201

View File

@ -370,79 +370,6 @@ zpl_test_super(struct super_block *s, void *data)
return (zfsvfs != NULL && os == zfsvfs->z_os);
}
static struct super_block *
zpl_mount_impl(struct file_system_type *fs_type, int flags, zfs_mnt_t *zm)
{
struct super_block *s;
objset_t *os;
boolean_t issnap = B_FALSE;
int err;
err = dmu_objset_hold(zm->mnt_osname, FTAG, &os);
if (err)
return (ERR_PTR(-err));
/*
* The dsl pool lock must be released prior to calling sget().
* It is possible sget() may block on the lock in grab_super()
* while deactivate_super() holds that same lock and waits for
* a txg sync. If the dsl_pool lock is held over sget()
* this can prevent the pool sync and cause a deadlock.
*/
dsl_dataset_long_hold(dmu_objset_ds(os), FTAG);
dsl_pool_rele(dmu_objset_pool(os), FTAG);
s = sget(fs_type, zpl_test_super, set_anon_super, flags, os);
/*
* Recheck with the lock held to prevent mounting the wrong dataset
* since z_os can be stale when the teardown lock is held.
*
* We can't do this in zpl_test_super in since it's under spinlock and
* also s_umount lock is not held there so it would race with
* zfs_umount and zfsvfs can be freed.
*/
if (!IS_ERR(s) && s->s_fs_info != NULL) {
zfsvfs_t *zfsvfs = s->s_fs_info;
if (zpl_enter(zfsvfs, FTAG) == 0) {
if (os != zfsvfs->z_os)
err = -SET_ERROR(EBUSY);
issnap = zfsvfs->z_issnap;
zpl_exit(zfsvfs, FTAG);
} else {
err = -SET_ERROR(EBUSY);
}
}
dsl_dataset_long_rele(dmu_objset_ds(os), FTAG);
dsl_dataset_rele(dmu_objset_ds(os), FTAG);
if (IS_ERR(s))
return (ERR_CAST(s));
if (err) {
deactivate_locked_super(s);
return (ERR_PTR(err));
}
if (s->s_root == NULL) {
err = zpl_fill_super(s, zm, flags & SB_SILENT ? 1 : 0);
if (err) {
deactivate_locked_super(s);
return (ERR_PTR(err));
}
s->s_flags |= SB_ACTIVE;
} else if (!issnap && ((flags ^ s->s_flags) & SB_RDONLY)) {
/*
* Skip ro check for snap since snap is always ro regardless
* ro flag is passed by mount or not.
*/
deactivate_locked_super(s);
return (ERR_PTR(-EBUSY));
}
return (s);
}
static void
zpl_kill_sb(struct super_block *sb)
{
@ -492,12 +419,79 @@ zpl_parse_monolithic(struct fs_context *fc, void *data)
static int
zpl_get_tree(struct fs_context *fc)
{
zfs_mnt_t zm = { .mnt_osname = fc->source, .mnt_data = fc->fs_private };
struct super_block *sb;
objset_t *os;
boolean_t issnap = B_FALSE;
int err;
err = dmu_objset_hold(fc->source, FTAG, &os);
if (err)
return (-err);
/*
* The dsl pool lock must be released prior to calling sget().
* It is possible sget() may block on the lock in grab_super()
* while deactivate_super() holds that same lock and waits for
* a txg sync. If the dsl_pool lock is held over sget()
* this can prevent the pool sync and cause a deadlock.
*/
dsl_dataset_long_hold(dmu_objset_ds(os), FTAG);
dsl_pool_rele(dmu_objset_pool(os), FTAG);
sb = sget(fc->fs_type, zpl_test_super, set_anon_super,
fc->sb_flags, os);
/*
* Recheck with the lock held to prevent mounting the wrong dataset
* since z_os can be stale when the teardown lock is held.
*
* We can't do this in zpl_test_super in since it's under spinlock and
* also s_umount lock is not held there so it would race with
* zfs_umount and zfsvfs can be freed.
*/
if (!IS_ERR(sb) && sb->s_fs_info != NULL) {
zfsvfs_t *zfsvfs = sb->s_fs_info;
if (zpl_enter(zfsvfs, FTAG) == 0) {
if (os != zfsvfs->z_os)
err = SET_ERROR(EBUSY);
issnap = zfsvfs->z_issnap;
zpl_exit(zfsvfs, FTAG);
} else {
err = SET_ERROR(EBUSY);
}
}
dsl_dataset_long_rele(dmu_objset_ds(os), FTAG);
dsl_dataset_rele(dmu_objset_ds(os), FTAG);
struct super_block *sb = zpl_mount_impl(fc->fs_type, fc->sb_flags, &zm);
if (IS_ERR(sb))
return (PTR_ERR(sb));
if (err) {
deactivate_locked_super(sb);
return (-err);
}
if (sb->s_root == NULL) {
zfs_mnt_t zm = {
.mnt_osname = fc->source,
.mnt_data = fc->fs_private,
};
err = zpl_fill_super(sb, &zm,
fc->sb_flags & SB_SILENT ? 1 : 0);
if (err) {
deactivate_locked_super(sb);
return (-err);
}
sb->s_flags |= SB_ACTIVE;
} else if (!issnap && ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)) {
/*
* Skip ro check for snap since snap is always ro regardless
* ro flag is passed by mount or not.
*/
deactivate_locked_super(sb);
return (-SET_ERROR(EBUSY));
}
struct dentry *root = dget(sb->s_root);
if (IS_ERR(root))
return (PTR_ERR(root));