@@ -1484,7 +1484,8 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
return -ENOMEM;
while (nbytes < *nbytesp && nr_pages < max_pages) {
- unsigned nfolios, i;
+ unsigned npages;
+ unsigned i = 0;
size_t start;
ret = iov_iter_extract_pages(ii, &pages,
@@ -1496,19 +1497,28 @@ 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);
+ npages = DIV_ROUND_UP(ret + start, PAGE_SIZE);
- 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]);
+ while (ret && i < npages) {
+ struct folio *folio;
+ unsigned int folio_offset;
+ unsigned int len;
- ap->num_folios += nfolios;
- ap->descs[ap->num_folios - 1].length -=
- (PAGE_SIZE - ret) & (PAGE_SIZE - 1);
- nr_pages += nfolios;
+ folio = page_folio(pages[i]);
+ folio_offset = ((size_t)folio_page_idx(folio, pages[i]) <<
+ PAGE_SHIFT) + start;
+ len = min_t(ssize_t, ret, folio_size(folio) - folio_offset);
+
+ ap->folios[ap->num_folios] = folio;
+ ap->descs[ap->num_folios].offset = folio_offset;
+ ap->descs[ap->num_folios].length = len;
+ ap->num_folios++;
+
+ ret -= len;
+ i += DIV_ROUND_UP(start + len, PAGE_SIZE);
+ start = 0;
+ }
+ nr_pages += npages;
}
kfree(pages);
Add support for folios larger than one page size for direct io. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> --- fs/fuse/file.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-)