ext4: teach ext4_meta_trans_blocks() about number of allocated extents

So far ext4_meta_trans_blocks() expects that each extent counted in
@pextents will be allocated in the transaction we estimate credits for.
This is correct for the use in ext4_chunk_trans_blocks() and
ext4_chunk_trans_extent() however the use in atomic write path
(ext4_convert_unwritten_extents_atomic() and ext4_iomap_alloc() for
IOMAP_ATOMIC) unnecessarily overestimates the number of necessary
credits as neither of them allocates any data. Add argument to
ext4_meta_trans_blocks() for number of extents that are going to be
allocated in the transaction.

Signed-off-by: Jan Kara <jack@suse.cz>
Link: https://patch.msgid.link/20260805153605.166545-4-jack@suse.cz
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
This commit is contained in:
Jan Kara 2026-08-05 17:35:47 +02:00 committed by Theodore Ts'o
parent 8f3901fbb4
commit 25b2a7e8d4
3 changed files with 17 additions and 17 deletions

View File

@ -3196,7 +3196,7 @@ extern int ext4_normal_submit_inode_data_buffers(struct jbd2_inode *jinode);
extern int ext4_chunk_trans_blocks(struct inode *, int nrblocks);
extern int ext4_chunk_trans_extent(struct inode *inode, int nrblocks);
extern int ext4_meta_trans_blocks(struct inode *inode, int lblocks,
int pextents);
int pextents, int alloc_extents);
extern int ext4_block_zero_eof(struct inode *inode, loff_t from, loff_t end);
#define EXT4_PARTIAL_ZERO_START 0x1

View File

@ -5063,7 +5063,7 @@ int ext4_convert_unwritten_extents_atomic(handle_t *handle, struct inode *inode,
* it can tell if the extent in the cache is a split extent.
* But for now let's assume pextents as 2 always.
*/
credits = ext4_meta_trans_blocks(inode, max_blocks, 2);
credits = ext4_meta_trans_blocks(inode, max_blocks, 2, 0);
}
if (credits) {

View File

@ -3709,8 +3709,8 @@ static int ext4_iomap_alloc(struct inode *inode, struct ext4_map_blocks *map,
return ret;
if (map->m_len < orig_mlen) {
map->m_len = orig_mlen;
dio_credits = ext4_meta_trans_blocks(inode, orig_mlen,
map->m_len);
dio_credits = ext4_meta_trans_blocks(inode, map->m_len,
map->m_len, 0);
} else {
dio_credits = ext4_chunk_trans_blocks(inode,
map->m_len);
@ -6394,17 +6394,17 @@ static int ext4_index_trans_blocks(struct inode *inode, int lblocks,
}
/*
* Account for index blocks, block groups bitmaps and block group
* descriptor blocks if modify datablocks and index blocks
* worse case, the indexs blocks spread over different block groups
*
* If datablocks are discontiguous, they are possible to spread over
* different block groups too. If they are contiguous, with flexbg,
* they could still across block group boundary.
*
* Also account for superblock, inode, quota and xattr blocks
* Calculate number of credits needed in a transaction to:
* * Allocate data blocks from @alloc_extents different groups - note that
* with flexbg a single physical extent can span multiple groups but
* single mballoc request only returns extent within one group.
* * Allocate metatadata (extent tree blocks, indirect blocks) to store
* pointers to @pextents data extents having @lblocks in total.
* * Modify extent tree / indirect block tree, inode, superblock, quota
* tracking, xattr blocks
*/
int ext4_meta_trans_blocks(struct inode *inode, int lblocks, int pextents)
int ext4_meta_trans_blocks(struct inode *inode, int lblocks, int pextents,
int alloc_extents)
{
ext4_group_t groups, ngroups = ext4_get_groups_count(inode->i_sb);
int gdpblocks;
@ -6421,7 +6421,7 @@ int ext4_meta_trans_blocks(struct inode *inode, int lblocks, int pextents)
* Now let's see how many group bitmaps and group descriptors need
* to account
*/
groups = idxblocks + pextents;
groups = idxblocks + alloc_extents;
gdpblocks = groups;
if (groups > ngroups)
groups = ngroups;
@ -6447,7 +6447,7 @@ int ext4_chunk_trans_extent(struct inode *inode, int nrblocks)
{
int ret;
ret = ext4_meta_trans_blocks(inode, nrblocks, 1);
ret = ext4_meta_trans_blocks(inode, nrblocks, 1, 1);
/* Account for data blocks for journalled mode */
if (ext4_should_journal_data(inode))
ret += nrblocks;
@ -6465,7 +6465,7 @@ int ext4_chunk_trans_extent(struct inode *inode, int nrblocks)
*/
int ext4_chunk_trans_blocks(struct inode *inode, int nrblocks)
{
return ext4_meta_trans_blocks(inode, nrblocks, 1);
return ext4_meta_trans_blocks(inode, nrblocks, 1, 1);
}
/*