[PATCH -next v5 09/32] ext4: avoid unnecessary transaction in ext4_map_blocks() for unwritten extents
From: Zhang Yi
Date: Fri Aug 14 2026 - 05:43:47 EST
From: Zhang Yi <yi.zhang@xxxxxxxxxx>
When ext4_map_blocks() finds an unwritten extent in the extent cache and
the caller is willing to accept unwritten extents without conversion,
there is no need to start a journal transaction since no metadata update
is required. This avoids unnecessary transaction overhead in the
upcoming iomap writeback path when overwriting already-allocated
unwritten extents.
One thing to be careful about, as the comment in ext4_map_blocks()
states, if the flags contain EXT4_GET_BLOCKS_CREATE, the function will
mark @map as mapped.
Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx>
---
fs/ext4/inode.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index c9904c274347..5dcc3f7b2ffd 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -807,14 +807,23 @@ int ext4_map_blocks(handle_t *handle, struct inode *inode,
* Note that if blocks have been preallocated
* ext4_ext_map_blocks() returns with buffer head unmapped
*/
- if (retval > 0 && map->m_flags & EXT4_MAP_MAPPED)
+ if (retval > 0) {
/*
- * If we need to convert extent to unwritten
- * we continue and do the actual work in
- * ext4_ext_map_blocks()
+ * If we need to convert written extent to unwritten or
+ * convert unwritten extent to written, continue and do
+ * the actual work in ext4_ext_map_blocks().
*/
- if (!(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))
+ if (map->m_flags & EXT4_MAP_MAPPED &&
+ !(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))
goto out_handle;
+ if (map->m_flags & EXT4_MAP_UNWRITTEN &&
+ (flags & EXT4_GET_BLOCKS_UNWRIT_EXT) &&
+ !(flags & EXT4_GET_BLOCKS_CONVERT)) {
+ /* Contains EXT4_GET_BLOCKS_CREATE - mark mapped. */
+ map->m_flags |= EXT4_MAP_MAPPED;
+ goto out_handle;
+ }
+ }
if (!handle) {
handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
--
2.52.0