From: Baokun Li <libaokun1@huawei.com>
To: Jan Kara <jack@suse.cz>
Cc: <linux-ext4@vger.kernel.org>, <tytso@mit.edu>,
<adilger.kernel@dilger.ca>, <ojaswin@linux.ibm.com>,
<linux-kernel@vger.kernel.org>, <yi.zhang@huawei.com>,
<yangerkun@huawei.com>, <stable@vger.kernel.org>,
Baokun Li <libaokun1@huawei.com>
Subject: Re: [PATCH v2 10/16] ext4: fix largest free orders lists corruption on mb_optimize_scan switch
Date: Mon, 30 Jun 2025 15:34:30 +0800 [thread overview]
Message-ID: <5bf464c0-5cfe-4e29-8138-4fb85c83f5bb@huawei.com> (raw)
In-Reply-To: <a4rctz75l4c6vejweqq67ptzojs276eicqp6kqegpxinirk32n@dnhg6h4pbvdr>
On 2025/6/28 3:34, Jan Kara wrote:
> On Mon 23-06-25 15:32:58, Baokun Li wrote:
>> The grp->bb_largest_free_order is updated regardless of whether
>> mb_optimize_scan is enabled. This can lead to inconsistencies between
>> grp->bb_largest_free_order and the actual s_mb_largest_free_orders list
>> index when mb_optimize_scan is repeatedly enabled and disabled via remount.
>>
>> For example, if mb_optimize_scan is initially enabled, largest free
>> order is 3, and the group is in s_mb_largest_free_orders[3]. Then,
>> mb_optimize_scan is disabled via remount, block allocations occur,
>> updating largest free order to 2. Finally, mb_optimize_scan is re-enabled
>> via remount, more block allocations update largest free order to 1.
>>
>> At this point, the group would be removed from s_mb_largest_free_orders[3]
>> under the protection of s_mb_largest_free_orders_locks[2]. This lock
>> mismatch can lead to list corruption.
>>
>> To fix this, a new field bb_largest_free_order_idx is added to struct
>> ext4_group_info to explicitly track the list index. Then still update
>> bb_largest_free_order unconditionally, but only update
>> bb_largest_free_order_idx when mb_optimize_scan is enabled. so that there
>> is no inconsistency between the lock and the data to be protected.
>>
>> Fixes: 196e402adf2e ("ext4: improve cr 0 / cr 1 group scanning")
>> CC: stable@vger.kernel.org
>> Signed-off-by: Baokun Li <libaokun1@huawei.com>
> Hum, rather than duplicating index like this, couldn't we add to
> mb_set_largest_free_order():
>
> /* Did mb_optimize_scan setting change? */
> if (!test_opt2(sb, MB_OPTIMIZE_SCAN) &&
> !list_empty(&grp->bb_largest_free_order_node)) {
> write_lock(&sbi->s_mb_largest_free_orders_locks[old]);
> list_del_init(&grp->bb_largest_free_order_node);
> write_unlock(&sbi->s_mb_largest_free_orders_locks[old]);
> }
>
> Also arguably we should reinit bb lists when mb_optimize_scan gets
> reenabled because otherwise inconsistent lists could lead to suboptimal
> results... But that's less important to fix I guess.
>
> Honza
Yeah, this looks good. We just need to remove groups modified when
mb_optimize_scan=0 from the list. Groups that remain in the list after
mb_optimize_scan is re-enabled can be used normally.
As for the groups that were removed, they will be re-added to their
corresponding lists during block freeing or block allocation when
cr >= CR_GOAL_LEN_SLOW. So, I agree that we don't need to explicitly
reinit them.
Cheers,
Baokun
>> ---
>> fs/ext4/ext4.h | 1 +
>> fs/ext4/mballoc.c | 35 ++++++++++++++++-------------------
>> 2 files changed, 17 insertions(+), 19 deletions(-)
>>
>> diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
>> index 003b8d3726e8..0e574378c6a3 100644
>> --- a/fs/ext4/ext4.h
>> +++ b/fs/ext4/ext4.h
>> @@ -3476,6 +3476,7 @@ struct ext4_group_info {
>> int bb_avg_fragment_size_order; /* order of average
>> fragment in BG */
>> ext4_grpblk_t bb_largest_free_order;/* order of largest frag in BG */
>> + ext4_grpblk_t bb_largest_free_order_idx; /* index of largest frag */
>> ext4_group_t bb_group; /* Group number */
>> struct list_head bb_prealloc_list;
>> #ifdef DOUBLE_CHECK
>> diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
>> index e6d6c2da3c6e..dc82124f0905 100644
>> --- a/fs/ext4/mballoc.c
>> +++ b/fs/ext4/mballoc.c
>> @@ -1152,33 +1152,29 @@ static void
>> mb_set_largest_free_order(struct super_block *sb, struct ext4_group_info *grp)
>> {
>> struct ext4_sb_info *sbi = EXT4_SB(sb);
>> - int i;
>> + int new, old = grp->bb_largest_free_order_idx;
>>
>> - for (i = MB_NUM_ORDERS(sb) - 1; i >= 0; i--)
>> - if (grp->bb_counters[i] > 0)
>> + for (new = MB_NUM_ORDERS(sb) - 1; new >= 0; new--)
>> + if (grp->bb_counters[new] > 0)
>> break;
>> +
>> + grp->bb_largest_free_order = new;
>> /* No need to move between order lists? */
>> - if (!test_opt2(sb, MB_OPTIMIZE_SCAN) ||
>> - i == grp->bb_largest_free_order) {
>> - grp->bb_largest_free_order = i;
>> + if (!test_opt2(sb, MB_OPTIMIZE_SCAN) || new == old)
>> return;
>> - }
>>
>> - if (grp->bb_largest_free_order >= 0) {
>> - write_lock(&sbi->s_mb_largest_free_orders_locks[
>> - grp->bb_largest_free_order]);
>> + if (old >= 0) {
>> + write_lock(&sbi->s_mb_largest_free_orders_locks[old]);
>> list_del_init(&grp->bb_largest_free_order_node);
>> - write_unlock(&sbi->s_mb_largest_free_orders_locks[
>> - grp->bb_largest_free_order]);
>> + write_unlock(&sbi->s_mb_largest_free_orders_locks[old]);
>> }
>> - grp->bb_largest_free_order = i;
>> - if (grp->bb_largest_free_order >= 0 && grp->bb_free) {
>> - write_lock(&sbi->s_mb_largest_free_orders_locks[
>> - grp->bb_largest_free_order]);
>> +
>> + grp->bb_largest_free_order_idx = new;
>> + if (new >= 0 && grp->bb_free) {
>> + write_lock(&sbi->s_mb_largest_free_orders_locks[new]);
>> list_add_tail(&grp->bb_largest_free_order_node,
>> - &sbi->s_mb_largest_free_orders[grp->bb_largest_free_order]);
>> - write_unlock(&sbi->s_mb_largest_free_orders_locks[
>> - grp->bb_largest_free_order]);
>> + &sbi->s_mb_largest_free_orders[new]);
>> + write_unlock(&sbi->s_mb_largest_free_orders_locks[new]);
>> }
>> }
>>
>> @@ -3391,6 +3387,7 @@ int ext4_mb_add_groupinfo(struct super_block *sb, ext4_group_t group,
>> INIT_LIST_HEAD(&meta_group_info[i]->bb_avg_fragment_size_node);
>> meta_group_info[i]->bb_largest_free_order = -1; /* uninit */
>> meta_group_info[i]->bb_avg_fragment_size_order = -1; /* uninit */
>> + meta_group_info[i]->bb_largest_free_order_idx = -1; /* uninit */
>> meta_group_info[i]->bb_group = group;
>>
>> mb_group_bb_bitmap_alloc(sb, meta_group_info[i], group);
>> --
>> 2.46.1
>>
next prev parent reply other threads:[~2025-06-30 7:34 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-06-23 7:32 [PATCH v2 00/16] ext4: better scalability for ext4 block allocation Baokun Li
2025-06-23 7:32 ` [PATCH v2 01/16] ext4: add ext4_try_lock_group() to skip busy groups Baokun Li
2025-06-27 18:06 ` Jan Kara
2025-07-14 6:53 ` Ojaswin Mujoo
2025-06-23 7:32 ` [PATCH v2 02/16] ext4: remove unnecessary s_mb_last_start Baokun Li
2025-06-27 18:15 ` Jan Kara
2025-06-30 3:32 ` Baokun Li
2025-06-30 7:31 ` Jan Kara
2025-06-30 7:52 ` Baokun Li
2025-07-14 7:00 ` Ojaswin Mujoo
2025-06-23 7:32 ` [PATCH v2 03/16] ext4: remove unnecessary s_md_lock on update s_mb_last_group Baokun Li
2025-06-27 18:19 ` Jan Kara
2025-06-30 3:48 ` Baokun Li
2025-06-30 7:47 ` Jan Kara
2025-06-30 9:21 ` Baokun Li
2025-06-30 16:32 ` Jan Kara
2025-07-01 2:39 ` Baokun Li
2025-07-01 12:21 ` Jan Kara
2025-07-01 13:17 ` Baokun Li
2025-07-08 13:08 ` Baokun Li
2025-07-10 14:38 ` Jan Kara
2025-07-14 3:01 ` Theodore Ts'o
2025-07-14 7:00 ` Baokun Li
2025-07-01 2:57 ` kernel test robot
2025-06-23 7:32 ` [PATCH v2 04/16] ext4: utilize multiple global goals to reduce contention Baokun Li
2025-06-27 18:31 ` Jan Kara
2025-06-30 6:50 ` Baokun Li
2025-06-30 8:38 ` Jan Kara
2025-06-30 10:02 ` Baokun Li
2025-06-30 17:41 ` Jan Kara
2025-07-01 3:32 ` Baokun Li
2025-07-01 11:53 ` Jan Kara
2025-07-01 12:12 ` Baokun Li
2025-06-23 7:32 ` [PATCH v2 05/16] ext4: get rid of some obsolete EXT4_MB_HINT flags Baokun Li
2025-06-23 7:32 ` [PATCH v2 06/16] ext4: fix typo in CR_GOAL_LEN_SLOW comment Baokun Li
2025-06-23 7:32 ` [PATCH v2 07/16] ext4: convert sbi->s_mb_free_pending to atomic_t Baokun Li
2025-06-27 18:33 ` Jan Kara
2025-06-23 7:32 ` [PATCH v2 08/16] ext4: merge freed extent with existing extents before insertion Baokun Li
2025-06-27 19:11 ` Jan Kara
2025-06-23 7:32 ` [PATCH v2 09/16] ext4: fix zombie groups in average fragment size lists Baokun Li
2025-06-27 19:14 ` Jan Kara
2025-06-30 6:53 ` Baokun Li
2025-06-23 7:32 ` [PATCH v2 10/16] ext4: fix largest free orders lists corruption on mb_optimize_scan switch Baokun Li
2025-06-27 19:34 ` Jan Kara
2025-06-30 7:34 ` Baokun Li [this message]
2025-06-23 7:32 ` [PATCH v2 11/16] ext4: factor out __ext4_mb_scan_group() Baokun Li
2025-06-23 7:33 ` [PATCH v2 12/16] ext4: factor out ext4_mb_might_prefetch() Baokun Li
2025-06-23 7:33 ` [PATCH v2 13/16] ext4: factor out ext4_mb_scan_group() Baokun Li
2025-06-23 7:33 ` [PATCH v2 14/16] ext4: convert free group lists to ordered xarrays Baokun Li
2025-06-23 7:33 ` [PATCH v2 15/16] ext4: refactor choose group to scan group Baokun Li
2025-06-23 7:33 ` [PATCH v2 16/16] ext4: ensure global ordered traversal across all free groups xarrays Baokun Li
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=5bf464c0-5cfe-4e29-8138-4fb85c83f5bb@huawei.com \
--to=libaokun1@huawei.com \
--cc=adilger.kernel@dilger.ca \
--cc=jack@suse.cz \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojaswin@linux.ibm.com \
--cc=stable@vger.kernel.org \
--cc=tytso@mit.edu \
--cc=yangerkun@huawei.com \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.