From ad866d756de0682419b04d66b466046880482f03 Mon Sep 17 00:00:00 2001 From: Joanne Koong Date: Tue, 15 Sep 2026 18:05:24 -0700 Subject: [PATCH] virtio_fs: zero the correct range on a short read reply virtio_fs_request_complete() zeroes the unfilled tail of a short reply at [len, thislen) within the folio. That is only correct when the read started at the beginning of the folio, which is what the WARN_ON(descs[i].offset) above it documents. The assumption holds on every configuration that exists today. A fuse read covers a sub-range of a folio only when iomap trims it to the blocks of a folio that are not uptodate, which requires the file system block size to be smaller than the folio. virtio-fs is not block backed, so its block size is PAGE_SIZE, an order-0 folio is a single block, and descs[i].offset is always 0. Large folios make i_blocks_per_folio() greater than one and the assumption false. iomap_adjust_read_range() skips the blocks that are already uptodate at the front of the range and hands the position of the first block that has to be read to ->read_folio_range(), both when __iomap_write_begin() fills the blocks around an unaligned write and when a folio that is only partially uptodate is read - in which case one folio can take several reads at different offsets. fuse turns that position into offset_in_folio(folio, iter->pos) and stores it in the descriptor, so the tail that needs zeroing is [offset + len, offset + thislen). Zero that range and drop the WARN_ON(). This is a no-op today and a prerequisite for enabling large folios. Signed-off-by: Joanne Koong Signed-off-by: Miklos Szeredi --- fs/fuse/virtio_fs.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index f15e516ebcb5..61ab7cb302c1 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -798,9 +798,11 @@ static void virtio_fs_request_complete(struct fuse_req *req, for (i = 0; i < ap->num_folios; i++) { thislen = ap->descs[i].length; if (len < thislen) { - WARN_ON(ap->descs[i].offset); + unsigned int offset = ap->descs[i].offset; + folio = ap->folios[i]; - folio_zero_segment(folio, len, thislen); + folio_zero_segment(folio, offset + len, + offset + thislen); len = 0; } else { len -= thislen;