Add support for folios larger than one page size for direct io. Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> --- fs/fuse/file.c | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 255c7f2f2ed4..54e2b58df82f 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -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); -- 2.43.5