From: Greg Kroah-Hartman Date: Tue, 27 Feb 2024 13:07:28 +0000 (+0100) Subject: 5.15-stable patches X-Git-Tag: v4.19.308~6 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=6206b7b9112baccae6f4f9a7866cdcd180bdc261;p=thirdparty%2Fkernel%2Fstable-queue.git 5.15-stable patches added patches: ext4-avoid-bb_free-and-bb_fragments-inconsistency-in-mb_free_blocks.patch ext4-regenerate-buddy-after-block-freeing-failed-if-under-fc-replay.patch --- diff --git a/queue-5.15/ext4-avoid-bb_free-and-bb_fragments-inconsistency-in-mb_free_blocks.patch b/queue-5.15/ext4-avoid-bb_free-and-bb_fragments-inconsistency-in-mb_free_blocks.patch new file mode 100644 index 00000000000..2f8725b431d --- /dev/null +++ b/queue-5.15/ext4-avoid-bb_free-and-bb_fragments-inconsistency-in-mb_free_blocks.patch @@ -0,0 +1,102 @@ +From 2331fd4a49864e1571b4f50aa3aa1536ed6220d0 Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 4 Jan 2024 22:20:36 +0800 +Subject: ext4: avoid bb_free and bb_fragments inconsistency in mb_free_blocks() + +From: Baokun Li + +commit 2331fd4a49864e1571b4f50aa3aa1536ed6220d0 upstream. + +After updating bb_free in mb_free_blocks, it is possible to return without +updating bb_fragments because the block being freed is found to have +already been freed, which leads to inconsistency between bb_free and +bb_fragments. + +Since the group may be unlocked in ext4_grp_locked_error(), this can lead +to problems such as dividing by zero when calculating the average fragment +length. Hence move the update of bb_free to after the block double-free +check guarantees that the corresponding statistics are updated only after +the core block bitmap is modified. + +Fixes: eabe0444df90 ("ext4: speed-up releasing blocks on commit") +CC: # 3.10 +Suggested-by: Jan Kara +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20240104142040.2835097-5-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 39 +++++++++++++++++++++------------------ + 1 file changed, 21 insertions(+), 18 deletions(-) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1835,11 +1835,6 @@ static void mb_free_blocks(struct inode + mb_check_buddy(e4b); + mb_free_blocks_double(inode, e4b, first, count); + +- this_cpu_inc(discard_pa_seq); +- e4b->bd_info->bb_free += count; +- if (first < e4b->bd_info->bb_first_free) +- e4b->bd_info->bb_first_free = first; +- + /* access memory sequentially: check left neighbour, + * clear range and then check right neighbour + */ +@@ -1853,23 +1848,31 @@ static void mb_free_blocks(struct inode + struct ext4_sb_info *sbi = EXT4_SB(sb); + ext4_fsblk_t blocknr; + ++ /* ++ * Fastcommit replay can free already freed blocks which ++ * corrupts allocation info. Regenerate it. ++ */ ++ if (sbi->s_mount_state & EXT4_FC_REPLAY) { ++ mb_regenerate_buddy(e4b); ++ goto check; ++ } ++ + blocknr = ext4_group_first_block_no(sb, e4b->bd_group); + blocknr += EXT4_C2B(sbi, block); +- if (!(sbi->s_mount_state & EXT4_FC_REPLAY)) { +- ext4_grp_locked_error(sb, e4b->bd_group, +- inode ? inode->i_ino : 0, +- blocknr, +- "freeing already freed block (bit %u); block bitmap corrupt.", +- block); +- ext4_mark_group_bitmap_corrupted( +- sb, e4b->bd_group, ++ ext4_grp_locked_error(sb, e4b->bd_group, ++ inode ? inode->i_ino : 0, blocknr, ++ "freeing already freed block (bit %u); block bitmap corrupt.", ++ block); ++ ext4_mark_group_bitmap_corrupted(sb, e4b->bd_group, + EXT4_GROUP_INFO_BBITMAP_CORRUPT); +- } else { +- mb_regenerate_buddy(e4b); +- } +- goto done; ++ return; + } + ++ this_cpu_inc(discard_pa_seq); ++ e4b->bd_info->bb_free += count; ++ if (first < e4b->bd_info->bb_first_free) ++ e4b->bd_info->bb_first_free = first; ++ + /* let's maintain fragments counter */ + if (left_is_free && right_is_free) + e4b->bd_info->bb_fragments--; +@@ -1894,9 +1897,9 @@ static void mb_free_blocks(struct inode + if (first <= last) + mb_buddy_mark_free(e4b, first >> 1, last >> 1); + +-done: + mb_set_largest_free_order(sb, e4b->bd_info); + mb_update_avg_fragment_size(sb, e4b->bd_info); ++check: + mb_check_buddy(e4b); + } + diff --git a/queue-5.15/ext4-regenerate-buddy-after-block-freeing-failed-if-under-fc-replay.patch b/queue-5.15/ext4-regenerate-buddy-after-block-freeing-failed-if-under-fc-replay.patch new file mode 100644 index 00000000000..4436950a3dc --- /dev/null +++ b/queue-5.15/ext4-regenerate-buddy-after-block-freeing-failed-if-under-fc-replay.patch @@ -0,0 +1,63 @@ +From c9b528c35795b711331ed36dc3dbee90d5812d4e Mon Sep 17 00:00:00 2001 +From: Baokun Li +Date: Thu, 4 Jan 2024 22:20:35 +0800 +Subject: ext4: regenerate buddy after block freeing failed if under fc replay + +From: Baokun Li + +commit c9b528c35795b711331ed36dc3dbee90d5812d4e upstream. + +This mostly reverts commit 6bd97bf273bd ("ext4: remove redundant +mb_regenerate_buddy()") and reintroduces mb_regenerate_buddy(). Based on +code in mb_free_blocks(), fast commit replay can end up marking as free +blocks that are already marked as such. This causes corruption of the +buddy bitmap so we need to regenerate it in that case. + +Reported-by: Jan Kara +Fixes: 6bd97bf273bd ("ext4: remove redundant mb_regenerate_buddy()") +Signed-off-by: Baokun Li +Reviewed-by: Jan Kara +Link: https://lore.kernel.org/r/20240104142040.2835097-4-libaokun1@huawei.com +Signed-off-by: Theodore Ts'o +Signed-off-by: Baokun Li +Signed-off-by: Greg Kroah-Hartman +--- + fs/ext4/mballoc.c | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + +--- a/fs/ext4/mballoc.c ++++ b/fs/ext4/mballoc.c +@@ -1168,6 +1168,24 @@ void ext4_mb_generate_buddy(struct super + mb_update_avg_fragment_size(sb, grp); + } + ++static void mb_regenerate_buddy(struct ext4_buddy *e4b) ++{ ++ int count; ++ int order = 1; ++ void *buddy; ++ ++ while ((buddy = mb_find_buddy(e4b, order++, &count))) ++ ext4_set_bits(buddy, 0, count); ++ ++ e4b->bd_info->bb_fragments = 0; ++ memset(e4b->bd_info->bb_counters, 0, ++ sizeof(*e4b->bd_info->bb_counters) * ++ (e4b->bd_sb->s_blocksize_bits + 2)); ++ ++ ext4_mb_generate_buddy(e4b->bd_sb, e4b->bd_buddy, ++ e4b->bd_bitmap, e4b->bd_group, e4b->bd_info); ++} ++ + /* The buddy information is attached the buddy cache inode + * for convenience. The information regarding each group + * is loaded via ext4_mb_load_buddy. The information involve +@@ -1846,6 +1864,8 @@ static void mb_free_blocks(struct inode + ext4_mark_group_bitmap_corrupted( + sb, e4b->bd_group, + EXT4_GROUP_INFO_BBITMAP_CORRUPT); ++ } else { ++ mb_regenerate_buddy(e4b); + } + goto done; + } diff --git a/queue-5.15/series b/queue-5.15/series index 0c64a03bcb8..67384c35493 100644 --- a/queue-5.15/series +++ b/queue-5.15/series @@ -240,3 +240,5 @@ cifs-fix-mid-leak-during-reconnection-after-timeout-threshold.patch fs-aio-restrict-kiocb_set_cancel_fn-to-i-o-submitted-via-libaio.patch arp-prevent-overflow-in-arp_req_get.patch netfilter-nf_tables-fix-scheduling-while-atomic-splat.patch +ext4-regenerate-buddy-after-block-freeing-failed-if-under-fc-replay.patch +ext4-avoid-bb_free-and-bb_fragments-inconsistency-in-mb_free_blocks.patch