Message ID | 20241002165253.3872513-2-joannelkoong@gmail.com (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | fuse: use folios instead of pages for requests | expand |
On Wed, Oct 02, 2024 at 09:52:41AM -0700, Joanne Koong wrote: > This adds support in struct fuse_args_pages and fuse_copy_pages() for > using folios instead of pages for transferring data. Both folios and > pages must be supported right now in struct fuse_args_pages and > fuse_copy_pages() until all request types have been converted to use > folios. Once all have been converted, then > struct fuse_args_pages and fuse_copy_pages() will only support folios. > > Right now in fuse, all folios are one page (large folios are not yet > supported). As such, copying folio->page is sufficient for copying > the entire folio in fuse_copy_pages(). > > No functional changes. > > Signed-off-by: Joanne Koong <joannelkoong@gmail.com> > --- > fs/fuse/dev.c | 36 ++++++++++++++++++++++++++++-------- > fs/fuse/fuse_i.h | 22 +++++++++++++++++++--- > 2 files changed, 47 insertions(+), 11 deletions(-) > > diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c > index 7e4c5be45aec..cd9c5e0eefca 100644 > --- a/fs/fuse/dev.c > +++ b/fs/fuse/dev.c > @@ -1028,17 +1028,37 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, > struct fuse_req *req = cs->req; > struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); > > + if (ap->uses_folios) { > + for (i = 0; i < ap->num_folios && (nbytes || zeroing); i++) { > + int err; > + unsigned int offset = ap->folio_descs[i].offset; > + unsigned int count = min(nbytes, ap->folio_descs[i].length); > + struct page *orig, *pagep; > > - for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { > - int err; > - unsigned int offset = ap->descs[i].offset; > - unsigned int count = min(nbytes, ap->descs[i].length); > + orig = pagep = &ap->folios[i]->page; > > - err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); > - if (err) > - return err; > + err = fuse_copy_page(cs, &pagep, offset, count, zeroing); > + if (err) > + return err; > + > + nbytes -= count; > + > + /* Check if the folio was replaced in the page cache */ This comment confused me, I think it would be better to say something like /* * fuse_copy_page may have moved a page from a pipe instead of copying into our * given page, so update the folios if it was replaced. */ Or something like that. Thanks, Josef
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 7e4c5be45aec..cd9c5e0eefca 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -1028,17 +1028,37 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes, struct fuse_req *req = cs->req; struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args); + if (ap->uses_folios) { + for (i = 0; i < ap->num_folios && (nbytes || zeroing); i++) { + int err; + unsigned int offset = ap->folio_descs[i].offset; + unsigned int count = min(nbytes, ap->folio_descs[i].length); + struct page *orig, *pagep; - for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { - int err; - unsigned int offset = ap->descs[i].offset; - unsigned int count = min(nbytes, ap->descs[i].length); + orig = pagep = &ap->folios[i]->page; - err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); - if (err) - return err; + err = fuse_copy_page(cs, &pagep, offset, count, zeroing); + if (err) + return err; + + nbytes -= count; + + /* Check if the folio was replaced in the page cache */ + if (pagep != orig) + ap->folios[i] = page_folio(pagep); + } + } else { + for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) { + int err; + unsigned int offset = ap->descs[i].offset; + unsigned int count = min(nbytes, ap->descs[i].length); + + err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); + if (err) + return err; - nbytes -= count; + nbytes -= count; + } } return 0; } diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 7ff00bae4a84..dcc0ab4bea78 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -291,6 +291,12 @@ struct fuse_page_desc { unsigned int offset; }; +/** FUSE folio descriptor */ +struct fuse_folio_desc { + unsigned int length; + unsigned int offset; +}; + struct fuse_args { uint64_t nodeid; uint32_t opcode; @@ -316,9 +322,19 @@ struct fuse_args { struct fuse_args_pages { struct fuse_args args; - struct page **pages; - struct fuse_page_desc *descs; - unsigned int num_pages; + union { + struct { + struct page **pages; + struct fuse_page_desc *descs; + unsigned int num_pages; + }; + struct { + struct folio **folios; + struct fuse_folio_desc *folio_descs; + unsigned int num_folios; + }; + }; + bool uses_folios; }; struct fuse_release_args {
This adds support in struct fuse_args_pages and fuse_copy_pages() for using folios instead of pages for transferring data. Both folios and pages must be supported right now in struct fuse_args_pages and fuse_copy_pages() until all request types have been converted to use folios. Once all have been converted, then struct fuse_args_pages and fuse_copy_pages() will only support folios. Right now in fuse, all folios are one page (large folios are not yet supported). As such, copying folio->page is sufficient for copying the entire folio in fuse_copy_pages(). No functional changes. Signed-off-by: Joanne Koong <joannelkoong@gmail.com> --- fs/fuse/dev.c | 36 ++++++++++++++++++++++++++++-------- fs/fuse/fuse_i.h | 22 +++++++++++++++++++--- 2 files changed, 47 insertions(+), 11 deletions(-)