mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-04-14 07:31:45 +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);
|
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
|
static void
|
||||||
zpl_kill_sb(struct super_block *sb)
|
zpl_kill_sb(struct super_block *sb)
|
||||||
{
|
{
|
||||||
@ -492,12 +419,79 @@ zpl_parse_monolithic(struct fs_context *fc, void *data)
|
|||||||
static int
|
static int
|
||||||
zpl_get_tree(struct fs_context *fc)
|
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))
|
if (IS_ERR(sb))
|
||||||
return (PTR_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);
|
struct dentry *root = dget(sb->s_root);
|
||||||
if (IS_ERR(root))
|
if (IS_ERR(root))
|
||||||
return (PTR_ERR(root));
|
return (PTR_ERR(root));
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user