On Fri, Nov 08, 2024 at 04:12:47PM -0800, Joanne Koong wrote: > Currently, all folios associated with fuse are one page size. As part of > the work to enable large folios, this commit adds support for copying > to/from folios larger than one page size. > > Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> > --- > fs/fuse/dev.c | 89 +++++++++++++++++++++++---------------------------- > 1 file changed, 40 insertions(+), 49 deletions(-) > > diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c > index 29fc61a072ba..9914cc1243f4 100644 > --- a/fs/fuse/dev.c > +++ b/fs/fuse/dev.c > @@ -703,7 +703,7 @@ struct fuse_copy_state { > struct page *pg; > unsigned len; > unsigned offset; > - unsigned move_pages:1; > + unsigned move_folios:1; > }; > > static void fuse_copy_init(struct fuse_copy_state *cs, int write, > @@ -836,10 +836,10 @@ static int fuse_check_folio(struct folio *folio) > return 0; > } > > -static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) > +static int fuse_try_move_folio(struct fuse_copy_state *cs, struct folio **foliop) > { > int err; > - struct folio *oldfolio = page_folio(*pagep); > + struct folio *oldfolio = *foliop; > struct folio *newfolio; > struct pipe_buffer *buf = cs->pipebufs; > > @@ -860,7 +860,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) > cs->pipebufs++; > cs->nr_segs--; > > - if (cs->len != PAGE_SIZE) > + if (cs->len != folio_size(oldfolio)) > goto out_fallback; > > if (!pipe_buf_try_steal(cs->pipe, buf)) > @@ -906,7 +906,7 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) > if (test_bit(FR_ABORTED, &cs->req->flags)) > err = -ENOENT; > else > - *pagep = &newfolio->page; > + *foliop = newfolio; > spin_unlock(&cs->req->waitq.lock); > > if (err) { > @@ -939,8 +939,8 @@ static int fuse_try_move_page(struct fuse_copy_state *cs, struct page **pagep) > goto out_put_old; > } > > -static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page, > - unsigned offset, unsigned count) > +static int fuse_ref_folio(struct fuse_copy_state *cs, struct folio *folio, > + unsigned offset, unsigned count) > { > struct pipe_buffer *buf; > int err; > @@ -948,17 +948,17 @@ static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page, > if (cs->nr_segs >= cs->pipe->max_usage) > return -EIO; > > - get_page(page); > + folio_get(folio); > err = unlock_request(cs->req); > if (err) { > - put_page(page); > + folio_put(folio); > return err; > } > > fuse_copy_finish(cs); > > buf = cs->pipebufs; > - buf->page = page; > + buf->page = &folio->page; > buf->offset = offset; > buf->len = count; > > @@ -970,20 +970,24 @@ static int fuse_ref_page(struct fuse_copy_state *cs, struct page *page, > } > > /* > - * Copy a page in the request to/from the userspace buffer. Must be > + * Copy a folio in the request to/from the userspace buffer. Must be > * done atomically > */ > -static int fuse_copy_page(struct fuse_copy_state *cs, struct page **pagep, > - unsigned offset, unsigned count, int zeroing) > +static int fuse_copy_folio(struct fuse_copy_state *cs, struct folio **foliop, > + unsigned offset, unsigned count, int zeroing) > { > int err; > - struct page *page = *pagep; > + struct folio *folio = *foliop; > + size_t size = folio_size(folio); > > - if (page && zeroing && count < PAGE_SIZE) > - clear_highpage(page); > + if (folio && zeroing && count < size) { > + void *kaddr = kmap_local_folio(folio, 0); > + memset(kaddr, 0, size); > + kunmap_local(kaddr); There's a folio_zero_range() that can be used here instead of this, but be sure you get it right, I definitely did it wrong recently and I think Jan had to fix my mistake. Thanks, Josef