From: Ojaswin Mujoo <ojaswin@linux.ibm.com>
To: linux-ext4@vger.kernel.org, "Theodore Ts'o" <tytso@mit.edu>
Cc: Ritesh Harjani <ritesh.list@gmail.com>,
Zhang Yi <yi.zhang@huawei.com>, Jan Kara <jack@suse.cz>,
libaokun1@huawei.com, linux-kernel@vger.kernel.org
Subject: [PATCH 7/7] ext4: Allow zeroout when doing written to unwritten split
Date: Sun, 4 Jan 2026 17:49:20 +0530 [thread overview]
Message-ID: <bd83af6cd845ac1567900f84c754fc2c0ffd40b3.1767528171.git.ojaswin@linux.ibm.com> (raw)
In-Reply-To: <cover.1767528171.git.ojaswin@linux.ibm.com>
Currently, when we are doing an extent split and convert operation of
written to unwritten extent (example, as done by ZERO_RANGE), we don't
allow the zeroout fallback in case the extent tree manipulation fails.
This is mostly because zeroout might take unsually long and the fact that
this code path is more tolerant to failures than endio.
Since we have zeroout machinery in place, we might as well use it hence
lift this restriction. To mitigate zeroout taking too long respect the
max zeroout limit here so that the operation finishes relatively fast.
Also, add kunit tests for this case.
Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com>
---
fs/ext4/extents-test.c | 33 +++++++++++++++++++++++++++++++++
fs/ext4/extents.c | 23 +++++++++++++++--------
2 files changed, 48 insertions(+), 8 deletions(-)
diff --git a/fs/ext4/extents-test.c b/fs/ext4/extents-test.c
index 725d5e79be96..3b5274297fe9 100644
--- a/fs/ext4/extents-test.c
+++ b/fs/ext4/extents-test.c
@@ -685,6 +685,39 @@ static const struct kunit_ext_test_param test_split_convert_params[] = {
.is_zeroout_test = 1,
.nr_exp_data_segs = 1,
.exp_data_state = { { .exp_char = 0, .off_blk = 0, .len_blk = 3 } } },
+
+ /* writ to unwrit splits */
+ { .desc = "split writ extent to 2 extents and convert 1st half unwrit (zeroout)",
+ .is_unwrit_at_start = 0,
+ .split_flags = EXT4_GET_BLOCKS_CONVERT_UNWRITTEN,
+ .split_map = { .m_lblk = 10, .m_len = 1 },
+ .nr_exp_ext = 1,
+ .exp_ext_state = { { .ex_lblk = 10, .ex_len = 3, .is_unwrit = 0 } },
+ .is_zeroout_test = 1,
+ .nr_exp_data_segs = 2,
+ .exp_data_state = { { .exp_char = 0, .off_blk = 0, .len_blk = 1 },
+ { .exp_char = 'X', .off_blk = 1, .len_blk = 2 }}},
+ { .desc = "split writ extent to 2 extents and convert 2nd half unwrit (zeroout)",
+ .is_unwrit_at_start = 0,
+ .split_flags = EXT4_GET_BLOCKS_CONVERT_UNWRITTEN,
+ .split_map = { .m_lblk = 11, .m_len = 2 },
+ .nr_exp_ext = 1,
+ .exp_ext_state = { { .ex_lblk = 10, .ex_len = 3, .is_unwrit = 0 } },
+ .is_zeroout_test = 1,
+ .nr_exp_data_segs = 2,
+ .exp_data_state = { { .exp_char = 'X', .off_blk = 0, .len_blk = 1 },
+ { .exp_char = 0, .off_blk = 1, .len_blk = 2 } } },
+ { .desc = "split writ extent to 3 extents and convert 2nd half unwrit (zeroout)",
+ .is_unwrit_at_start = 0,
+ .split_flags = EXT4_GET_BLOCKS_CONVERT_UNWRITTEN,
+ .split_map = { .m_lblk = 11, .m_len = 1 },
+ .nr_exp_ext = 1,
+ .exp_ext_state = { { .ex_lblk = 10, .ex_len = 3, .is_unwrit = 0 } },
+ .is_zeroout_test = 1,
+ .nr_exp_data_segs = 3,
+ .exp_data_state = { { .exp_char = 'X', .off_blk = 0, .len_blk = 1 },
+ { .exp_char = 0, .off_blk = 1, .len_blk = 1 },
+ { .exp_char = 'X', .off_blk = 2, .len_blk = 1 }}},
};
static const struct kunit_ext_test_param
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index 9fb8a3220ae2..95dd88df8fe4 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -3485,7 +3485,19 @@ static struct ext4_ext_path *ext4_split_extent(handle_t *handle,
* to initialize as a last resort
*/
if (split_flag & EXT4_EXT_MAY_ZEROOUT) {
- path = ext4_find_extent(inode, map->m_lblk, NULL, flags);
+ int max_zeroout_blks =
+ EXT4_SB(inode->i_sb)->s_extent_max_zeroout_kb >>
+ (inode->i_sb->s_blocksize_bits - 10);
+ if (flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN &&
+ map->m_len > max_zeroout_blks)
+ /*
+ * Written to unwritten extent is not a critical path so
+ * lets respect the max zeroout
+ */
+ return ERR_PTR(orig_err);
+
+ path = ext4_find_extent(inode, map->m_lblk, NULL,
+ flags);
if (IS_ERR(path))
return path;
@@ -3863,15 +3875,10 @@ static struct ext4_ext_path *ext4_split_convert_extents(handle_t *handle,
goto convert;
/*
- * We don't use zeroout fallback for written to unwritten conversion as
- * it is not as critical as endio and it might take unusually long.
- * Also, it is only safe to convert extent to initialized via explicit
+ * It is only safe to convert extent to initialized via explicit
* zeroout only if extent is fully inside i_size or new_size.
*/
- if (!(flags & EXT4_GET_BLOCKS_CONVERT_UNWRITTEN))
- split_flag |= ee_block + ee_len <= eof_block ?
- EXT4_EXT_MAY_ZEROOUT :
- 0;
+ split_flag |= ee_block + ee_len <= eof_block ? EXT4_EXT_MAY_ZEROOUT : 0;
/*
* pass SPLIT_NOMERGE explicitly so we don't end up merging extents we
--
2.51.0
next prev parent reply other threads:[~2026-01-04 12:19 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-04 12:19 [PATCH 0/7] ext4 extent split/convert refactor and kunit tests Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 1/7] ext4: kunit tests for extent splitting and conversion Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 2/7] ext4: kunit tests for higher level extent manipulation functions Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 3/7] ext4: propagate flags to convert_initialized_extent() Ojaswin Mujoo
2026-01-06 14:33 ` Jan Kara
2026-01-07 7:19 ` Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 4/7] ext4: propagate flags to ext4_convert_unwritten_extents_endio() Ojaswin Mujoo
2026-01-06 14:34 ` Jan Kara
2026-01-07 6:33 ` Zhang Yi
2026-01-07 6:59 ` Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 5/7] ext4: Refactor zeroout path and handle all cases Ojaswin Mujoo
2026-01-06 15:31 ` Jan Kara
2026-01-07 7:15 ` Ojaswin Mujoo
2026-01-08 11:58 ` Zhang Yi
2026-01-08 12:42 ` Ojaswin Mujoo
2026-01-08 12:54 ` Zhang Yi
2026-01-08 14:08 ` Ojaswin Mujoo
2026-01-04 12:19 ` [PATCH 6/7] ext4: Refactor split and convert extents Ojaswin Mujoo
2026-01-06 15:55 ` Jan Kara
2026-01-08 12:34 ` Zhang Yi
2026-01-12 9:41 ` Ojaswin Mujoo
2026-01-04 12:19 ` Ojaswin Mujoo [this message]
2026-01-06 15:41 ` [PATCH 7/7] ext4: Allow zeroout when doing written to unwritten split Jan Kara
2026-01-05 6:34 ` [PATCH 0/7] ext4 extent split/convert refactor and kunit tests Ojaswin Mujoo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bd83af6cd845ac1567900f84c754fc2c0ffd40b3.1767528171.git.ojaswin@linux.ibm.com \
--to=ojaswin@linux.ibm.com \
--cc=jack@suse.cz \
--cc=libaokun1@huawei.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®