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 <joannelkoong@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Joanne Koong 2026-09-15 18:05:24 -07:00 committed by Miklos Szeredi
parent f7585e1ce3
commit ad866d756d

View File

@ -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;