]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
fuse: support large folios for readahead
authorJoanne Koong <joannelkoong@gmail.com>
Mon, 12 May 2025 22:58:38 +0000 (15:58 -0700)
committerMiklos Szeredi <mszeredi@redhat.com>
Thu, 29 May 2025 10:31:23 +0000 (12:31 +0200)
Add support for folios larger than one page size for readahead.

Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
fs/fuse/file.c

index f221a45b4bad4fd95a631ee21f03f63b90e8225c..07ff81469a59346a4549c4c59b8e2b44a8b163f6 100644 (file)
@@ -876,14 +876,13 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
        fuse_io_free(ia);
 }
 
-static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
+static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file,
+                               unsigned int count)
 {
        struct fuse_file *ff = file->private_data;
        struct fuse_mount *fm = ff->fm;
        struct fuse_args_pages *ap = &ia->ap;
        loff_t pos = folio_pos(ap->folios[0]);
-       /* Currently, all folios in FUSE are one page */
-       size_t count = ap->num_folios << PAGE_SHIFT;
        ssize_t res;
        int err;
 
@@ -918,6 +917,7 @@ static void fuse_readahead(struct readahead_control *rac)
        struct inode *inode = rac->mapping->host;
        struct fuse_conn *fc = get_fuse_conn(inode);
        unsigned int max_pages, nr_pages;
+       struct folio *folio = NULL;
 
        if (fuse_is_bad(inode))
                return;
@@ -939,8 +939,8 @@ static void fuse_readahead(struct readahead_control *rac)
        while (nr_pages) {
                struct fuse_io_args *ia;
                struct fuse_args_pages *ap;
-               struct folio *folio;
                unsigned cur_pages = min(max_pages, nr_pages);
+               unsigned int pages = 0;
 
                if (fc->num_background >= fc->congestion_threshold &&
                    rac->ra->async_size >= readahead_count(rac))
@@ -952,10 +952,12 @@ static void fuse_readahead(struct readahead_control *rac)
 
                ia = fuse_io_alloc(NULL, cur_pages);
                if (!ia)
-                       return;
+                       break;
                ap = &ia->ap;
 
-               while (ap->num_folios < cur_pages) {
+               while (pages < cur_pages) {
+                       unsigned int folio_pages;
+
                        /*
                         * This returns a folio with a ref held on it.
                         * The ref needs to be held until the request is
@@ -963,13 +965,31 @@ static void fuse_readahead(struct readahead_control *rac)
                         * fuse_try_move_page()) drops the ref after it's
                         * replaced in the page cache.
                         */
-                       folio = __readahead_folio(rac);
+                       if (!folio)
+                               folio =  __readahead_folio(rac);
+
+                       folio_pages = folio_nr_pages(folio);
+                       if (folio_pages > cur_pages - pages) {
+                               /*
+                                * Large folios belonging to fuse will never
+                                * have more pages than max_pages.
+                                */
+                               WARN_ON(!pages);
+                               break;
+                       }
+
                        ap->folios[ap->num_folios] = folio;
                        ap->descs[ap->num_folios].length = folio_size(folio);
                        ap->num_folios++;
+                       pages += folio_pages;
+                       folio = NULL;
                }
-               fuse_send_readpages(ia, rac->file);
-               nr_pages -= cur_pages;
+               fuse_send_readpages(ia, rac->file, pages << PAGE_SHIFT);
+               nr_pages -= pages;
+       }
+       if (folio) {
+               folio_end_read(folio, false);
+               folio_put(folio);
        }
 }