Re: [PATCH v2 4/6] ext4: zero out whole block for clean edges in WRITE_ZEROES

From: Jan Kara

Date: Wed Jul 08 2026 - 11:37:18 EST


On Tue 07-07-26 10:13:36, Zhang Yi wrote:
> 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 already allocated, ext4_zero_partial_blocks() zeros them directly.
> However, for unaligned edges whose underlying extent is a clean
> unwritten extent or a hole, the extent type remains unwritten after
> partial zeroing, which does not align with the semantics of
> WRITE_ZEROES.
>
> Therefore, when ext4_zero_partial_blocks() skips partial zeroing, it
> indicates that the corresponding edges are clean unwritten extents or
> holes. In this case, we need to expand the aligned allocation range
> outward to cover such edges, so that ext4_alloc_file_blocks() can
> correctly allocate blocks for the unaligned range. Edges that were
> partial-zeroed (i.e., written or dirty) are left untouched.
>
> Fixes: f4265b8d32c4 ("ext4: add FALLOC_FL_WRITE_ZEROES support")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Zhang Yi <yi.zhang@xxxxxxxxxx>

Looks good. Feel free to add:

Reviewed-by: Jan Kara <jack@xxxxxxx>

Honza

> ---
> fs/ext4/extents.c | 15 +++++++++++++++
> 1 file changed, 15 insertions(+)
>
> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
> index 7a8f9f188a29..c34505765521 100644
> --- a/fs/ext4/extents.c
> +++ b/fs/ext4/extents.c
> @@ -4760,6 +4760,21 @@ static long ext4_zero_range(struct file *file, loff_t offset,
> /* Zero range excluding the unaligned edges */
> align_start = round_up(offset, blocksize);
> align_end = round_down(end, blocksize);
> +
> + /*
> + * In WRITE_ZEROES mode, edges that were not partial-zeroed (clean
> + * unwritten or hole) must be allocated and zeroed as whole blocks.
> + * Expand the aligned range outward to cover them.
> + */
> + if (mode & FALLOC_FL_WRITE_ZEROES) {
> + if (!IS_ALIGNED(offset, blocksize) &&
> + !(partial_zeroed & EXT4_PARTIAL_ZERO_START))
> + align_start = round_down(offset, blocksize);
> + if (!IS_ALIGNED(end, blocksize) &&
> + !(partial_zeroed & EXT4_PARTIAL_ZERO_END))
> + align_end = round_up(end, blocksize);
> + }
> +
> if (align_end > align_start) {
> if (mode & FALLOC_FL_WRITE_ZEROES)
> flags = EXT4_GET_BLOCKS_CREATE_ZERO | EXT4_EX_NOCACHE;
> --
> 2.52.0
>
--
Jan Kara <jack@xxxxxxxx>
SUSE Labs, CR