@@ -837,6 +837,12 @@ struct btrfs_fs_info {
struct lockdep_map btrfs_trans_pending_ordered_map;
struct lockdep_map btrfs_ordered_extent_map;
+ /*
+ * Temporary pointer to the mount option string.
+ * This is to workaround the fact that all open_ctree() init
+ * functions can only accept a single @fs_info pointer.
+ */
+ char *__options;
#ifdef CONFIG_BTRFS_FS_REF_VERIFY
spinlock_t ref_verify_lock;
struct rb_root block_tree;
@@ -3554,6 +3554,50 @@ static int open_ctree_super_init(struct btrfs_fs_info *fs_info)
return ret;
}
+static int open_ctree_features_init(struct btrfs_fs_info *fs_info)
+{
+ int ret;
+
+ ret = btrfs_parse_options(fs_info, fs_info->__options,
+ fs_info->sb->s_flags);
+ if (ret)
+ return ret;
+
+ ret = btrfs_check_features(fs_info, fs_info->sb);
+ if (ret < 0)
+ return ret;
+
+ if (fs_info->sectorsize < PAGE_SIZE) {
+ struct btrfs_subpage_info *subpage_info;
+
+ /*
+ * V1 space cache has some hardcoded PAGE_SIZE usage, and is
+ * going to be deprecated.
+ *
+ * Force to use v2 cache for subpage case.
+ */
+ btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
+ btrfs_set_and_info(fs_info, FREE_SPACE_TREE,
+ "forcing free space tree for sector size %u with page size %lu",
+ fs_info->sectorsize, PAGE_SIZE);
+
+ btrfs_warn(fs_info,
+ "read-write for sector size %u with page size %lu is experimental",
+ fs_info->sectorsize, PAGE_SIZE);
+ subpage_info = kzalloc(sizeof(*subpage_info), GFP_KERNEL);
+ if (!subpage_info)
+ return -ENOMEM;
+ btrfs_init_subpage_info(subpage_info, fs_info->sectorsize);
+ fs_info->subpage_info = subpage_info;
+ }
+
+ if (!btrfs_test_opt(fs_info, NOSSD) &&
+ !fs_info->fs_devices->rotating)
+ btrfs_set_and_info(fs_info, SSD, "enabling ssd optimizations");
+
+ return 0;
+}
+
struct init_sequence {
int (*init_func)(struct btrfs_fs_info *fs_info);
void (*exit_func)(struct btrfs_fs_info *fs_info);
@@ -3566,22 +3610,25 @@ static const struct init_sequence open_ctree_seq[] = {
}, {
.init_func = open_ctree_super_init,
.exit_func = NULL,
+ }, {
+ .init_func = open_ctree_features_init,
+ .exit_func = NULL,
}
};
-
int __cold open_ctree(struct super_block *sb, char *options)
{
u64 generation;
- bool open_ctree_res[ARRAY_SIZE(open_ctree_seq)] = {0};
struct btrfs_fs_info *fs_info = btrfs_sb(sb);
struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+ bool open_ctree_res[ARRAY_SIZE(open_ctree_seq)] = {0};
int ret;
int err = -EINVAL;
int level;
int i;
fs_info->sb = sb;
+ fs_info->__options = options;
/* Caller should have already initialized fs_info->fs_devices. */
ASSERT(fs_info->fs_devices);
@@ -3593,42 +3640,6 @@ int __cold open_ctree(struct super_block *sb, char *options)
open_ctree_res[i] = true;
}
- ret = btrfs_parse_options(fs_info, options, fs_info->sb->s_flags);
- if (ret) {
- err = ret;
- goto fail_alloc;
- }
-
- ret = btrfs_check_features(fs_info, fs_info->sb);
- if (ret < 0) {
- err = ret;
- goto fail_alloc;
- }
-
- if (fs_info->sectorsize < PAGE_SIZE) {
- struct btrfs_subpage_info *subpage_info;
-
- /*
- * V1 space cache has some hardcoded PAGE_SIZE usage, and is
- * going to be deprecated.
- *
- * Force to use v2 cache for subpage case.
- */
- btrfs_clear_opt(fs_info->mount_opt, SPACE_CACHE);
- btrfs_set_and_info(fs_info, FREE_SPACE_TREE,
- "forcing free space tree for sector size %u with page size %lu",
- fs_info->sectorsize, PAGE_SIZE);
-
- btrfs_warn(fs_info,
- "read-write for sector size %u with page size %lu is experimental",
- fs_info->sectorsize, PAGE_SIZE);
- subpage_info = kzalloc(sizeof(*subpage_info), GFP_KERNEL);
- if (!subpage_info)
- goto fail_alloc;
- btrfs_init_subpage_info(subpage_info, fs_info->sectorsize);
- fs_info->subpage_info = subpage_info;
- }
-
ret = btrfs_init_workqueues(fs_info);
if (ret) {
err = ret;
@@ -3783,11 +3794,6 @@ int __cold open_ctree(struct super_block *sb, char *options)
if (IS_ERR(fs_info->transaction_kthread))
goto fail_cleaner;
- if (!btrfs_test_opt(fs_info, NOSSD) &&
- !fs_info->fs_devices->rotating) {
- btrfs_set_and_info(fs_info, SSD, "enabling ssd optimizations");
- }
-
/*
* Mount does not set all options immediately, we can do it now and do
* not have to wait for transaction commit
@@ -3796,7 +3802,7 @@ int __cold open_ctree(struct super_block *sb, char *options)
#ifdef CONFIG_BTRFS_FS_CHECK_INTEGRITY
if (btrfs_test_opt(fs_info, CHECK_INTEGRITY)) {
- ret = btrfsic_mount(fs_info, fs_devices,
+ ret = btrfsic_mount(fs_info, fs_info->fs_devices,
btrfs_test_opt(fs_info,
CHECK_INTEGRITY_DATA) ? 1 : 0,
fs_info->check_integrity_print_mask);
@@ -3806,6 +3812,7 @@ int __cold open_ctree(struct super_block *sb, char *options)
ret);
}
#endif
+
ret = btrfs_read_qgroup_config(fs_info);
if (ret)
goto fail_trans_kthread;
@@ -3898,7 +3905,6 @@ int __cold open_ctree(struct super_block *sb, char *options)
fail_sb_buffer:
btrfs_stop_all_workers(fs_info);
btrfs_free_block_groups(fs_info);
-fail_alloc:
btrfs_mapping_tree_free(&fs_info->mapping_tree);
fail:
for (i = ARRAY_SIZE(open_ctree_seq) - 1; i >= 0; i--) {
This patch will extract the mount option parsing and features checking code into a new helper, open_ctree_features_init(). This extraction also did the following non-functional change: - Add btrfs_fs_info::__options member Currently the open_ctree_* helpers can only accept a single @fs_info parameter, to parse the mount options we have to use a temporary pointer for this purpose. Thankfully we don't need to do anything like freeing it. - Move ssd optimization check into open_ctree_features_init() - Move check_int related code into open_ctree_features_init() The mount time integrity check doesn't rely on any tree blocks, thus is safe to be called at feature init time. - Separate @features variable into @incompat and @compat_ro So there will be no confusion, and compiler should be clever enough to optimize them out anyway. - Properly return error for subpage initialization failure Preivously we just goto fail_alloc label, relying on the default -EINVAL error. Now we can return a proper -ENOMEM error instead. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/ctree.h | 6 +++ fs/btrfs/disk-io.c | 96 ++++++++++++++++++++++++---------------------- 2 files changed, 57 insertions(+), 45 deletions(-)