From: Zhang Yi 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 Reviewed-by: Ojaswin Mujoo --- fs/ext4/inode.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index 553b767148c7b..6b0489cbb1319 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -812,14 +812,25 @@ 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; + 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. */ + ret = check_block_validity(inode, map); + if (!ret) + map->m_flags |= EXT4_MAP_MAPPED; + goto out; + } + } if (!handle) { handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS, -- 2.52.0