Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ext4: fix calculation of credits for extent tree modification

Luis and David are reporting that after running generic/750 test for 90+
hours on 2k ext4 filesystem, they are able to trigger a warning in
jbd2_journal_dirty_metadata() complaining that there are not enough
credits in the running transaction started in ext4_do_writepages().

Indeed the code in ext4_do_writepages() is racy and the extent tree can
change between the time we compute credits necessary for extent tree
computation and the time we actually modify the extent tree. Thus it may
happen that the number of credits actually needed is higher. Modify
ext4_ext_index_trans_blocks() to count with the worst case of maximum
tree depth. This can reduce the possible number of writers that can
operate in the system in parallel (because the credit estimates now won't
fit in one transaction) but for reasonably sized journals this shouldn't
really be an issue. So just go with a safe and simple fix.

Link: https://lore.kernel.org/all/20250415013641.f2ppw6wov4kn4wq2@offworld
Reported-by: Davidlohr Bueso <dave@stgolabs.net>
Reported-by: Luis Chamberlain <mcgrof@kernel.org>
Tested-by: kdevops@lists.linux.dev
Signed-off-by: Jan Kara <jack@suse.cz>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20250429175535.23125-2-jack@suse.cz
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Cc: stable@kernel.org

authored by

Jan Kara and committed by
Theodore Ts'o
32a93f5b d612a079

+6 -5
+6 -5
fs/ext4/extents.c
··· 2399 2399 int ext4_ext_index_trans_blocks(struct inode *inode, int extents) 2400 2400 { 2401 2401 int index; 2402 - int depth; 2403 2402 2404 2403 /* If we are converting the inline data, only one is needed here. */ 2405 2404 if (ext4_has_inline_data(inode)) 2406 2405 return 1; 2407 2406 2408 - depth = ext_depth(inode); 2409 - 2407 + /* 2408 + * Extent tree can change between the time we estimate credits and 2409 + * the time we actually modify the tree. Assume the worst case. 2410 + */ 2410 2411 if (extents <= 1) 2411 - index = depth * 2; 2412 + index = EXT4_MAX_EXTENT_DEPTH * 2; 2412 2413 else 2413 - index = depth * 3; 2414 + index = EXT4_MAX_EXTENT_DEPTH * 3; 2414 2415 2415 2416 return index; 2416 2417 }