[PATCH v6 07/31] ext4: allow ext4_map_blocks() to start its own transaction handle
From: Zhang Yi
Date: Thu Sep 03 2026 - 09:07:18 EST
From: Zhang Yi <yi.zhang@xxxxxxxxxx>
Make ext4_map_blocks() start its own transaction handle when the caller
does not provide one. The handle is started after the lookup path
confirms that allocation is actually needed, and is stopped at the
unified out_handle exit path. This avoids unnecessarily starting a
handle for pure mapping queries. This prepares for the buffered iomap
writeback conversion, which improves performance for fragile overwrite
cases.
Suggested-by: Jan Kara <jack@xxxxxxx>
Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx>
---
fs/ext4/inode.c | 36 +++++++++++++++++++++++++++---------
1 file changed, 27 insertions(+), 9 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 73af6d386985..c9dea4ca5caf 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -703,6 +703,7 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
struct extent_status es;
int retval;
int ret = 0;
+ bool internal_handle = false;
unsigned int orig_mlen;
#ifdef ES_AGGRESSIVE_TEST
struct ext4_map_blocks orig_map;
@@ -787,13 +788,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
retval = ext4_map_query_blocks(handle, inode, map, flags);
up_read((&EXT4_I(inode)->i_data_sem));
if (retval < 0)
- return retval;
+ goto out_handle;
found:
if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED) {
ret = check_block_validity(inode, map);
- if (ret != 0)
- return ret;
+ if (ret != 0) {
+ retval = ret;
+ goto out_handle;
+ }
}
/* If it is only a block(s) look up */
@@ -813,8 +816,15 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
* ext4_ext_map_blocks()
*/
if (!(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))
- return retval;
+ goto out_handle;
+ if (!handle) {
+ handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
+ ext4_chunk_trans_blocks(inode, orig_mlen));
+ if (IS_ERR(handle))
+ return PTR_ERR(handle);
+ internal_handle = true;
+ }
ext4_fc_track_inode(handle, inode);
/*
@@ -843,12 +853,14 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
if (retval < 0)
ext_debug(inode, "failed with err %d\n", retval);
if (retval <= 0)
- return retval;
+ goto out_handle;
if (map->m_flags & EXT4_MAP_MAPPED) {
ret = check_block_validity(inode, map);
- if (ret != 0)
- return ret;
+ if (ret != 0) {
+ retval = ret;
+ goto out_handle;
+ }
/*
* Inodes with freshly allocated blocks where contents will be
@@ -869,12 +881,18 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
else
ret = ext4_jbd2_inode_add_write(handle, inode,
start_byte, length);
- if (ret)
- return ret;
+ if (ret) {
+ retval = ret;
+ goto out_handle;
+ }
}
}
ext4_fc_track_range(handle, inode, map->m_lblk, map->m_lblk +
map->m_len - 1);
+
+out_handle:
+ if (internal_handle)
+ ext4_journal_stop(handle);
return retval;
}
--
2.52.0