On 4/26/25 02:08, Joanne Koong wrote: > Add support for folios larger than one page size for retrieves. > > Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> > Reviewed-by: Josef Bacik <josef@xxxxxxxxxxxxxx> > Reviewed-by: Jeff Layton <jlayton@xxxxxxxxxx> Reviewed-by: Bernd Schubert <bschubert@xxxxxxx> > --- > fs/fuse/dev.c | 25 +++++++++++++++---------- > 1 file changed, 15 insertions(+), 10 deletions(-) > > diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c > index 7b0e3a394480..fb81c0a1c6cd 100644 > --- a/fs/fuse/dev.c > +++ b/fs/fuse/dev.c > @@ -1837,7 +1837,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, > unsigned int num; > unsigned int offset; > size_t total_len = 0; > - unsigned int num_pages, cur_pages = 0; > + unsigned int num_pages; > struct fuse_conn *fc = fm->fc; > struct fuse_retrieve_args *ra; > size_t args_size = sizeof(*ra); > @@ -1855,6 +1855,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, > > num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT; > num_pages = min(num_pages, fc->max_pages); > + num = min(num, num_pages << PAGE_SHIFT); > > args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->descs[0])); > > @@ -1875,25 +1876,29 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, > > index = outarg->offset >> PAGE_SHIFT; > > - while (num && cur_pages < num_pages) { > + while (num) { > struct folio *folio; > - unsigned int this_num; > + unsigned int folio_offset; > + unsigned int nr_bytes; > + unsigned int nr_pages; > > folio = filemap_get_folio(mapping, index); > if (IS_ERR(folio)) > break; > > - this_num = min_t(unsigned, num, PAGE_SIZE - offset); > + folio_offset = ((index - folio->index) << PAGE_SHIFT) + offset; > + nr_bytes = min(folio_size(folio) - folio_offset, num); > + nr_pages = (offset + nr_bytes + PAGE_SIZE - 1) >> PAGE_SHIFT; > + > ap->folios[ap->num_folios] = folio; > - ap->descs[ap->num_folios].offset = offset; > - ap->descs[ap->num_folios].length = this_num; > + ap->descs[ap->num_folios].offset = folio_offset; > + ap->descs[ap->num_folios].length = nr_bytes; > ap->num_folios++; > - cur_pages++; > > offset = 0; > - num -= this_num; > - total_len += this_num; > - index++; > + num -= nr_bytes; > + total_len += nr_bytes; > + index += nr_pages; > } > ra->inarg.offset = outarg->offset; > ra->inarg.size = total_len;