diff mbox series

[10/12] fuse: support large folios for direct io

Message ID 20241109001258.2216604-11-joannelkoong@gmail.com (mailing list archive)
State New
Headers show
Series fuse: support large folios | expand

Commit Message

Joanne Koong Nov. 9, 2024, 12:12 a.m. UTC
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(-)
diff mbox series

Patch

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