[PATCH] ext4: move ext4_percpu_param_init() before ext4_mb_init()

libaokun@huaweicloud.com posted 1 patch 1 week, 2 days ago
fs/ext4/super.c | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
[PATCH] ext4: move ext4_percpu_param_init() before ext4_mb_init()
Posted by libaokun@huaweicloud.com 1 week, 2 days ago
From: Baokun Li <libaokun1@huawei.com>

When running `kvm-xfstests -c ext4/1k -C 1 generic/383` with the
`DOUBLE_CHECK` macro defined, the following panic is triggered:

==================================================================
EXT4-fs error (device vdc): ext4_validate_block_bitmap:423:
                        comm mount: bg 0: bad block bitmap checksum
BUG: unable to handle page fault for address: ff110000fa2cc000
PGD 3e01067 P4D 3e02067 PUD 0
Oops: Oops: 0000 [#1] SMP NOPTI
CPU: 0 UID: 0 PID: 2386 Comm: mount Tainted: G W
                        6.18.0-gba65a4e7120a-dirty #1152 PREEMPT(none)
RIP: 0010:percpu_counter_add_batch+0x13/0xa0
Call Trace:
 <TASK>
 ext4_mark_group_bitmap_corrupted+0xcb/0xe0
 ext4_validate_block_bitmap+0x2a1/0x2f0
 ext4_read_block_bitmap+0x33/0x50
 mb_group_bb_bitmap_alloc+0x33/0x80
 ext4_mb_add_groupinfo+0x190/0x250
 ext4_mb_init_backend+0x87/0x290
 ext4_mb_init+0x456/0x640
 __ext4_fill_super+0x1072/0x1680
 ext4_fill_super+0xd3/0x280
 get_tree_bdev_flags+0x132/0x1d0
 vfs_get_tree+0x29/0xd0
 vfs_cmd_create+0x59/0xe0
 __do_sys_fsconfig+0x4f6/0x6b0
 do_syscall_64+0x50/0x1f0
 entry_SYSCALL_64_after_hwframe+0x76/0x7e
==================================================================

This issue can be reproduced using the following commands:
        mkfs.ext4 -F -q -b 1024 /dev/sda 5G
        tune2fs -O quota,project /dev/sda
        mount /dev/sda /tmp/test

With DOUBLE_CHECK defined, mb_group_bb_bitmap_alloc() reads
and validates the block bitmap. When the validation fails,
ext4_mark_group_bitmap_corrupted() attempts to update
sbi->s_freeclusters_counter. However, this percpu_counter has not been
initialized yet at this point, which leads to the panic described above.

Fix this by moving the execution of ext4_percpu_param_init() to occur
before ext4_mb_init(), ensuring the per-CPU counters are initialized
before they are used.

Signed-off-by: Baokun Li <libaokun1@huawei.com>
---
 fs/ext4/super.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 87205660c5d0..5c2e931d8a53 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5599,35 +5599,35 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
 	 */
 	if (!(ctx->spec & EXT4_SPEC_mb_optimize_scan)) {
 		if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD)
 			set_opt2(sb, MB_OPTIMIZE_SCAN);
 		else
 			clear_opt2(sb, MB_OPTIMIZE_SCAN);
 	}
 
+	err = ext4_percpu_param_init(sbi);
+	if (err)
+		goto failed_mount5;
+
 	err = ext4_mb_init(sb);
 	if (err) {
 		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
 			 err);
 		goto failed_mount5;
 	}
 
 	/*
 	 * We can only set up the journal commit callback once
 	 * mballoc is initialized
 	 */
 	if (sbi->s_journal)
 		sbi->s_journal->j_commit_callback =
 			ext4_journal_commit_callback;
 
-	err = ext4_percpu_param_init(sbi);
-	if (err)
-		goto failed_mount6;
-
 	if (ext4_has_feature_flex_bg(sb))
 		if (!ext4_fill_flex_info(sb)) {
 			ext4_msg(sb, KERN_ERR,
 			       "unable to initialize "
 			       "flex_bg meta info!");
 			err = -ENOMEM;
 			goto failed_mount6;
 		}
@@ -5699,18 +5699,18 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
 	ext4_quotas_off(sb, EXT4_MAXQUOTAS);
 failed_mount8: __maybe_unused
 	ext4_release_orphan_info(sb);
 failed_mount7:
 	ext4_unregister_li_request(sb);
 failed_mount6:
 	ext4_mb_release(sb);
 	ext4_flex_groups_free(sbi);
-	ext4_percpu_param_destroy(sbi);
 failed_mount5:
+	ext4_percpu_param_destroy(sbi);
 	ext4_ext_release(sb);
 	ext4_release_system_zone(sb);
 failed_mount4a:
 	dput(sb->s_root);
 	sb->s_root = NULL;
 failed_mount4:
 	ext4_msg(sb, KERN_ERR, "mount failed");
 	if (EXT4_SB(sb)->rsv_conversion_wq)
-- 
2.39.2
Re: [PATCH] ext4: move ext4_percpu_param_init() before ext4_mb_init()
Posted by Zhang Yi 1 week ago
On 12/9/2025 9:31 PM, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
> 
> When running `kvm-xfstests -c ext4/1k -C 1 generic/383` with the
> `DOUBLE_CHECK` macro defined, the following panic is triggered:
> 
> ==================================================================
> EXT4-fs error (device vdc): ext4_validate_block_bitmap:423:
>                         comm mount: bg 0: bad block bitmap checksum
> BUG: unable to handle page fault for address: ff110000fa2cc000
> PGD 3e01067 P4D 3e02067 PUD 0
> Oops: Oops: 0000 [#1] SMP NOPTI
> CPU: 0 UID: 0 PID: 2386 Comm: mount Tainted: G W
>                         6.18.0-gba65a4e7120a-dirty #1152 PREEMPT(none)
> RIP: 0010:percpu_counter_add_batch+0x13/0xa0
> Call Trace:
>  <TASK>
>  ext4_mark_group_bitmap_corrupted+0xcb/0xe0
>  ext4_validate_block_bitmap+0x2a1/0x2f0
>  ext4_read_block_bitmap+0x33/0x50
>  mb_group_bb_bitmap_alloc+0x33/0x80
>  ext4_mb_add_groupinfo+0x190/0x250
>  ext4_mb_init_backend+0x87/0x290
>  ext4_mb_init+0x456/0x640
>  __ext4_fill_super+0x1072/0x1680
>  ext4_fill_super+0xd3/0x280
>  get_tree_bdev_flags+0x132/0x1d0
>  vfs_get_tree+0x29/0xd0
>  vfs_cmd_create+0x59/0xe0
>  __do_sys_fsconfig+0x4f6/0x6b0
>  do_syscall_64+0x50/0x1f0
>  entry_SYSCALL_64_after_hwframe+0x76/0x7e
> ==================================================================
> 
> This issue can be reproduced using the following commands:
>         mkfs.ext4 -F -q -b 1024 /dev/sda 5G
>         tune2fs -O quota,project /dev/sda
>         mount /dev/sda /tmp/test
> 
> With DOUBLE_CHECK defined, mb_group_bb_bitmap_alloc() reads
> and validates the block bitmap. When the validation fails,
> ext4_mark_group_bitmap_corrupted() attempts to update
> sbi->s_freeclusters_counter. However, this percpu_counter has not been
> initialized yet at this point, which leads to the panic described above.
> 
> Fix this by moving the execution of ext4_percpu_param_init() to occur
> before ext4_mb_init(), ensuring the per-CPU counters are initialized
> before they are used.
> 
> Signed-off-by: Baokun Li <libaokun1@huawei.com>

Looks good to me.

Reviewed-by: Zhang Yi <yi.zhang@huawei.com>

> ---
>  fs/ext4/super.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 87205660c5d0..5c2e931d8a53 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -5599,35 +5599,35 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
>  	 */
>  	if (!(ctx->spec & EXT4_SPEC_mb_optimize_scan)) {
>  		if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD)
>  			set_opt2(sb, MB_OPTIMIZE_SCAN);
>  		else
>  			clear_opt2(sb, MB_OPTIMIZE_SCAN);
>  	}
>  
> +	err = ext4_percpu_param_init(sbi);
> +	if (err)
> +		goto failed_mount5;
> +
>  	err = ext4_mb_init(sb);
>  	if (err) {
>  		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
>  			 err);
>  		goto failed_mount5;
>  	}
>  
>  	/*
>  	 * We can only set up the journal commit callback once
>  	 * mballoc is initialized
>  	 */
>  	if (sbi->s_journal)
>  		sbi->s_journal->j_commit_callback =
>  			ext4_journal_commit_callback;
>  
> -	err = ext4_percpu_param_init(sbi);
> -	if (err)
> -		goto failed_mount6;
> -
>  	if (ext4_has_feature_flex_bg(sb))
>  		if (!ext4_fill_flex_info(sb)) {
>  			ext4_msg(sb, KERN_ERR,
>  			       "unable to initialize "
>  			       "flex_bg meta info!");
>  			err = -ENOMEM;
>  			goto failed_mount6;
>  		}
> @@ -5699,18 +5699,18 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
>  	ext4_quotas_off(sb, EXT4_MAXQUOTAS);
>  failed_mount8: __maybe_unused
>  	ext4_release_orphan_info(sb);
>  failed_mount7:
>  	ext4_unregister_li_request(sb);
>  failed_mount6:
>  	ext4_mb_release(sb);
>  	ext4_flex_groups_free(sbi);
> -	ext4_percpu_param_destroy(sbi);
>  failed_mount5:
> +	ext4_percpu_param_destroy(sbi);
>  	ext4_ext_release(sb);
>  	ext4_release_system_zone(sb);
>  failed_mount4a:
>  	dput(sb->s_root);
>  	sb->s_root = NULL;
>  failed_mount4:
>  	ext4_msg(sb, KERN_ERR, "mount failed");
>  	if (EXT4_SB(sb)->rsv_conversion_wq)
Re: [PATCH] ext4: move ext4_percpu_param_init() before ext4_mb_init()
Posted by Jan Kara 1 week, 1 day ago
On Tue 09-12-25 21:31:16, libaokun@huaweicloud.com wrote:
> From: Baokun Li <libaokun1@huawei.com>
> 
> When running `kvm-xfstests -c ext4/1k -C 1 generic/383` with the
> `DOUBLE_CHECK` macro defined, the following panic is triggered:
> 
> ==================================================================
> EXT4-fs error (device vdc): ext4_validate_block_bitmap:423:
>                         comm mount: bg 0: bad block bitmap checksum
> BUG: unable to handle page fault for address: ff110000fa2cc000
> PGD 3e01067 P4D 3e02067 PUD 0
> Oops: Oops: 0000 [#1] SMP NOPTI
> CPU: 0 UID: 0 PID: 2386 Comm: mount Tainted: G W
>                         6.18.0-gba65a4e7120a-dirty #1152 PREEMPT(none)
> RIP: 0010:percpu_counter_add_batch+0x13/0xa0
> Call Trace:
>  <TASK>
>  ext4_mark_group_bitmap_corrupted+0xcb/0xe0
>  ext4_validate_block_bitmap+0x2a1/0x2f0
>  ext4_read_block_bitmap+0x33/0x50
>  mb_group_bb_bitmap_alloc+0x33/0x80
>  ext4_mb_add_groupinfo+0x190/0x250
>  ext4_mb_init_backend+0x87/0x290
>  ext4_mb_init+0x456/0x640
>  __ext4_fill_super+0x1072/0x1680
>  ext4_fill_super+0xd3/0x280
>  get_tree_bdev_flags+0x132/0x1d0
>  vfs_get_tree+0x29/0xd0
>  vfs_cmd_create+0x59/0xe0
>  __do_sys_fsconfig+0x4f6/0x6b0
>  do_syscall_64+0x50/0x1f0
>  entry_SYSCALL_64_after_hwframe+0x76/0x7e
> ==================================================================
> 
> This issue can be reproduced using the following commands:
>         mkfs.ext4 -F -q -b 1024 /dev/sda 5G
>         tune2fs -O quota,project /dev/sda
>         mount /dev/sda /tmp/test
> 
> With DOUBLE_CHECK defined, mb_group_bb_bitmap_alloc() reads
> and validates the block bitmap. When the validation fails,
> ext4_mark_group_bitmap_corrupted() attempts to update
> sbi->s_freeclusters_counter. However, this percpu_counter has not been
> initialized yet at this point, which leads to the panic described above.
> 
> Fix this by moving the execution of ext4_percpu_param_init() to occur
> before ext4_mb_init(), ensuring the per-CPU counters are initialized
> before they are used.
> 
> Signed-off-by: Baokun Li <libaokun1@huawei.com>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@suse.cz>

								Honza

> ---
>  fs/ext4/super.c | 10 +++++-----
>  1 file changed, 5 insertions(+), 5 deletions(-)
> 
> diff --git a/fs/ext4/super.c b/fs/ext4/super.c
> index 87205660c5d0..5c2e931d8a53 100644
> --- a/fs/ext4/super.c
> +++ b/fs/ext4/super.c
> @@ -5599,35 +5599,35 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
>  	 */
>  	if (!(ctx->spec & EXT4_SPEC_mb_optimize_scan)) {
>  		if (sbi->s_groups_count >= MB_DEFAULT_LINEAR_SCAN_THRESHOLD)
>  			set_opt2(sb, MB_OPTIMIZE_SCAN);
>  		else
>  			clear_opt2(sb, MB_OPTIMIZE_SCAN);
>  	}
>  
> +	err = ext4_percpu_param_init(sbi);
> +	if (err)
> +		goto failed_mount5;
> +
>  	err = ext4_mb_init(sb);
>  	if (err) {
>  		ext4_msg(sb, KERN_ERR, "failed to initialize mballoc (%d)",
>  			 err);
>  		goto failed_mount5;
>  	}
>  
>  	/*
>  	 * We can only set up the journal commit callback once
>  	 * mballoc is initialized
>  	 */
>  	if (sbi->s_journal)
>  		sbi->s_journal->j_commit_callback =
>  			ext4_journal_commit_callback;
>  
> -	err = ext4_percpu_param_init(sbi);
> -	if (err)
> -		goto failed_mount6;
> -
>  	if (ext4_has_feature_flex_bg(sb))
>  		if (!ext4_fill_flex_info(sb)) {
>  			ext4_msg(sb, KERN_ERR,
>  			       "unable to initialize "
>  			       "flex_bg meta info!");
>  			err = -ENOMEM;
>  			goto failed_mount6;
>  		}
> @@ -5699,18 +5699,18 @@ static int __ext4_fill_super(struct fs_context *fc, struct super_block *sb)
>  	ext4_quotas_off(sb, EXT4_MAXQUOTAS);
>  failed_mount8: __maybe_unused
>  	ext4_release_orphan_info(sb);
>  failed_mount7:
>  	ext4_unregister_li_request(sb);
>  failed_mount6:
>  	ext4_mb_release(sb);
>  	ext4_flex_groups_free(sbi);
> -	ext4_percpu_param_destroy(sbi);
>  failed_mount5:
> +	ext4_percpu_param_destroy(sbi);
>  	ext4_ext_release(sb);
>  	ext4_release_system_zone(sb);
>  failed_mount4a:
>  	dput(sb->s_root);
>  	sb->s_root = NULL;
>  failed_mount4:
>  	ext4_msg(sb, KERN_ERR, "mount failed");
>  	if (EXT4_SB(sb)->rsv_conversion_wq)
> -- 
> 2.39.2
> 
-- 
Jan Kara <jack@suse.com>
SUSE Labs, CR