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);
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
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");
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");
.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,
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.
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)
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
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
}
#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)
{
}
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");