Commit 7a4f5418 authored by Joanne Koong's avatar Joanne Koong Committed by Miklos Szeredi
Browse files

fuse: fix direct io folio offset and length calculation



For the direct io case, the pages from userspace may be part of a huge
folio, even if all folios in the page cache for fuse are small.

Fix the logic for calculating the offset and length of the folio for
the direct io case, which currently incorrectly assumes that all folios
encountered are one page size.

Fixes: 3b97c365 ("fuse: convert direct io to use folios")
Signed-off-by: default avatarJoanne Koong <joannelkoong@gmail.com>
Reviewed-by: default avatarJingbo Xu <jefflexu@linux.alibaba.com>
Reviewed-by: default avatarBernd Schubert <bschubert@ddn.com>
Signed-off-by: default avatarMiklos Szeredi <mszeredi@redhat.com>
parent 40384c84
Loading
Loading
Loading
Loading
+16 −12
Original line number Diff line number Diff line
@@ -1557,18 +1557,22 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,

		nbytes += ret;

		ret += start;
		/* Currently, all folios in FUSE are one page */
		nfolios = DIV_ROUND_UP(ret, PAGE_SIZE);
		nfolios = DIV_ROUND_UP(ret + start, PAGE_SIZE);

		for (i = 0; i < nfolios; i++) {
			struct folio *folio = page_folio(pages[i]);
			unsigned int offset = start +
				(folio_page_idx(folio, pages[i]) << PAGE_SHIFT);
			unsigned int len = min_t(unsigned int, ret, PAGE_SIZE - start);

		ap->descs[ap->num_folios].offset = start;
		fuse_folio_descs_length_init(ap->descs, ap->num_folios, nfolios);
		for (i = 0; i < nfolios; i++)
			ap->folios[i + ap->num_folios] = page_folio(pages[i]);
			ap->descs[ap->num_folios].offset = offset;
			ap->descs[ap->num_folios].length = len;
			ap->folios[ap->num_folios] = folio;
			start = 0;
			ret -= len;
			ap->num_folios++;
		}

		ap->num_folios += nfolios;
		ap->descs[ap->num_folios - 1].length -=
			(PAGE_SIZE - ret) & (PAGE_SIZE - 1);
		nr_pages += nfolios;
	}
	kfree(pages);