[PATCH 0/6] ext4: fix unaligned edge handling in FALLOC_FL_WRITE_ZEROES
From: yizhang089
Date: Wed Jul 01 2026 - 10:29:06 EST
From: Zhang Yi <yi.zhang@xxxxxxxxxx>
Hi,
The current FALLOC_FL_WRITE_ZEROES implementation in ext4 does not
correctly handle unaligned edge blocks. FALLOC_FL_WRITE_ZEROES is
needed to convert the requested range to written extents with zeroed
content, but the existing code only partially zero the edges and never
guarantees that:
1) edges that are clean unwritten extents or holes get promoted to
written extents, and
2) edges that are dirty unwritten or delalloc get their underlying
extents converted to written before the syscall returns.
Both cases leave the on-disk extent type unwritten, violating the
WRITE_ZEROES contract, and in these cases a subsequent sync buffered
overwrite would still observe pending metadata changes from the
conversion work that should have been completed by WRITE_ZEROES itself.
This series fixes the unaligned edge handling and cleans up a related
redundant i_disksize update. The first three patches are preparatory:
moving ext4_zero_partial_blocks() earlier in ext4_zero_range(),
documenting the return semantics of ext4_load_tail_bh(), and
replacing the single bool output of ext4_zero_partial_blocks() with a
per-edge bitmask (EXT4_PARTIAL_ZERO_START/END). The next two patches
fix the two scenarios above by expanding the aligned allocation range
outward for skipped (clean unwritten or hole) edges, and by writing
back partial-zeroed edges so the underlying extents are converted to
written. The final patch drops the now-redundant
ext4_update_disksize_before_punch() call on the WRITE_ZEROES path,
since WRITE_ZEROES is mutually exclusive with KEEP_SIZE and the
i_disksize update is already handled by ext4_alloc_file_blocks().
Thanks,
Yi.
Discussion Link:
https://lore.kernel.org/linux-xfs/0b7f1a4f-da1c-4297-8099-98d738070ab7@xxxxxxxxxxxxxxx/
Zhang Yi (6):
ext4: move partial block zeroing earlier in ext4_zero_range()
ext4: clarify return semantics of ext4_load_tail_bh()
ext4: track partial-zero outcome per edge in
ext4_zero_partial_blocks()
ext4: zero out whole block for clean edges in WRITE_ZEROES
ext4: write back partial-zeroed edges in WRITE_ZEROES
ext4: skip ext4_update_disksize_before_punch() in WRITE_ZEROES
fs/ext4/ext4.h | 5 ++++-
fs/ext4/extents.c | 47 +++++++++++++++++++++++++++++++++++++----------
fs/ext4/inode.c | 42 +++++++++++++++++++++++++++++++++++-------
3 files changed, 76 insertions(+), 18 deletions(-)
--
2.53.0