diff options
author | Azat Khuzhin <a3at.mail@gmail.com> | 2014-04-07 10:54:20 -0400 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2014-04-07 10:54:20 -0400 |
commit | 007649375f6af242d5b1df2c15996949714303ba (patch) | |
tree | bfdffb47dc55ad575b93a4ca013a397ec5751b46 /fs/ext4 | |
parent | 4adb6ab3e0fa71363a5ef229544b2d17de6600d7 (diff) |
ext4: initialize multi-block allocator before checking block descriptors
With EXT4FS_DEBUG ext4_count_free_clusters() will call
ext4_read_block_bitmap() without s_group_info initialized, so we need to
initialize multi-block allocator before.
And dependencies that must be solved, to allow this:
- multi-block allocator needs in group descriptors
- need to install s_op before initializing multi-block allocator,
because in ext4_mb_init_backend() new inode is created.
- initialize number of group desc blocks (s_gdb_count) otherwise
number of clusters returned by ext4_free_clusters_after_init() is not correct.
(see ext4_bg_num_gdb_nometa())
Here is the stack backtrace:
(gdb) bt
#0 ext4_get_group_info (group=0, sb=0xffff880079a10000) at ext4.h:2430
#1 ext4_validate_block_bitmap (sb=sb@entry=0xffff880079a10000,
desc=desc@entry=0xffff880056510000, block_group=block_group@entry=0,
bh=bh@entry=0xffff88007bf2b2d8) at balloc.c:358
#2 0xffffffff81232202 in ext4_wait_block_bitmap (sb=sb@entry=0xffff880079a10000,
block_group=block_group@entry=0,
bh=bh@entry=0xffff88007bf2b2d8) at balloc.c:476
#3 0xffffffff81232eaf in ext4_read_block_bitmap (sb=sb@entry=0xffff880079a10000,
block_group=block_group@entry=0) at balloc.c:489
#4 0xffffffff81232fc0 in ext4_count_free_clusters (sb=sb@entry=0xffff880079a10000) at balloc.c:665
#5 0xffffffff81259ffa in ext4_check_descriptors (first_not_zeroed=<synthetic pointer>,
sb=0xffff880079a10000) at super.c:2143
#6 ext4_fill_super (sb=sb@entry=0xffff880079a10000, data=<optimized out>,
data@entry=0x0 <irq_stack_union>, silent=silent@entry=0) at super.c:3851
...
Signed-off-by: Azat Khuzhin <a3at.mail@gmail.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/super.c | 51 |
1 files changed, 27 insertions, 24 deletions
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index f3c667091618..6f9e6fadac04 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -3869,19 +3869,38 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3869 | goto failed_mount2; | 3869 | goto failed_mount2; |
3870 | } | 3870 | } |
3871 | } | 3871 | } |
3872 | |||
3873 | /* | ||
3874 | * set up enough so that it can read an inode, | ||
3875 | * and create new inode for buddy allocator | ||
3876 | */ | ||
3877 | sbi->s_gdb_count = db_count; | ||
3878 | if (!test_opt(sb, NOLOAD) && | ||
3879 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) | ||
3880 | sb->s_op = &ext4_sops; | ||
3881 | else | ||
3882 | sb->s_op = &ext4_nojournal_sops; | ||
3883 | |||
3884 | ext4_ext_init(sb); | ||
3885 | err = ext4_mb_init(sb); | ||
3886 | if (err) { | ||
3887 | ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", | ||
3888 | err); | ||
3889 | goto failed_mount2; | ||
3890 | } | ||
3891 | |||
3872 | if (!ext4_check_descriptors(sb, &first_not_zeroed)) { | 3892 | if (!ext4_check_descriptors(sb, &first_not_zeroed)) { |
3873 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); | 3893 | ext4_msg(sb, KERN_ERR, "group descriptors corrupted!"); |
3874 | goto failed_mount2; | 3894 | goto failed_mount2a; |
3875 | } | 3895 | } |
3876 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) | 3896 | if (EXT4_HAS_INCOMPAT_FEATURE(sb, EXT4_FEATURE_INCOMPAT_FLEX_BG)) |
3877 | if (!ext4_fill_flex_info(sb)) { | 3897 | if (!ext4_fill_flex_info(sb)) { |
3878 | ext4_msg(sb, KERN_ERR, | 3898 | ext4_msg(sb, KERN_ERR, |
3879 | "unable to initialize " | 3899 | "unable to initialize " |
3880 | "flex_bg meta info!"); | 3900 | "flex_bg meta info!"); |
3881 | goto failed_mount2; | 3901 | goto failed_mount2a; |
3882 | } | 3902 | } |
3883 | 3903 | ||
3884 | sbi->s_gdb_count = db_count; | ||
3885 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | 3904 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); |
3886 | spin_lock_init(&sbi->s_next_gen_lock); | 3905 | spin_lock_init(&sbi->s_next_gen_lock); |
3887 | 3906 | ||
@@ -3916,14 +3935,6 @@ static int ext4_fill_super(struct super_block *sb, void *data, int silent) | |||
3916 | sbi->s_stripe = ext4_get_stripe_size(sbi); | 3935 | sbi->s_stripe = ext4_get_stripe_size(sbi); |
3917 | sbi->s_extent_max_zeroout_kb = 32; | 3936 | sbi->s_extent_max_zeroout_kb = 32; |
3918 | 3937 | ||
3919 | /* | ||
3920 | * set up enough so that it can read an inode | ||
3921 | */ | ||
3922 | if (!test_opt(sb, NOLOAD) && | ||
3923 | EXT4_HAS_COMPAT_FEATURE(sb, EXT4_FEATURE_COMPAT_HAS_JOURNAL)) | ||
3924 | sb->s_op = &ext4_sops; | ||
3925 | else | ||
3926 | sb->s_op = &ext4_nojournal_sops; | ||
3927 | sb->s_export_op = &ext4_export_ops; | 3938 | sb->s_export_op = &ext4_export_ops; |
3928 | sb->s_xattr = ext4_xattr_handlers; | 3939 | sb->s_xattr = ext4_xattr_handlers; |
3929 | #ifdef CONFIG_QUOTA | 3940 | #ifdef CONFIG_QUOTA |
@@ -4113,21 +4124,13 @@ no_journal: | |||
4113 | if (err) { | 4124 | if (err) { |
4114 | ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " | 4125 | ext4_msg(sb, KERN_ERR, "failed to reserve %llu clusters for " |
4115 | "reserved pool", ext4_calculate_resv_clusters(sb)); | 4126 | "reserved pool", ext4_calculate_resv_clusters(sb)); |
4116 | goto failed_mount4a; | 4127 | goto failed_mount5; |
4117 | } | 4128 | } |
4118 | 4129 | ||
4119 | err = ext4_setup_system_zone(sb); | 4130 | err = ext4_setup_system_zone(sb); |
4120 | if (err) { | 4131 | if (err) { |
4121 | ext4_msg(sb, KERN_ERR, "failed to initialize system " | 4132 | ext4_msg(sb, KERN_ERR, "failed to initialize system " |
4122 | "zone (%d)", err); | 4133 | "zone (%d)", err); |
4123 | goto failed_mount4a; | ||
4124 | } | ||
4125 | |||
4126 | ext4_ext_init(sb); | ||
4127 | err = ext4_mb_init(sb); | ||
4128 | if (err) { | ||
4129 | ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)", | ||
4130 | err); | ||
4131 | goto failed_mount5; | 4134 | goto failed_mount5; |
4132 | } | 4135 | } |
4133 | 4136 | ||
@@ -4204,11 +4207,8 @@ failed_mount8: | |||
4204 | failed_mount7: | 4207 | failed_mount7: |
4205 | ext4_unregister_li_request(sb); | 4208 | ext4_unregister_li_request(sb); |
4206 | failed_mount6: | 4209 | failed_mount6: |
4207 | ext4_mb_release(sb); | ||
4208 | failed_mount5: | ||
4209 | ext4_ext_release(sb); | ||
4210 | ext4_release_system_zone(sb); | 4210 | ext4_release_system_zone(sb); |
4211 | failed_mount4a: | 4211 | failed_mount5: |
4212 | dput(sb->s_root); | 4212 | dput(sb->s_root); |
4213 | sb->s_root = NULL; | 4213 | sb->s_root = NULL; |
4214 | failed_mount4: | 4214 | failed_mount4: |
@@ -4232,11 +4232,14 @@ failed_mount3: | |||
4232 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); | 4232 | percpu_counter_destroy(&sbi->s_extent_cache_cnt); |
4233 | if (sbi->s_mmp_tsk) | 4233 | if (sbi->s_mmp_tsk) |
4234 | kthread_stop(sbi->s_mmp_tsk); | 4234 | kthread_stop(sbi->s_mmp_tsk); |
4235 | failed_mount2a: | ||
4236 | ext4_mb_release(sb); | ||
4235 | failed_mount2: | 4237 | failed_mount2: |
4236 | for (i = 0; i < db_count; i++) | 4238 | for (i = 0; i < db_count; i++) |
4237 | brelse(sbi->s_group_desc[i]); | 4239 | brelse(sbi->s_group_desc[i]); |
4238 | ext4_kvfree(sbi->s_group_desc); | 4240 | ext4_kvfree(sbi->s_group_desc); |
4239 | failed_mount: | 4241 | failed_mount: |
4242 | ext4_ext_release(sb); | ||
4240 | if (sbi->s_chksum_driver) | 4243 | if (sbi->s_chksum_driver) |
4241 | crypto_free_shash(sbi->s_chksum_driver); | 4244 | crypto_free_shash(sbi->s_chksum_driver); |
4242 | if (sbi->s_proc) { | 4245 | if (sbi->s_proc) { |