iomap: fix zero padding data issue in concurrent append writes changed ioend accounting so that io_size tracks only valid data within EOF. This trims io_size when a writeback range extends past end_pos: ioend->io_size += map_len; if (ioend->io_offset + ioend->io_size > end_pos) ioend->io_size = end_pos - ioend->io_offset; However, ioend can be created before a concurrent truncate shrinks the file. In that case, end_pos can move below ioend->io_offset before the trim happens. The subtraction then becomes negative, but the result is stored in size_t io_size, causing an unsigned wrap to a huge value. A wrapped io_size can mislead append detection and corrupt completion-time size handling, since filesystem end_io paths consume io_size for decisions such as on-disk EOF updates and unwritten/COW completion ranges. Fix this by clamping io_size to zero when EOF has moved to or before the ioend start offset. This preserves the original intent of trimming io_size to valid in-EOF data while avoiding the underflow. Fixes: 51d20d1dacbe ("iomap: fix zero padding data issue in concurrent append writes") Signed-off-by: Morduan Zang --- fs/iomap/ioend.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/fs/iomap/ioend.c b/fs/iomap/ioend.c index acf3cf98b23a..0c391a66db6f 100644 --- a/fs/iomap/ioend.c +++ b/fs/iomap/ioend.c @@ -297,8 +297,12 @@ ssize_t iomap_add_to_ioend(struct iomap_writepage_ctx *wpc, struct folio *folio, * appending writes. */ ioend->io_size += map_len; - if (ioend->io_offset + ioend->io_size > end_pos) - ioend->io_size = end_pos - ioend->io_offset; + if (ioend->io_offset + ioend->io_size > end_pos) { + if (end_pos > ioend->io_offset) + ioend->io_size = end_pos - ioend->io_offset; + else + ioend->io_size = 0; + } wbc_account_cgroup_owner(wpc->wbc, folio, map_len); return map_len; -- 2.50.1