@@ -3448,55 +3448,18 @@ static void open_ctree_btree_inode_exit(struct btrfs_fs_info *fs_info)
fs_info->chunk_root = NULL;
}
-struct init_sequence {
- int (*init_func)(struct btrfs_fs_info *fs_info);
- void (*exit_func)(struct btrfs_fs_info *fs_info);
-};
-
-static const struct init_sequence open_ctree_seq[] = {
- {
- .init_func = open_ctree_btree_inode_init,
- .exit_func = open_ctree_btree_inode_exit,
- }
-};
-
-int __cold open_ctree(struct super_block *sb, char *options)
+static int open_ctree_super_init(struct btrfs_fs_info *fs_info)
{
- u32 sectorsize;
+ struct btrfs_super_block *disk_super;
u32 nodesize;
- u32 stripesize;
- u64 generation;
- u64 features;
+ u32 sectorsize;
u16 csum_type;
- bool open_ctree_res[ARRAY_SIZE(open_ctree_seq)] = {0};
- struct btrfs_super_block *disk_super;
- struct btrfs_fs_info *fs_info = btrfs_sb(sb);
- struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
int ret;
- int err = -EINVAL;
- int level;
- int i;
- fs_info->sb = sb;
-
- /* Caller should have already initialized fs_info->fs_devices. */
- ASSERT(fs_info->fs_devices);
-
- for (i = 0; i < ARRAY_SIZE(open_ctree_seq); i++) {
- ret = open_ctree_seq[i].init_func(fs_info);
- if (ret < 0)
- goto fail;
- open_ctree_res[i] = true;
- }
-
- /*
- * Read super block and check the signature bytes only
- */
- disk_super = btrfs_read_dev_super(fs_devices->latest_dev->bdev);
- if (IS_ERR(disk_super)) {
- err = PTR_ERR(disk_super);
- goto fail_alloc;
- }
+ /* Read super block and check the signature bytes only */
+ disk_super = btrfs_read_dev_super(fs_info->fs_devices->latest_dev->bdev);
+ if (IS_ERR(disk_super))
+ return PTR_ERR(disk_super);
/*
* Verify the type first, if that or the checksum value are
@@ -3506,19 +3469,15 @@ int __cold open_ctree(struct super_block *sb, char *options)
if (!btrfs_supported_super_csum(csum_type)) {
btrfs_err(fs_info, "unsupported checksum algorithm: %u",
csum_type);
- err = -EINVAL;
- btrfs_release_disk_super(disk_super);
- goto fail_alloc;
+ ret = -EINVAL;
+ goto error;
}
fs_info->csum_size = btrfs_super_csum_size(disk_super);
ret = btrfs_init_csum_hash(fs_info, csum_type);
- if (ret) {
- err = ret;
- btrfs_release_disk_super(disk_super);
- goto fail_alloc;
- }
+ if (ret)
+ goto error;
/*
* We want to check superblock checksum, the type is stored inside.
@@ -3526,9 +3485,8 @@ int __cold open_ctree(struct super_block *sb, char *options)
*/
if (btrfs_check_super_csum(fs_info, (u8 *)disk_super)) {
btrfs_err(fs_info, "superblock checksum mismatch");
- err = -EINVAL;
- btrfs_release_disk_super(disk_super);
- goto fail_alloc;
+ ret = -EINVAL;
+ goto error;
}
/*
@@ -3536,33 +3494,30 @@ int __cold open_ctree(struct super_block *sb, char *options)
* following bytes up to INFO_SIZE, the checksum is calculated from
* the whole block of INFO_SIZE
*/
- memcpy(fs_info->super_copy, disk_super, sizeof(*fs_info->super_copy));
+ memcpy(fs_info->super_copy, disk_super, BTRFS_SUPER_INFO_SIZE);
btrfs_release_disk_super(disk_super);
- disk_super = fs_info->super_copy;
-
-
- features = btrfs_super_flags(disk_super);
- if (features & BTRFS_SUPER_FLAG_CHANGING_FSID_V2) {
- features &= ~BTRFS_SUPER_FLAG_CHANGING_FSID_V2;
- btrfs_set_super_flags(disk_super, features);
+ if (btrfs_super_flags(fs_info->super_copy) &
+ BTRFS_SUPER_FLAG_CHANGING_FSID_V2) {
+ btrfs_set_super_flags(fs_info->super_copy,
+ btrfs_super_flags(fs_info->super_copy) &
+ ~BTRFS_SUPER_FLAG_CHANGING_FSID_V2);
btrfs_info(fs_info,
"found metadata UUID change in progress flag, clearing");
}
-
memcpy(fs_info->super_for_commit, fs_info->super_copy,
- sizeof(*fs_info->super_for_commit));
-
+ BTRFS_SUPER_INFO_SIZE);
ret = btrfs_validate_mount_super(fs_info);
- if (ret) {
+ if (ret < 0) {
btrfs_err(fs_info, "superblock contains fatal errors");
- err = -EINVAL;
- goto fail_alloc;
+ return -EINVAL;
}
- if (!btrfs_super_root(disk_super))
- goto fail_alloc;
-
+ if (!btrfs_super_root(fs_info->super_copy)) {
+ btrfs_err(fs_info,
+ "invalid super root bytenr, should have non-zero bytenr");
+ return -EINVAL;
+ }
/* check FS state, whether FS is broken. */
if (btrfs_super_flags(disk_super) & BTRFS_SUPER_FLAG_ERROR)
set_bit(BTRFS_FS_STATE_ERROR, &fs_info->fs_state);
@@ -3573,11 +3528,9 @@ int __cold open_ctree(struct super_block *sb, char *options)
*/
fs_info->compress_type = BTRFS_COMPRESS_ZLIB;
-
/* Set up fs_info before parsing mount options */
nodesize = btrfs_super_nodesize(disk_super);
sectorsize = btrfs_super_sectorsize(disk_super);
- stripesize = sectorsize;
fs_info->dirty_metadata_batch = nodesize * (1 + ilog2(nr_cpu_ids));
fs_info->delalloc_batch = sectorsize * 512 * (1 + ilog2(nr_cpu_ids));
@@ -3585,7 +3538,60 @@ int __cold open_ctree(struct super_block *sb, char *options)
fs_info->sectorsize = sectorsize;
fs_info->sectorsize_bits = ilog2(sectorsize);
fs_info->csums_per_leaf = BTRFS_MAX_ITEM_SIZE(fs_info) / fs_info->csum_size;
- fs_info->stripesize = stripesize;
+ fs_info->stripesize = sectorsize;
+
+ fs_info->sb->s_bdi->ra_pages *= btrfs_super_num_devices(fs_info->super_copy);
+ fs_info->sb->s_bdi->ra_pages = max(fs_info->sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
+
+ fs_info->sb->s_blocksize = sectorsize;
+ fs_info->sb->s_blocksize_bits = blksize_bits(sectorsize);
+ memcpy(&fs_info->sb->s_uuid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE);
+
+ return 0;
+
+error:
+ btrfs_release_disk_super(disk_super);
+ return ret;
+}
+
+struct init_sequence {
+ int (*init_func)(struct btrfs_fs_info *fs_info);
+ void (*exit_func)(struct btrfs_fs_info *fs_info);
+};
+
+static const struct init_sequence open_ctree_seq[] = {
+ {
+ .init_func = open_ctree_btree_inode_init,
+ .exit_func = open_ctree_btree_inode_exit,
+ }, {
+ .init_func = open_ctree_super_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;
+ int ret;
+ int err = -EINVAL;
+ int level;
+ int i;
+
+ fs_info->sb = sb;
+
+ /* Caller should have already initialized fs_info->fs_devices. */
+ ASSERT(fs_info->fs_devices);
+
+ for (i = 0; i < ARRAY_SIZE(open_ctree_seq); i++) {
+ ret = open_ctree_seq[i].init_func(fs_info);
+ if (ret < 0)
+ goto fail;
+ open_ctree_res[i] = true;
+ }
ret = btrfs_parse_options(fs_info, options, fs_info->sb->s_flags);
if (ret) {
@@ -3599,7 +3605,7 @@ int __cold open_ctree(struct super_block *sb, char *options)
goto fail_alloc;
}
- if (sectorsize < PAGE_SIZE) {
+ if (fs_info->sectorsize < PAGE_SIZE) {
struct btrfs_subpage_info *subpage_info;
/*
@@ -3611,15 +3617,15 @@ int __cold open_ctree(struct super_block *sb, char *options)
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",
- sectorsize, PAGE_SIZE);
+ fs_info->sectorsize, PAGE_SIZE);
btrfs_warn(fs_info,
"read-write for sector size %u with page size %lu is experimental",
- sectorsize, PAGE_SIZE);
+ 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, sectorsize);
+ btrfs_init_subpage_info(subpage_info, fs_info->sectorsize);
fs_info->subpage_info = subpage_info;
}
@@ -3629,13 +3635,6 @@ int __cold open_ctree(struct super_block *sb, char *options)
goto fail_sb_buffer;
}
- fs_info->sb->s_bdi->ra_pages *= btrfs_super_num_devices(disk_super);
- fs_info->sb->s_bdi->ra_pages = max(fs_info->sb->s_bdi->ra_pages, SZ_4M / PAGE_SIZE);
-
- fs_info->sb->s_blocksize = sectorsize;
- fs_info->sb->s_blocksize_bits = blksize_bits(sectorsize);
- memcpy(&fs_info->sb->s_uuid, fs_info->fs_devices->fsid, BTRFS_FSID_SIZE);
-
mutex_lock(&fs_info->chunk_mutex);
ret = btrfs_read_sys_array(fs_info);
mutex_unlock(&fs_info->chunk_mutex);
@@ -3644,10 +3643,10 @@ int __cold open_ctree(struct super_block *sb, char *options)
goto fail_sb_buffer;
}
- generation = btrfs_super_chunk_root_generation(disk_super);
- level = btrfs_super_chunk_root_level(disk_super);
+ generation = btrfs_super_chunk_root_generation(fs_info->super_copy);
+ level = btrfs_super_chunk_root_level(fs_info->super_copy);
ret = load_super_root(fs_info->chunk_root,
- btrfs_super_chunk_root(disk_super),
+ btrfs_super_chunk_root(fs_info->super_copy),
generation, level);
if (ret) {
btrfs_err(fs_info, "failed to read chunk root");
@@ -3703,7 +3702,8 @@ int __cold open_ctree(struct super_block *sb, char *options)
* even though it was perfectly fine.
*/
if (fs_info->uuid_root && !btrfs_test_opt(fs_info, RESCAN_UUID_TREE) &&
- fs_info->generation == btrfs_super_uuid_tree_generation(disk_super))
+ fs_info->generation ==
+ btrfs_super_uuid_tree_generation(fs_info->super_copy))
set_bit(BTRFS_FS_UPDATE_UUID_TREE_GEN, &fs_info->flags);
ret = btrfs_verify_dev_extents(fs_info);
@@ -3814,7 +3814,7 @@ int __cold open_ctree(struct super_block *sb, char *options)
btrfs_err(fs_info, "couldn't build ref tree");
/* do not make disk changes in broken FS or nologreplay is given */
- if (btrfs_super_log_root(disk_super) != 0 &&
+ if (btrfs_super_log_root(fs_info->super_copy) != 0 &&
!btrfs_test_opt(fs_info, NOLOGREPLAY)) {
btrfs_info(fs_info, "start tree-log replay");
ret = btrfs_replay_log(fs_info, fs_devices);
@@ -3844,7 +3844,8 @@ int __cold open_ctree(struct super_block *sb, char *options)
if (fs_info->uuid_root &&
(btrfs_test_opt(fs_info, RESCAN_UUID_TREE) ||
- fs_info->generation != btrfs_super_uuid_tree_generation(disk_super))) {
+ fs_info->generation !=
+ btrfs_super_uuid_tree_generation(fs_info->super_copy))) {
btrfs_info(fs_info, "checking UUID tree");
ret = btrfs_check_uuid_tree(fs_info);
if (ret) {
This patch will extract the super block read and cached members (sectorsize/nodesize/etc) initialization into a helper, open_ctree_super_init(). This extraction also did the following non-functional change: - Add an error message for super_root == 0 case Previously we just goto fail_alloc, with ret == 0. This can be very confusing and would cause problems since we didn't finish the mount at all. - Move sb->s_blocksize and sb->s_bdi initialization into the new helper Since at this stage we already have valid super block and its sectorsize, we can directly initialize them here. Signed-off-by: Qu Wenruo <wqu@suse.com> --- fs/btrfs/disk-io.c | 185 +++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 92 deletions(-)