mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-04-12 22:51:46 +03:00
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:
parent
5ebb9ff914
commit
96a0b20201
@ -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));
|
||||
|
||||
Loading…
Reference in New Issue
Block a user