When ext4_mb_generate_buddy() detects block group descriptor corruption (free block count mismatch between descriptor and bitmap), it corrects the in-memory group descriptor (grp->bb_free) but does not synchronize the percpu free clusters counter. This causes delayed allocation to read stale counter values when checking for available space. The allocator believes space is available based on the stale counter, makes reservation promises, but later fails during writeback when trying to allocate actual blocks from the bitmap. This results in "Delayed block allocation failed" errors and potential system crashes. Fix by updating the percpu counter with the correction delta when corruption is detected: s64 correction = (s64)free - (s64)grp->bb_free; grp->bb_free = free; percpu_counter_add(&sbi->s_freeclusters_counter, correction); This ensures the global counter stays synchronized with the corrected group descriptor, preventing false promises and crashes. Reported-by: syzbot+f3185be57d7e8dda32b8@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=f3185be57d7e8dda32b8 Tested-by: syzbot+f3185be57d7e8dda32b8@syzkaller.appspotmail.com Co-developed-by: Ahmet Eray Karadag Signed-off-by: Ahmet Eray Karadag Signed-off-by: Albin Babu Varghese --- Changes in v2: - v1 added bounds checking in ext4_write_inline_data_end() to reject writes beyond inline capacity - v2 fixes the root cause by synchronizing the percpu free clusters counter when corruption is detected in ext4_mb_generate_buddy() - Addresses review feedback from Ted Ts'o and Darrick Wong Link to v1: https://lore.kernel.org/all/20251007234221.28643-2-eraykrdg1@gmail.com/T/ --- fs/ext4/mballoc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/fs/ext4/mballoc.c b/fs/ext4/mballoc.c index 9087183602e4..956e5fa307ca 100644 --- a/fs/ext4/mballoc.c +++ b/fs/ext4/mballoc.c @@ -1290,8 +1290,11 @@ void ext4_mb_generate_buddy(struct super_block *sb, /* * If we intend to continue, we consider group descriptor * corrupt and update bb_free using bitmap value + * Also update the global free clusters counter to stay in sync. */ + s64 correction = (s64)free - (s64)grp->bb_free; grp->bb_free = free; + percpu_counter_add(&sbi->s_freeclusters_counter, correction); ext4_mark_group_bitmap_corrupted(sb, group, EXT4_GROUP_INFO_BBITMAP_CORRUPT); } -- 2.51.0