summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBaokun Li <libaokun1@huawei.com>2024-01-04 22:20:35 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2024-03-01 13:22:00 +0100
commitc1317822e2de80e78f137d3a2d99febab1b80326 (patch)
treea465198a22df6ddd2aff42127af799a40275db4a
parentd82ec7529c5f9641bf4d97dfeec43faf07ec1b8e (diff)
ext4: regenerate buddy after block freeing failed if under fc replay
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 <jack@suse.cz> Fixes: 6bd97bf273bd ("ext4: remove redundant mb_regenerate_buddy()") Signed-off-by: Baokun Li <libaokun1@huawei.com> Reviewed-by: Jan Kara <jack@suse.cz> Link: https://lore.kernel.org/r/20240104142040.2835097-4-libaokun1@huawei.com Signed-off-by: Theodore Ts'o <tytso@mit.edu> Signed-off-by: Baokun Li <libaokun1@huawei.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/ext4/mballoc.c20
1 files changed, 20 insertions, 0 deletions
diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c
index 622f60d9e1c6..6bf98e61ed46 100644
--- a/fs/ext4/mballoc.c
+++ b/fs/ext4/mballoc.c
@@ -1168,6 +1168,24 @@ void ext4_mb_generate_buddy(struct super_block *sb,
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 *inode, struct ext4_buddy *e4b,
ext4_mark_group_bitmap_corrupted(
sb, e4b->bd_group,
EXT4_GROUP_INFO_BBITMAP_CORRUPT);
+ } else {
+ mb_regenerate_buddy(e4b);
}
goto done;
}