
From: Joanne Koong <joannelkoong@gmail.com> All fuse requests use folios instead of pages for transferring data. Remove pages from the requests and exclusively use folios. No functional changes. [SzM: rename back folio_descs -> descs, etc.] Signed-off-by: Joanne Koong <joannelkoong@gmail.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> --- fs/fuse/cuse.c | 3 +- fs/fuse/dev.c | 57 ++++++++++----------------- fs/fuse/dir.c | 3 +- fs/fuse/file.c | 58 +++++++++++++--------------- fs/fuse/fuse_i.h | 22 ++--------- fs/fuse/ioctl.c | 5 +-- fs/fuse/readdir.c | 3 +- fs/fuse/virtio_fs.c | 93 +++++++++++++++++---------------------------- 8 files changed, 90 insertions(+), 154 deletions(-) diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c index 6018af98dd08..40f3e640e055 100644 --- a/fs/fuse/cuse.c +++ b/fs/fuse/cuse.c @@ -456,10 +456,9 @@ static int cuse_send_init(struct cuse_conn *cc) ap->args.out_args[1].size = CUSE_INIT_INFO_MAX; ap->args.out_argvar = true; ap->args.out_pages = true; - ap->uses_folios = true; ap->num_folios = 1; ap->folios = &ia->folio; - ap->folio_descs = &ia->desc; + ap->descs = &ia->desc; ia->folio = folio; ia->desc.length = ap->args.out_args[1].size; ap->args.end = cuse_process_init_reply; diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 57790734ad48..875d7ecd2fde 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -983,41 +983,27 @@ 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_folios && (nbytes || zeroing); i++) { + int err; + unsigned int offset = ap->descs[i].offset; + unsigned int count = min(nbytes, ap->descs[i].length); + struct page *orig, *pagep; - orig = pagep = &ap->folios[i]->page; + orig = pagep = &ap->folios[i]->page; - err = fuse_copy_page(cs, &pagep, offset, count, zeroing); - if (err) - return err; - - nbytes -= count; - - /* - * 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. - */ - 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, &pagep, offset, count, zeroing); + if (err) + return err; - err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing); - if (err) - return err; + nbytes -= count; - nbytes -= count; - } + /* + * 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. + */ + if (pagep != orig) + ap->folios[i] = page_folio(pagep); } return 0; } @@ -1717,7 +1703,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); - args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->folio_descs[0])); + args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->descs[0])); ra = kzalloc(args_size, GFP_KERNEL); if (!ra) @@ -1725,8 +1711,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, ap = &ra->ap; ap->folios = (void *) (ra + 1); - ap->folio_descs = (void *) (ap->folios + num_pages); - ap->uses_folios = true; + ap->descs = (void *) (ap->folios + num_pages); args = &ap->args; args->nodeid = outarg->nodeid; @@ -1747,8 +1732,8 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode, this_num = min_t(unsigned, num, PAGE_SIZE - offset); ap->folios[ap->num_folios] = folio; - ap->folio_descs[ap->num_folios].offset = offset; - ap->folio_descs[ap->num_folios].length = this_num; + ap->descs[ap->num_folios].offset = offset; + ap->descs[ap->num_folios].length = this_num; ap->num_folios++; cur_pages++; diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c index a163faefa9c2..b50a091b1dfb 100644 --- a/fs/fuse/dir.c +++ b/fs/fuse/dir.c @@ -1566,10 +1566,9 @@ static int fuse_readlink_page(struct inode *inode, struct folio *folio) struct fuse_mount *fm = get_fuse_mount(inode); struct fuse_folio_desc desc = { .length = PAGE_SIZE - 1 }; struct fuse_args_pages ap = { - .uses_folios = true, .num_folios = 1, .folios = &folio, - .folio_descs = &desc, + .descs = &desc, }; char *link; ssize_t res; diff --git a/fs/fuse/file.c b/fs/fuse/file.c index 94bb0abc2f5b..5eb1571960f5 100644 --- a/fs/fuse/file.c +++ b/fs/fuse/file.c @@ -731,7 +731,7 @@ static void fuse_aio_complete(struct fuse_io_priv *io, int err, ssize_t pos) kref_put(&io->refcnt, fuse_io_release); } -static struct fuse_io_args *fuse_io_folios_alloc(struct fuse_io_priv *io, +static struct fuse_io_args *fuse_io_alloc(struct fuse_io_priv *io, unsigned int nfolios) { struct fuse_io_args *ia; @@ -739,9 +739,8 @@ static struct fuse_io_args *fuse_io_folios_alloc(struct fuse_io_priv *io, ia = kzalloc(sizeof(*ia), GFP_KERNEL); if (ia) { ia->io = io; - ia->ap.uses_folios = true; ia->ap.folios = fuse_folios_alloc(nfolios, GFP_KERNEL, - &ia->ap.folio_descs); + &ia->ap.descs); if (!ia->ap.folios) { kfree(ia); ia = NULL; @@ -750,7 +749,7 @@ static struct fuse_io_args *fuse_io_folios_alloc(struct fuse_io_priv *io, return ia; } -static void fuse_io_folios_free(struct fuse_io_args *ia) +static void fuse_io_free(struct fuse_io_args *ia) { kfree(ia->ap.folios); kfree(ia); @@ -786,7 +785,7 @@ static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args, fuse_release_user_pages(&ia->ap, err ?: nres, io->should_dirty); fuse_aio_complete(io, err, pos); - fuse_io_folios_free(ia); + fuse_io_free(ia); } static ssize_t fuse_async_req_send(struct fuse_mount *fm, @@ -869,10 +868,9 @@ static int fuse_do_readfolio(struct file *file, struct folio *folio) struct fuse_io_args ia = { .ap.args.page_zeroing = true, .ap.args.out_pages = true, - .ap.uses_folios = true, .ap.num_folios = 1, .ap.folios = &folio, - .ap.folio_descs = &desc, + .ap.descs = &desc, }; ssize_t res; u64 attr_ver; @@ -953,7 +951,7 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args, if (ia->ff) fuse_file_put(ia->ff, false); - fuse_io_folios_free(ia); + fuse_io_free(ia); } static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file) @@ -974,7 +972,7 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file) /* Don't overflow end offset */ if (pos + (count - 1) == LLONG_MAX) { count--; - ap->folio_descs[ap->num_folios - 1].length--; + ap->descs[ap->num_folios - 1].length--; } WARN_ON((loff_t) (pos + count) < 0); @@ -1035,7 +1033,7 @@ static void fuse_readahead(struct readahead_control *rac) */ break; - ia = fuse_io_folios_alloc(NULL, cur_pages); + ia = fuse_io_alloc(NULL, cur_pages); if (!ia) return; ap = &ia->ap; @@ -1050,7 +1048,7 @@ static void fuse_readahead(struct readahead_control *rac) */ folio = __readahead_folio(rac); ap->folios[ap->num_folios] = folio; - ap->folio_descs[ap->num_folios].length = folio_size(folio); + ap->descs[ap->num_folios].length = folio_size(folio); ap->num_folios++; } fuse_send_readpages(ia, rac->file); @@ -1184,7 +1182,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia, err = -EIO; short_write = ia->write.out.size < count; - offset = ap->folio_descs[0].offset; + offset = ap->descs[0].offset; count = ia->write.out.size; for (i = 0; i < ap->num_folios; i++) { struct folio *folio = ap->folios[i]; @@ -1222,7 +1220,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, int err; ap->args.in_pages = true; - ap->folio_descs[0].offset = offset; + ap->descs[0].offset = offset; do { size_t tmp; @@ -1259,7 +1257,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, err = 0; ap->folios[ap->num_folios] = folio; - ap->folio_descs[ap->num_folios].length = tmp; + ap->descs[ap->num_folios].length = tmp; ap->num_folios++; nr_pages++; @@ -1316,8 +1314,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii) unsigned int nr_pages = fuse_wr_pages(pos, iov_iter_count(ii), fc->max_pages); - ap->uses_folios = true; - ap->folios = fuse_folios_alloc(nr_pages, GFP_KERNEL, &ap->folio_descs); + ap->folios = fuse_folios_alloc(nr_pages, GFP_KERNEL, &ap->descs); if (!ap->folios) { err = -ENOMEM; break; @@ -1483,13 +1480,13 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii, /* Currently, all folios in FUSE are one page */ nfolios = DIV_ROUND_UP(ret, PAGE_SIZE); - ap->folio_descs[ap->num_folios].offset = start; - fuse_folio_descs_length_init(ap->folio_descs, ap->num_folios, nfolios); + ap->descs[ap->num_folios].offset = start; + fuse_folio_descs_length_init(ap->descs, ap->num_folios, nfolios); for (i = 0; i < nfolios; i++) ap->folios[i + ap->num_folios] = page_folio(pages[i]); ap->num_folios += nfolios; - ap->folio_descs[ap->num_folios - 1].length -= + ap->descs[ap->num_folios - 1].length -= (PAGE_SIZE - ret) & (PAGE_SIZE - 1); nr_pages += nfolios; } @@ -1533,14 +1530,14 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, bool fopen_direct_io = ff->open_flags & FOPEN_DIRECT_IO; max_pages = iov_iter_npages(iter, fc->max_pages); - ia = fuse_io_folios_alloc(io, max_pages); + ia = fuse_io_alloc(io, max_pages); if (!ia) return -ENOMEM; if (fopen_direct_io && fc->direct_io_allow_mmap) { res = filemap_write_and_wait_range(mapping, pos, pos + count - 1); if (res) { - fuse_io_folios_free(ia); + fuse_io_free(ia); return res; } } @@ -1555,7 +1552,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, if (fopen_direct_io && write) { res = invalidate_inode_pages2_range(mapping, idx_from, idx_to); if (res) { - fuse_io_folios_free(ia); + fuse_io_free(ia); return res; } } @@ -1582,7 +1579,7 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, if (!io->async || nres < 0) { fuse_release_user_pages(&ia->ap, nres, io->should_dirty); - fuse_io_folios_free(ia); + fuse_io_free(ia); } ia = NULL; if (nres < 0) { @@ -1601,13 +1598,13 @@ ssize_t fuse_direct_io(struct fuse_io_priv *io, struct iov_iter *iter, } if (count) { max_pages = iov_iter_npages(iter, fc->max_pages); - ia = fuse_io_folios_alloc(io, max_pages); + ia = fuse_io_alloc(io, max_pages); if (!ia) break; } } if (ia) - fuse_io_folios_free(ia); + fuse_io_free(ia); if (res > 0) *ppos = pos; @@ -2017,8 +2014,7 @@ static struct fuse_writepage_args *fuse_writepage_args_alloc(void) if (wpa) { ap = &wpa->ia.ap; ap->num_folios = 0; - ap->uses_folios = true; - ap->folios = fuse_folios_alloc(1, GFP_NOFS, &ap->folio_descs); + ap->folios = fuse_folios_alloc(1, GFP_NOFS, &ap->descs); if (!ap->folios) { kfree(wpa); wpa = NULL; @@ -2051,8 +2047,8 @@ static void fuse_writepage_args_page_fill(struct fuse_writepage_args *wpa, struc folio_copy(tmp_folio, folio); ap->folios[folio_index] = tmp_folio; - ap->folio_descs[folio_index].offset = 0; - ap->folio_descs[folio_index].length = PAGE_SIZE; + ap->descs[folio_index].offset = 0; + ap->descs[folio_index].length = PAGE_SIZE; inc_wb_stat(&inode_to_bdi(inode)->wb, WB_WRITEBACK); node_stat_add_folio(tmp_folio, NR_WRITEBACK_TEMP); @@ -2158,10 +2154,10 @@ static bool fuse_pages_realloc(struct fuse_fill_wb_data *data) return false; memcpy(folios, ap->folios, sizeof(struct folio *) * ap->num_folios); - memcpy(descs, ap->folio_descs, sizeof(struct fuse_folio_desc) * ap->num_folios); + memcpy(descs, ap->descs, sizeof(struct fuse_folio_desc) * ap->num_folios); kfree(ap->folios); ap->folios = folios; - ap->folio_descs = descs; + ap->descs = descs; data->max_folios = nfolios; return true; diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index 87bedbca529d..51e95eac47ff 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -263,12 +263,6 @@ struct fuse_arg { void *value; }; -/** FUSE page descriptor */ -struct fuse_page_desc { - unsigned int length; - unsigned int offset; -}; - /** FUSE folio descriptor */ struct fuse_folio_desc { unsigned int length; @@ -303,19 +297,9 @@ struct fuse_args { struct fuse_args_pages { struct fuse_args args; - 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 folio **folios; + struct fuse_folio_desc *descs; + unsigned int num_folios; }; #define FUSE_ARGS(args) struct fuse_args args = {} diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c index dc3e7c8ff97b..27115c618e94 100644 --- a/fs/fuse/ioctl.c +++ b/fs/fuse/ioctl.c @@ -201,12 +201,12 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, BUILD_BUG_ON(sizeof(struct fuse_ioctl_iovec) * FUSE_IOCTL_MAX_IOV > PAGE_SIZE); err = -ENOMEM; - ap.folios = fuse_folios_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.folio_descs); + ap.folios = fuse_folios_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs); iov_page = (struct iovec *) __get_free_page(GFP_KERNEL); if (!ap.folios || !iov_page) goto out; - fuse_folio_descs_length_init(ap.folio_descs, 0, fm->fc->max_pages); + fuse_folio_descs_length_init(ap.descs, 0, fm->fc->max_pages); /* * If restricted, initialize IO parameters as encoded in @cmd. @@ -244,7 +244,6 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg, err = -ENOMEM; if (max_pages > fm->fc->max_pages) goto out; - ap.uses_folios = true; while (ap.num_folios < max_pages) { ap.folios[ap.num_folios] = folio_alloc(GFP_KERNEL | __GFP_HIGHMEM, 0); if (!ap.folios[ap.num_folios]) diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c index 32604211403c..70dbdc4725e0 100644 --- a/fs/fuse/readdir.c +++ b/fs/fuse/readdir.c @@ -346,10 +346,9 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx) plus = fuse_use_readdirplus(inode, ctx); ap->args.out_pages = true; - ap->uses_folios = true; ap->num_folios = 1; ap->folios = &folio; - ap->folio_descs = &desc; + ap->descs = &desc; if (plus) { attr_version = fuse_get_attr_version(fm->fc); fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE, diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c index f974c7896783..591fb2beacde 100644 --- a/fs/fuse/virtio_fs.c +++ b/fs/fuse/virtio_fs.c @@ -623,7 +623,6 @@ static void virtio_fs_request_complete(struct fuse_req *req, struct fuse_args *args; struct fuse_args_pages *ap; unsigned int len, i, thislen; - struct page *page; struct folio *folio; /* @@ -636,29 +635,15 @@ static void virtio_fs_request_complete(struct fuse_req *req, if (args->out_pages && args->page_zeroing) { len = args->out_args[args->out_numargs - 1].size; ap = container_of(args, typeof(*ap), args); - if (ap->uses_folios) { - for (i = 0; i < ap->num_folios; i++) { - thislen = ap->folio_descs[i].length; - if (len < thislen) { - WARN_ON(ap->folio_descs[i].offset); - folio = ap->folios[i]; - folio_zero_segment(folio, len, thislen); - len = 0; - } else { - len -= thislen; - } - } - } else { - for (i = 0; i < ap->num_pages; i++) { - thislen = ap->descs[i].length; - if (len < thislen) { - WARN_ON(ap->descs[i].offset); - page = ap->pages[i]; - zero_user_segment(page, len, thislen); - len = 0; - } else { - len -= thislen; - } + for (i = 0; i < ap->num_folios; i++) { + thislen = ap->descs[i].length; + if (len < thislen) { + WARN_ON(ap->descs[i].offset); + folio = ap->folios[i]; + folio_zero_segment(folio, len, thislen); + len = 0; + } else { + len -= thislen; } } } @@ -1147,22 +1132,16 @@ __releases(fiq->lock) } /* Count number of scatter-gather elements required */ -static unsigned int sg_count_fuse_pages(struct fuse_args_pages *ap, - unsigned int total_len) +static unsigned int sg_count_fuse_folios(struct fuse_folio_desc *folio_descs, + unsigned int num_folios, + unsigned int total_len) { unsigned int i; unsigned int this_len; - if (ap->uses_folios) { - for (i = 0; i < ap->num_folios && total_len; i++) { - this_len = min(ap->folio_descs[i].length, total_len); - total_len -= this_len; - } - } else { - for (i = 0; i < ap->num_pages && total_len; i++) { - this_len = min(ap->descs[i].length, total_len); - total_len -= this_len; - } + for (i = 0; i < num_folios && total_len; i++) { + this_len = min(folio_descs[i].length, total_len); + total_len -= this_len; } return i; @@ -1180,7 +1159,8 @@ static unsigned int sg_count_fuse_req(struct fuse_req *req) if (args->in_pages) { size = args->in_args[args->in_numargs - 1].size; - total_sgs += sg_count_fuse_pages(ap, size); + total_sgs += sg_count_fuse_folios(ap->descs, ap->num_folios, + size); } if (!test_bit(FR_ISREPLY, &req->flags)) @@ -1193,35 +1173,28 @@ static unsigned int sg_count_fuse_req(struct fuse_req *req) if (args->out_pages) { size = args->out_args[args->out_numargs - 1].size; - total_sgs += sg_count_fuse_pages(ap, size); + total_sgs += sg_count_fuse_folios(ap->descs, ap->num_folios, + size); } return total_sgs; } -/* Add pages/folios to scatter-gather list and return number of elements used */ -static unsigned int sg_init_fuse_pages(struct scatterlist *sg, - struct fuse_args_pages *ap, - unsigned int total_len) +/* Add folios to scatter-gather list and return number of elements used */ +static unsigned int sg_init_fuse_folios(struct scatterlist *sg, + struct folio **folios, + struct fuse_folio_desc *folio_descs, + unsigned int num_folios, + unsigned int total_len) { unsigned int i; unsigned int this_len; - if (ap->uses_folios) { - for (i = 0; i < ap->num_folios && total_len; i++) { - sg_init_table(&sg[i], 1); - this_len = min(ap->folio_descs[i].length, total_len); - sg_set_folio(&sg[i], ap->folios[i], this_len, - ap->folio_descs[i].offset); - total_len -= this_len; - } - } else { - for (i = 0; i < ap->num_pages && total_len; i++) { - sg_init_table(&sg[i], 1); - this_len = min(ap->descs[i].length, total_len); - sg_set_page(&sg[i], ap->pages[i], this_len, ap->descs[i].offset); - total_len -= this_len; - } + for (i = 0; i < num_folios && total_len; i++) { + sg_init_table(&sg[i], 1); + this_len = min(folio_descs[i].length, total_len); + sg_set_folio(&sg[i], folios[i], this_len, folio_descs[i].offset); + total_len -= this_len; } return i; @@ -1245,8 +1218,10 @@ static unsigned int sg_init_fuse_args(struct scatterlist *sg, sg_init_one(&sg[total_sgs++], argbuf, len); if (argpages) - total_sgs += sg_init_fuse_pages(&sg[total_sgs], ap, - args[numargs - 1].size); + total_sgs += sg_init_fuse_folios(&sg[total_sgs], + ap->folios, ap->descs, + ap->num_folios, + args[numargs - 1].size); if (len_used) *len_used = len; -- 2.46.1