Skip to content

Commit 906354c

Browse files
joannekoongMiklos Szeredi
authored andcommitted
fuse: support large folios for readahead
Add support for folios larger than one page size for readahead. Signed-off-by: Joanne Koong <[email protected]> Reviewed-by: Jeff Layton <[email protected]> Signed-off-by: Miklos Szeredi <[email protected]>
1 parent ff7c3ee commit 906354c

File tree

1 file changed

+29
-9
lines changed

1 file changed

+29
-9
lines changed

fs/fuse/file.c

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -876,14 +876,13 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
876876
fuse_io_free(ia);
877877
}
878878

879-
static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
879+
static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file,
880+
unsigned int count)
880881
{
881882
struct fuse_file *ff = file->private_data;
882883
struct fuse_mount *fm = ff->fm;
883884
struct fuse_args_pages *ap = &ia->ap;
884885
loff_t pos = folio_pos(ap->folios[0]);
885-
/* Currently, all folios in FUSE are one page */
886-
size_t count = ap->num_folios << PAGE_SHIFT;
887886
ssize_t res;
888887
int err;
889888

@@ -918,6 +917,7 @@ static void fuse_readahead(struct readahead_control *rac)
918917
struct inode *inode = rac->mapping->host;
919918
struct fuse_conn *fc = get_fuse_conn(inode);
920919
unsigned int max_pages, nr_pages;
920+
struct folio *folio = NULL;
921921

922922
if (fuse_is_bad(inode))
923923
return;
@@ -939,8 +939,8 @@ static void fuse_readahead(struct readahead_control *rac)
939939
while (nr_pages) {
940940
struct fuse_io_args *ia;
941941
struct fuse_args_pages *ap;
942-
struct folio *folio;
943942
unsigned cur_pages = min(max_pages, nr_pages);
943+
unsigned int pages = 0;
944944

945945
if (fc->num_background >= fc->congestion_threshold &&
946946
rac->ra->async_size >= readahead_count(rac))
@@ -952,24 +952,44 @@ static void fuse_readahead(struct readahead_control *rac)
952952

953953
ia = fuse_io_alloc(NULL, cur_pages);
954954
if (!ia)
955-
return;
955+
break;
956956
ap = &ia->ap;
957957

958-
while (ap->num_folios < cur_pages) {
958+
while (pages < cur_pages) {
959+
unsigned int folio_pages;
960+
959961
/*
960962
* This returns a folio with a ref held on it.
961963
* The ref needs to be held until the request is
962964
* completed, since the splice case (see
963965
* fuse_try_move_page()) drops the ref after it's
964966
* replaced in the page cache.
965967
*/
966-
folio = __readahead_folio(rac);
968+
if (!folio)
969+
folio = __readahead_folio(rac);
970+
971+
folio_pages = folio_nr_pages(folio);
972+
if (folio_pages > cur_pages - pages) {
973+
/*
974+
* Large folios belonging to fuse will never
975+
* have more pages than max_pages.
976+
*/
977+
WARN_ON(!pages);
978+
break;
979+
}
980+
967981
ap->folios[ap->num_folios] = folio;
968982
ap->descs[ap->num_folios].length = folio_size(folio);
969983
ap->num_folios++;
984+
pages += folio_pages;
985+
folio = NULL;
970986
}
971-
fuse_send_readpages(ia, rac->file);
972-
nr_pages -= cur_pages;
987+
fuse_send_readpages(ia, rac->file, pages << PAGE_SHIFT);
988+
nr_pages -= pages;
989+
}
990+
if (folio) {
991+
folio_end_read(folio, false);
992+
folio_put(folio);
973993
}
974994
}
975995

0 commit comments

Comments
 (0)