diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/ext4/super.c | 195 |
1 files changed, 86 insertions, 109 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index 285f18f643ca..f093bb2ccab1 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c @@ -75,12 +75,9 @@ static int ext4_mark_recovery_complete(struct super_block *sb, static int ext4_clear_journal_err(struct super_block *sb, struct ext4_super_block *es); static int ext4_sync_fs(struct super_block *sb, int wait); -static int ext4_remount(struct super_block *sb, int *flags, char *data); static int ext4_statfs(struct dentry *dentry, struct kstatfs *buf); static int ext4_unfreeze(struct super_block *sb); static int ext4_freeze(struct super_block *sb); -static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data); static inline int ext2_feature_set_ok(struct super_block *sb); static inline int ext3_feature_set_ok(struct super_block *sb); static void ext4_destroy_lazyinit_thread(void); @@ -93,6 +90,11 @@ static int ext4_check_opt_consistency(struct fs_context *fc, struct super_block *sb); static int ext4_apply_options(struct fs_context *fc, struct super_block *sb); static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param); +static int ext4_get_tree(struct fs_context *fc); +static int ext4_reconfigure(struct fs_context *fc); +static void ext4_fc_free(struct fs_context *fc); +static int ext4_init_fs_context(struct fs_context *fc); +static const struct fs_parameter_spec ext4_param_specs[]; /* * Lock ordering @@ -122,16 +124,20 @@ static int ext4_parse_param(struct fs_context *fc, struct fs_parameter *param); static const struct fs_context_operations ext4_context_ops = { .parse_param = ext4_parse_param, + .get_tree = ext4_get_tree, + .reconfigure = ext4_reconfigure, + .free = ext4_fc_free, }; #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) static struct file_system_type ext2_fs_type = { - .owner = THIS_MODULE, - .name = "ext2", - .mount = ext4_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .owner = THIS_MODULE, + .name = "ext2", + .init_fs_context = ext4_init_fs_context, + .parameters = ext4_param_specs, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("ext2"); MODULE_ALIAS("ext2"); @@ -142,11 +148,12 @@ MODULE_ALIAS("ext2"); static struct file_system_type ext3_fs_type = { - .owner = THIS_MODULE, - .name = "ext3", - .mount = ext4_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV, + .owner = THIS_MODULE, + .name = "ext3", + .init_fs_context = ext4_init_fs_context, + .parameters = ext4_param_specs, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV, }; MODULE_ALIAS_FS("ext3"); MODULE_ALIAS("ext3"); @@ -1665,7 +1672,6 @@ static const struct super_operations ext4_sops = { .freeze_fs = ext4_freeze, .unfreeze_fs = ext4_unfreeze, .statfs = ext4_statfs, - .remount_fs = ext4_remount, .show_options = ext4_show_options, #ifdef CONFIG_QUOTA .quota_read = ext4_quota_read, @@ -2203,6 +2209,35 @@ struct ext4_fs_context { ext4_fsblk_t s_sb_block; }; +static void ext4_fc_free(struct fs_context *fc) +{ + struct ext4_fs_context *ctx = fc->fs_private; + int i; + + if (!ctx) + return; + + for (i = 0; i < EXT4_MAXQUOTAS; i++) + kfree(ctx->s_qf_names[i]); + + kfree(ctx->test_dummy_enc_arg); + kfree(ctx); +} + +int ext4_init_fs_context(struct fs_context *fc) +{ + struct xfs_fs_context *ctx; + + ctx = kzalloc(sizeof(struct ext4_fs_context), GFP_KERNEL); + if (!ctx) + return -ENOMEM; + + fc->fs_private = ctx; + fc->ops = &ext4_context_ops; + + return 0; +} + #ifdef CONFIG_QUOTA /* * Note the name of the specified quota file. @@ -5602,61 +5637,31 @@ out_fail: return err ? err : ret; } -static void cleanup_ctx(struct ext4_fs_context *ctx) +static int ext4_fill_super(struct super_block *sb, struct fs_context *fc) { - int i; - - if (!ctx) - return; - - for (i = 0; i < EXT4_MAXQUOTAS; i++) { - kfree(ctx->s_qf_names[i]); - } - - kfree(ctx->test_dummy_enc_arg); -} - -static int ext4_fill_super(struct super_block *sb, void *data, int silent) -{ - struct ext4_fs_context ctx; + struct ext4_fs_context *ctx = fc->fs_private; struct ext4_sb_info *sbi; - struct fs_context fc; const char *descr; - char *orig_data; - int ret = -ENOMEM; - - orig_data = kstrdup(data, GFP_KERNEL); - if (data && !orig_data) - return -ENOMEM; - - /* Cleanup superblock name */ - strreplace(sb->s_id, '/', '!'); - - memset(&fc, 0, sizeof(fc)); - memset(&ctx, 0, sizeof(ctx)); - fc.fs_private = &ctx; - - ret = parse_options(&fc, (char *) data); - if (ret < 0) - goto free_data; + int ret; sbi = ext4_alloc_sbi(sb); - if (!sbi) { + if (!sbi) ret = -ENOMEM; - goto free_data; - } - fc.s_fs_info = sbi; + fc->s_fs_info = sbi; + + /* Cleanup superblock name */ + strreplace(sb->s_id, '/', '!'); sbi->s_sb_block = 1; /* Default super block location */ - if (ctx.spec & EXT4_SPEC_s_sb_block) - sbi->s_sb_block = ctx.s_sb_block; + if (ctx->spec & EXT4_SPEC_s_sb_block) + sbi->s_sb_block = ctx->s_sb_block; - ret = __ext4_fill_super(&fc, sb, silent); + ret = __ext4_fill_super(fc, sb, fc->sb_flags & SB_SILENT); if (ret < 0) goto free_sbi; - if (EXT4_SB(sb)->s_journal) { + if (sbi->s_journal) { if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_JOURNAL_DATA) descr = " journalled data mode"; else if (test_opt(sb, DATA_FLAGS) == EXT4_MOUNT_ORDERED_DATA) @@ -5668,23 +5673,21 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) if (___ratelimit(&ext4_mount_msg_ratelimit, "EXT4-fs mount")) ext4_msg(sb, KERN_INFO, "mounted filesystem with%s. " - "Opts: %.*s%s%s. Quota mode: %s.", descr, - (int) sizeof(sbi->s_es->s_mount_opts), - sbi->s_es->s_mount_opts, - *sbi->s_es->s_mount_opts ? "; " : "", orig_data, - ext4_quota_mode(sb)); - - kfree(orig_data); - cleanup_ctx(&ctx); + "Quota mode: %s.", descr, ext4_quota_mode(sb)); + return 0; + free_sbi: ext4_free_sbi(sbi); -free_data: - kfree(orig_data); - cleanup_ctx(&ctx); + fc->s_fs_info = NULL; return ret; } +static int ext4_get_tree(struct fs_context *fc) +{ + return get_tree_bdev(fc, ext4_fill_super); +} + /* * Setup any per-fs journal parameters now. We'll do this both on * initial mount, once the journal has been initialised but before we've @@ -6609,47 +6612,26 @@ restore_opts: return err; } -static int ext4_remount(struct super_block *sb, int *flags, char *data) +static int ext4_reconfigure(struct fs_context *fc) { - struct ext4_sb_info *sbi = EXT4_SB(sb); - struct ext4_fs_context ctx; - struct fs_context fc; - char *orig_data; + struct super_block *sb = fc->root->d_sb; + int flags = fc->sb_flags; int ret; - orig_data = kstrdup(data, GFP_KERNEL); - if (data && !orig_data) - return -ENOMEM; - - memset(&fc, 0, sizeof(fc)); - memset(&ctx, 0, sizeof(ctx)); + fc->s_fs_info = EXT4_SB(sb); - fc.fs_private = &ctx; - fc.purpose = FS_CONTEXT_FOR_RECONFIGURE; - fc.s_fs_info = sbi; - - ret = parse_options(&fc, (char *) data); + ret = ext4_check_opt_consistency(fc, sb); if (ret < 0) - goto err_out; + return ret; - ret = ext4_check_opt_consistency(&fc, sb); + ret = __ext4_remount(fc, sb, &flags); if (ret < 0) - goto err_out; + return ret; - ret = __ext4_remount(&fc, sb, flags); - if (ret < 0) - goto err_out; + ext4_msg(sb, KERN_INFO, "re-mounted. Quota mode: %s.", + ext4_quota_mode(sb)); - ext4_msg(sb, KERN_INFO, "re-mounted. Opts: %s. Quota mode: %s.", - orig_data, ext4_quota_mode(sb)); - cleanup_ctx(&ctx); - kfree(orig_data); return 0; - -err_out: - cleanup_ctx(&ctx); - kfree(orig_data); - return ret; } #ifdef CONFIG_QUOTA @@ -7134,12 +7116,6 @@ out: } #endif -static struct dentry *ext4_mount(struct file_system_type *fs_type, int flags, - const char *dev_name, void *data) -{ - return mount_bdev(fs_type, flags, dev_name, data, ext4_fill_super); -} - #if !defined(CONFIG_EXT2_FS) && !defined(CONFIG_EXT2_FS_MODULE) && defined(CONFIG_EXT4_USE_FOR_EXT2) static inline void register_as_ext2(void) { @@ -7197,11 +7173,12 @@ static inline int ext3_feature_set_ok(struct super_block *sb) } static struct file_system_type ext4_fs_type = { - .owner = THIS_MODULE, - .name = "ext4", - .mount = ext4_mount, - .kill_sb = kill_block_super, - .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, + .owner = THIS_MODULE, + .name = "ext4", + .init_fs_context = ext4_init_fs_context, + .parameters = ext4_param_specs, + .kill_sb = kill_block_super, + .fs_flags = FS_REQUIRES_DEV | FS_ALLOW_IDMAP, }; MODULE_ALIAS_FS("ext4"); |