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>
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;
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;
}
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)
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;
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++;
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;
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;
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;
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);
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,
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;
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)
/* 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);
*/
break;
- ia = fuse_io_folios_alloc(NULL, cur_pages);
+ ia = fuse_io_alloc(NULL, cur_pages);
if (!ia)
return;
ap = &ia->ap;
while (ap->num_folios < cur_pages) {
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);
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];
int err;
ap->args.in_pages = true;
- ap->folio_descs[0].offset = offset;
+ ap->descs[0].offset = offset;
do {
size_t tmp;
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++;
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;
/* 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;
}
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;
}
}
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;
}
}
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) {
}
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;
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;
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);
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;
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;
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;
};
struct fuse_release_args {
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.
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])
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,
struct fuse_args *args;
struct fuse_args_pages *ap;
unsigned int len, i, thislen;
- struct page *page;
struct folio *folio;
/*
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;
}
}
}
}
/* 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;
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))
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;
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;