[PATCH v2 5/6] ext4: write back partial-zeroed edges in WRITE_ZEROES
From: Zhang Yi
Date: Mon Jul 06 2026 - 22:22:07 EST
FALLOC_FL_WRITE_ZEROES requires that all blocks in the requested range
end up as written extents with zeroed content. For unaligned edges that
were partial-zeroed in dirty unwritten or delalloc state, the buffer
is left dirty while the underlying extent may not yet be converted to
written. As a result, a subsequent SYNC write to this range would still
trigger metadata changes, which violates the semantics of WRITE_ZEROES.
Fix this by calling filemap_write_and_wait_range() for partial-zeroed
edges to flush out the zeroed data and ensure the extent conversion
is complete.
Fixes: f4265b8d32c4 ("ext4: add FALLOC_FL_WRITE_ZEROES support")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx>
Reviewed-by: Jan Kara <jack@xxxxxxx>
---
fs/ext4/extents.c | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
index c34505765521..c083703bf704 100644
--- a/fs/ext4/extents.c
+++ b/fs/ext4/extents.c
@@ -4791,7 +4791,15 @@ static long ext4_zero_range(struct file *file, loff_t offset,
if (IS_ALIGNED(offset | end, blocksize))
return ret;
- if (((file->f_flags & O_SYNC) || IS_SYNC(inode)) && partial_zeroed) {
+ /*
+ * In FALLOC_FL_WRITE_ZEROES mode, edges that have been partially
+ * zeroed must be written back to ensure the entire zeroed range
+ * is converted to the written state. In SYNC mode, writeback is
+ * also required to persist the zeroed data to disk.
+ */
+ if (partial_zeroed &&
+ ((mode & FALLOC_FL_WRITE_ZEROES) ||
+ (file->f_flags & O_SYNC) || IS_SYNC(inode))) {
ret = filemap_write_and_wait_range(inode->i_mapping, offset,
end - 1);
if (ret)
--
2.52.0