* [PATCH v2 00/13] fuse: use folios instead of pages for requests
@ 2024-10-22 18:54 Joanne Koong
2024-10-22 18:54 ` [PATCH v2 01/13] fuse: support folios in struct fuse_args_pages and fuse_copy_pages() Joanne Koong
` (12 more replies)
0 siblings, 13 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
This patchset converts fuse requests to use folios instead of pages. Right
now, all folios in fuse are one page, but a subsequent patchset will be
enabling larger-size folios on fuse. This patchset has no functional
changes. Any multi-page allocations for requests (eg ioctl request) will
also be optimized in a subsequent patchset as well.
v1: https://lore.kernel.org/linux-fsdevel/20241002165253.3872513-1-joannelkoong@gmail.com/
Changes from v1 -> v2:
* Address Josef's comments on v1
- Clarify comment about folio replacement in page cache
- Remove unused fuse_page_descs_length_init() and fuse_pages_alloc()
- Copy comment to folio_mark_dirty_lock()
* Add Josef's Reviewed-bys
* Refactor page_set_dirty_lock() to use folio_mark_dirty_lock()
* Keep using variable naming "nr_pages" in some places (eg fuse_direct_io)
instead of "nr_folios" to make accounting more clear for max_pages, which
reduce variable naming churn in subsequent patchset that supports large folio.
Joanne Koong (13):
fuse: support folios in struct fuse_args_pages and fuse_copy_pages()
fuse: add support in virtio for requests using folios
fuse: convert cuse to use folios
fuse: convert readlink to use folios
fuse: convert readdir to use folios
fuse: convert reads to use folios
fuse: convert writes (non-writeback) to use folios
fuse: convert ioctls to use folios
fuse: convert retrieves to use folios
fuse: convert writebacks to use folios
mm/writeback: add folio_mark_dirty_lock()
fuse: convert direct io to use folios
fuse: remove pages for requests and exclusively use folios
fs/fuse/cuse.c | 31 ++---
fs/fuse/dev.c | 42 ++++---
fs/fuse/dir.c | 28 ++---
fs/fuse/file.c | 268 +++++++++++++++++++++++---------------------
fs/fuse/fuse_i.h | 36 +++---
fs/fuse/ioctl.c | 31 +++--
fs/fuse/readdir.c | 20 ++--
fs/fuse/virtio_fs.c | 58 +++++-----
include/linux/mm.h | 1 +
mm/folio-compat.c | 6 +
mm/page-writeback.c | 22 ++--
11 files changed, 292 insertions(+), 251 deletions(-)
--
2.43.5
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v2 01/13] fuse: support folios in struct fuse_args_pages and fuse_copy_pages()
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 02/13] fuse: add support in virtio for requests using folios Joanne Koong
` (11 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
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>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/dev.c | 40 ++++++++++++++++++++++++++++++++--------
fs/fuse/fuse_i.h | 22 +++++++++++++++++++---
2 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 5edad55750b0..9f860bd655a4 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1028,17 +1028,41 @@ 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;
+
+ /*
+ * 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);
- nbytes -= count;
+ err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing);
+ if (err)
+ return err;
+
+ nbytes -= count;
+ }
}
return 0;
}
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 671daa4d07ad..24a3da8400d1 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;
@@ -319,9 +325,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 {
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 02/13] fuse: add support in virtio for requests using folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
2024-10-22 18:54 ` [PATCH v2 01/13] fuse: support folios in struct fuse_args_pages and fuse_copy_pages() Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 03/13] fuse: convert cuse to use folios Joanne Koong
` (10 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Until all requests have been converted to use folios instead of pages,
virtio will need to support both types. Once all requests have been
converted, then virtio will support just folios.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/virtio_fs.c | 87 +++++++++++++++++++++++++++++----------------
1 file changed, 56 insertions(+), 31 deletions(-)
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index f68527891929..9f0d98cc20d3 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -766,6 +766,7 @@ static void virtio_fs_request_complete(struct fuse_req *req,
struct fuse_args_pages *ap;
unsigned int len, i, thislen;
struct page *page;
+ struct folio *folio;
/*
* TODO verify that server properly follows FUSE protocol
@@ -777,15 +778,29 @@ 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);
- 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;
+ 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;
+ }
}
}
}
@@ -1272,16 +1287,22 @@ static void virtio_fs_send_interrupt(struct fuse_iqueue *fiq, struct fuse_req *r
}
/* Count number of scatter-gather elements required */
-static unsigned int sg_count_fuse_pages(struct fuse_page_desc *page_descs,
- unsigned int num_pages,
- unsigned int total_len)
+static unsigned int sg_count_fuse_pages(struct fuse_args_pages *ap,
+ unsigned int total_len)
{
unsigned int i;
unsigned int this_len;
- for (i = 0; i < num_pages && total_len; i++) {
- this_len = min(page_descs[i].length, total_len);
- total_len -= 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;
+ }
}
return i;
@@ -1299,8 +1320,7 @@ 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->descs, ap->num_pages,
- size);
+ total_sgs += sg_count_fuse_pages(ap, size);
}
if (!test_bit(FR_ISREPLY, &req->flags))
@@ -1313,28 +1333,35 @@ 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->descs, ap->num_pages,
- size);
+ total_sgs += sg_count_fuse_pages(ap, size);
}
return total_sgs;
}
-/* Add pages to scatter-gather list and return number of elements used */
+/* Add pages/folios to scatter-gather list and return number of elements used */
static unsigned int sg_init_fuse_pages(struct scatterlist *sg,
- struct page **pages,
- struct fuse_page_desc *page_descs,
- unsigned int num_pages,
+ struct fuse_args_pages *ap,
unsigned int total_len)
{
unsigned int i;
unsigned int this_len;
- for (i = 0; i < num_pages && total_len; i++) {
- sg_init_table(&sg[i], 1);
- this_len = min(page_descs[i].length, total_len);
- sg_set_page(&sg[i], pages[i], this_len, page_descs[i].offset);
- total_len -= 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;
+ }
}
return i;
@@ -1358,9 +1385,7 @@ 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->pages, ap->descs,
- ap->num_pages,
+ total_sgs += sg_init_fuse_pages(&sg[total_sgs], ap,
args[numargs - 1].size);
if (len_used)
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 03/13] fuse: convert cuse to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
2024-10-22 18:54 ` [PATCH v2 01/13] fuse: support folios in struct fuse_args_pages and fuse_copy_pages() Joanne Koong
2024-10-22 18:54 ` [PATCH v2 02/13] fuse: add support in virtio for requests using folios Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 04/13] fuse: convert readlink " Joanne Koong
` (9 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert cuse requests to use a folio instead of a page.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/cuse.c | 32 +++++++++++++++++---------------
1 file changed, 17 insertions(+), 15 deletions(-)
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index 0b2da7b7e2ad..eed78e303139 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -303,8 +303,8 @@ struct cuse_init_args {
struct fuse_args_pages ap;
struct cuse_init_in in;
struct cuse_init_out out;
- struct page *page;
- struct fuse_page_desc desc;
+ struct folio *folio;
+ struct fuse_folio_desc desc;
};
/**
@@ -326,7 +326,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
struct fuse_args_pages *ap = &ia->ap;
struct cuse_conn *cc = fc_to_cc(fc), *pos;
struct cuse_init_out *arg = &ia->out;
- struct page *page = ap->pages[0];
+ struct folio *folio = ap->folios[0];
struct cuse_devinfo devinfo = { };
struct device *dev;
struct cdev *cdev;
@@ -343,7 +343,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
/* parse init reply */
cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL;
- rc = cuse_parse_devinfo(page_address(page), ap->args.out_args[1].size,
+ rc = cuse_parse_devinfo(folio_address(folio), ap->args.out_args[1].size,
&devinfo);
if (rc)
goto err;
@@ -411,7 +411,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
kobject_uevent(&dev->kobj, KOBJ_ADD);
out:
kfree(ia);
- __free_page(page);
+ folio_put(folio);
return;
err_cdev:
@@ -429,7 +429,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
static int cuse_send_init(struct cuse_conn *cc)
{
int rc;
- struct page *page;
+ struct folio *folio;
struct fuse_mount *fm = &cc->fm;
struct cuse_init_args *ia;
struct fuse_args_pages *ap;
@@ -437,13 +437,14 @@ static int cuse_send_init(struct cuse_conn *cc)
BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
rc = -ENOMEM;
- page = alloc_page(GFP_KERNEL | __GFP_ZERO);
- if (!page)
+
+ folio = folio_alloc(GFP_KERNEL | __GFP_ZERO, 0);
+ if (!folio)
goto err;
ia = kzalloc(sizeof(*ia), GFP_KERNEL);
if (!ia)
- goto err_free_page;
+ goto err_free_folio;
ap = &ia->ap;
ia->in.major = FUSE_KERNEL_VERSION;
@@ -459,18 +460,19 @@ 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->num_pages = 1;
- ap->pages = &ia->page;
- ap->descs = &ia->desc;
- ia->page = page;
+ ap->uses_folios = true;
+ ap->num_folios = 1;
+ ap->folios = &ia->folio;
+ ap->folio_descs = &ia->desc;
+ ia->folio = folio;
ia->desc.length = ap->args.out_args[1].size;
ap->args.end = cuse_process_init_reply;
rc = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
if (rc) {
kfree(ia);
-err_free_page:
- __free_page(page);
+err_free_folio:
+ folio_put(folio);
}
err:
return rc;
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 04/13] fuse: convert readlink to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (2 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 03/13] fuse: convert cuse to use folios Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 05/13] fuse: convert readdir " Joanne Koong
` (8 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert readlink requests to use a folio instead of a page.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/dir.c | 29 +++++++++++++++--------------
1 file changed, 15 insertions(+), 14 deletions(-)
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 54104dd48af7..a08c532068d0 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1585,14 +1585,15 @@ static int fuse_permission(struct mnt_idmap *idmap,
return err;
}
-static int fuse_readlink_page(struct inode *inode, struct page *page)
+static int fuse_readlink_page(struct inode *inode, struct folio *folio)
{
struct fuse_mount *fm = get_fuse_mount(inode);
- struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
+ struct fuse_folio_desc desc = { .length = PAGE_SIZE - 1 };
struct fuse_args_pages ap = {
- .num_pages = 1,
- .pages = &page,
- .descs = &desc,
+ .uses_folios = true,
+ .num_folios = 1,
+ .folios = &folio,
+ .folio_descs = &desc,
};
char *link;
ssize_t res;
@@ -1614,7 +1615,7 @@ static int fuse_readlink_page(struct inode *inode, struct page *page)
if (WARN_ON(res >= PAGE_SIZE))
return -EIO;
- link = page_address(page);
+ link = folio_address(folio);
link[res] = '\0';
return 0;
@@ -1624,7 +1625,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
struct delayed_call *callback)
{
struct fuse_conn *fc = get_fuse_conn(inode);
- struct page *page;
+ struct folio *folio;
int err;
err = -EIO;
@@ -1638,20 +1639,20 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
if (!dentry)
goto out_err;
- page = alloc_page(GFP_KERNEL);
+ folio = folio_alloc(GFP_KERNEL, 0);
err = -ENOMEM;
- if (!page)
+ if (!folio)
goto out_err;
- err = fuse_readlink_page(inode, page);
+ err = fuse_readlink_page(inode, folio);
if (err) {
- __free_page(page);
+ folio_put(folio);
goto out_err;
}
- set_delayed_call(callback, page_put_link, page);
+ set_delayed_call(callback, page_put_link, &folio->page);
- return page_address(page);
+ return folio_address(folio);
out_err:
return ERR_PTR(err);
@@ -2231,7 +2232,7 @@ void fuse_init_dir(struct inode *inode)
static int fuse_symlink_read_folio(struct file *null, struct folio *folio)
{
- int err = fuse_readlink_page(folio->mapping->host, &folio->page);
+ int err = fuse_readlink_page(folio->mapping->host, folio);
if (!err)
folio_mark_uptodate(folio);
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 05/13] fuse: convert readdir to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (3 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 04/13] fuse: convert readlink " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 06/13] fuse: convert reads " Joanne Koong
` (7 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert readdir requests to use a folio instead of a page.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/readdir.c | 21 +++++++++++----------
1 file changed, 11 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/readdir.c b/fs/fuse/readdir.c
index 0377b6dc24c8..fd0eff1b9f2d 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -331,24 +331,25 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
{
int plus;
ssize_t res;
- struct page *page;
+ struct folio *folio;
struct inode *inode = file_inode(file);
struct fuse_mount *fm = get_fuse_mount(inode);
struct fuse_io_args ia = {};
struct fuse_args_pages *ap = &ia.ap;
- struct fuse_page_desc desc = { .length = PAGE_SIZE };
+ struct fuse_folio_desc desc = { .length = PAGE_SIZE };
u64 attr_version = 0;
bool locked;
- page = alloc_page(GFP_KERNEL);
- if (!page)
+ folio = folio_alloc(GFP_KERNEL, 0);
+ if (!folio)
return -ENOMEM;
plus = fuse_use_readdirplus(inode, ctx);
ap->args.out_pages = true;
- ap->num_pages = 1;
- ap->pages = &page;
- ap->descs = &desc;
+ ap->uses_folios = true;
+ ap->num_folios = 1;
+ ap->folios = &folio;
+ ap->folio_descs = &desc;
if (plus) {
attr_version = fuse_get_attr_version(fm->fc);
fuse_read_args_fill(&ia, file, ctx->pos, PAGE_SIZE,
@@ -367,15 +368,15 @@ static int fuse_readdir_uncached(struct file *file, struct dir_context *ctx)
if (ff->open_flags & FOPEN_CACHE_DIR)
fuse_readdir_cache_end(file, ctx->pos);
} else if (plus) {
- res = parse_dirplusfile(page_address(page), res,
+ res = parse_dirplusfile(folio_address(folio), res,
file, ctx, attr_version);
} else {
- res = parse_dirfile(page_address(page), res, file,
+ res = parse_dirfile(folio_address(folio), res, file,
ctx);
}
}
- __free_page(page);
+ folio_put(folio);
fuse_invalidate_atime(inode);
return res;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 06/13] fuse: convert reads to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (4 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 05/13] fuse: convert readdir " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 07/13] fuse: convert writes (non-writeback) " Joanne Koong
` (6 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert read requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/file.c | 67 ++++++++++++++++++++++++++++++++----------------
fs/fuse/fuse_i.h | 12 +++++++++
2 files changed, 57 insertions(+), 22 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ce67af163c9a..ece1c0319e35 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -760,12 +760,37 @@ static struct fuse_io_args *fuse_io_alloc(struct fuse_io_priv *io,
return ia;
}
+static struct fuse_io_args *fuse_io_folios_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);
+ if (!ia->ap.folios) {
+ kfree(ia);
+ ia = NULL;
+ }
+ }
+ return ia;
+}
+
static void fuse_io_free(struct fuse_io_args *ia)
{
kfree(ia->ap.pages);
kfree(ia);
}
+static void fuse_io_folios_free(struct fuse_io_args *ia)
+{
+ kfree(ia->ap.folios);
+ kfree(ia);
+}
+
static void fuse_aio_complete_req(struct fuse_mount *fm, struct fuse_args *args,
int err)
{
@@ -865,7 +890,7 @@ static void fuse_short_read(struct inode *inode, u64 attr_ver, size_t num_read,
* reached the client fs yet. So the hole is not present there.
*/
if (!fc->writeback_cache) {
- loff_t pos = page_offset(ap->pages[0]) + num_read;
+ loff_t pos = folio_pos(ap->folios[0]) + num_read;
fuse_read_update_size(inode, pos, attr_ver);
}
}
@@ -875,14 +900,14 @@ static int fuse_do_readfolio(struct file *file, struct folio *folio)
struct inode *inode = folio->mapping->host;
struct fuse_mount *fm = get_fuse_mount(inode);
loff_t pos = folio_pos(folio);
- struct fuse_page_desc desc = { .length = PAGE_SIZE };
- struct page *page = &folio->page;
+ struct fuse_folio_desc desc = { .length = PAGE_SIZE };
struct fuse_io_args ia = {
.ap.args.page_zeroing = true,
.ap.args.out_pages = true,
- .ap.num_pages = 1,
- .ap.pages = &page,
- .ap.descs = &desc,
+ .ap.uses_folios = true,
+ .ap.num_folios = 1,
+ .ap.folios = &folio,
+ .ap.folio_descs = &desc,
};
ssize_t res;
u64 attr_ver;
@@ -941,8 +966,8 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
size_t num_read = args->out_args[0].size;
struct address_space *mapping = NULL;
- for (i = 0; mapping == NULL && i < ap->num_pages; i++)
- mapping = ap->pages[i]->mapping;
+ for (i = 0; mapping == NULL && i < ap->num_folios; i++)
+ mapping = ap->folios[i]->mapping;
if (mapping) {
struct inode *inode = mapping->host;
@@ -956,15 +981,12 @@ static void fuse_readpages_end(struct fuse_mount *fm, struct fuse_args *args,
fuse_invalidate_atime(inode);
}
- for (i = 0; i < ap->num_pages; i++) {
- struct folio *folio = page_folio(ap->pages[i]);
-
- folio_end_read(folio, !err);
- }
+ for (i = 0; i < ap->num_folios; i++)
+ folio_end_read(ap->folios[i], !err);
if (ia->ff)
fuse_file_put(ia->ff, false);
- fuse_io_free(ia);
+ fuse_io_folios_free(ia);
}
static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
@@ -972,8 +994,9 @@ static void fuse_send_readpages(struct fuse_io_args *ia, struct file *file)
struct fuse_file *ff = file->private_data;
struct fuse_mount *fm = ff->fm;
struct fuse_args_pages *ap = &ia->ap;
- loff_t pos = page_offset(ap->pages[0]);
- size_t count = ap->num_pages << PAGE_SHIFT;
+ loff_t pos = folio_pos(ap->folios[0]);
+ /* Currently, all folios in FUSE are one page */
+ size_t count = ap->num_folios << PAGE_SHIFT;
ssize_t res;
int err;
@@ -984,7 +1007,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->descs[ap->num_pages - 1].length--;
+ ap->folio_descs[ap->num_folios - 1].length--;
}
WARN_ON((loff_t) (pos + count) < 0);
@@ -1045,16 +1068,16 @@ static void fuse_readahead(struct readahead_control *rac)
*/
break;
- ia = fuse_io_alloc(NULL, cur_pages);
+ ia = fuse_io_folios_alloc(NULL, cur_pages);
if (!ia)
return;
ap = &ia->ap;
- while (ap->num_pages < cur_pages) {
+ while (ap->num_folios < cur_pages) {
folio = readahead_folio(rac);
- ap->pages[ap->num_pages] = &folio->page;
- ap->descs[ap->num_pages].length = folio_size(folio);
- ap->num_pages++;
+ ap->folios[ap->num_folios] = folio;
+ ap->folio_descs[ap->num_folios].length = folio_size(folio);
+ ap->num_folios++;
}
fuse_send_readpages(ia, rac->file);
nr_pages -= cur_pages;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 24a3da8400d1..b6877064c071 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1029,6 +1029,18 @@ static inline struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,
return pages;
}
+static inline struct folio **fuse_folios_alloc(unsigned int nfolios, gfp_t flags,
+ struct fuse_folio_desc **desc)
+{
+ struct folio **folios;
+
+ folios = kzalloc(nfolios * (sizeof(struct folio *) +
+ sizeof(struct fuse_folio_desc)), flags);
+ *desc = (void *) (folios + nfolios);
+
+ return folios;
+}
+
static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,
unsigned int index,
unsigned int nr_pages)
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 07/13] fuse: convert writes (non-writeback) to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (5 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 06/13] fuse: convert reads " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 08/13] fuse: convert ioctls " Joanne Koong
` (5 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert non-writeback write requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/file.c | 33 ++++++++++++++++++---------------
fs/fuse/fuse_i.h | 2 +-
2 files changed, 19 insertions(+), 16 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ece1c0319e35..b3d5b7b5da52 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -1197,8 +1197,8 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
bool short_write;
int err;
- for (i = 0; i < ap->num_pages; i++)
- fuse_wait_on_page_writeback(inode, ap->pages[i]->index);
+ for (i = 0; i < ap->num_folios; i++)
+ fuse_wait_on_folio_writeback(inode, ap->folios[i]);
fuse_write_args_fill(ia, ff, pos, count);
ia->write.in.flags = fuse_write_flags(iocb);
@@ -1210,10 +1210,10 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
err = -EIO;
short_write = ia->write.out.size < count;
- offset = ap->descs[0].offset;
+ offset = ap->folio_descs[0].offset;
count = ia->write.out.size;
- for (i = 0; i < ap->num_pages; i++) {
- struct folio *folio = page_folio(ap->pages[i]);
+ for (i = 0; i < ap->num_folios; i++) {
+ struct folio *folio = ap->folios[i];
if (err) {
folio_clear_uptodate(folio);
@@ -1227,7 +1227,7 @@ static ssize_t fuse_send_write_pages(struct fuse_io_args *ia,
}
offset = 0;
}
- if (ia->write.page_locked && (i == ap->num_pages - 1))
+ if (ia->write.folio_locked && (i == ap->num_folios - 1))
folio_unlock(folio);
folio_put(folio);
}
@@ -1243,11 +1243,12 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
struct fuse_args_pages *ap = &ia->ap;
struct fuse_conn *fc = get_fuse_conn(mapping->host);
unsigned offset = pos & (PAGE_SIZE - 1);
+ unsigned int nr_pages = 0;
size_t count = 0;
int err;
ap->args.in_pages = true;
- ap->descs[0].offset = offset;
+ ap->folio_descs[0].offset = offset;
do {
size_t tmp;
@@ -1283,9 +1284,10 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
}
err = 0;
- ap->pages[ap->num_pages] = &folio->page;
- ap->descs[ap->num_pages].length = tmp;
- ap->num_pages++;
+ ap->folios[ap->num_folios] = folio;
+ ap->folio_descs[ap->num_folios].length = tmp;
+ ap->num_folios++;
+ nr_pages++;
count += tmp;
pos += tmp;
@@ -1300,13 +1302,13 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia,
if (folio_test_uptodate(folio)) {
folio_unlock(folio);
} else {
- ia->write.page_locked = true;
+ ia->write.folio_locked = true;
break;
}
if (!fc->big_writes)
break;
} while (iov_iter_count(ii) && count < fc->max_write &&
- ap->num_pages < max_pages && offset == 0);
+ nr_pages < max_pages && offset == 0);
return count > 0 ? count : err;
}
@@ -1340,8 +1342,9 @@ 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->pages = fuse_pages_alloc(nr_pages, GFP_KERNEL, &ap->descs);
- if (!ap->pages) {
+ ap->uses_folios = true;
+ ap->folios = fuse_folios_alloc(nr_pages, GFP_KERNEL, &ap->folio_descs);
+ if (!ap->folios) {
err = -ENOMEM;
break;
}
@@ -1363,7 +1366,7 @@ static ssize_t fuse_perform_write(struct kiocb *iocb, struct iov_iter *ii)
err = -EIO;
}
}
- kfree(ap->pages);
+ kfree(ap->folios);
} while (!err && iov_iter_count(ii));
fuse_write_update_attr(inode, pos, res);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index b6877064c071..201b08562b6b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1096,7 +1096,7 @@ struct fuse_io_args {
struct {
struct fuse_write_in in;
struct fuse_write_out out;
- bool page_locked;
+ bool folio_locked;
} write;
};
struct fuse_args_pages ap;
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 08/13] fuse: convert ioctls to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (6 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 07/13] fuse: convert writes (non-writeback) " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 09/13] fuse: convert retrieves " Joanne Koong
` (4 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert ioctl requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/fuse_i.h | 10 ++++++++++
fs/fuse/ioctl.c | 32 ++++++++++++++++----------------
2 files changed, 26 insertions(+), 16 deletions(-)
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index 201b08562b6b..c1c7def8ee4b 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1051,6 +1051,16 @@ static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,
descs[i].length = PAGE_SIZE - descs[i].offset;
}
+static inline void fuse_folio_descs_length_init(struct fuse_folio_desc *descs,
+ unsigned int index,
+ unsigned int nr_folios)
+{
+ int i;
+
+ for (i = index; i < index + nr_folios; i++)
+ descs[i].length = PAGE_SIZE - descs[i].offset;
+}
+
static inline void fuse_sync_bucket_dec(struct fuse_sync_bucket *bucket)
{
/* Need RCU protection to prevent use after free after the decrement */
diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c
index a6c8ee551635..1c77d8a27950 100644
--- a/fs/fuse/ioctl.c
+++ b/fs/fuse/ioctl.c
@@ -251,12 +251,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.pages = fuse_pages_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.descs);
+ ap.folios = fuse_folios_alloc(fm->fc->max_pages, GFP_KERNEL, &ap.folio_descs);
iov_page = (struct iovec *) __get_free_page(GFP_KERNEL);
- if (!ap.pages || !iov_page)
+ if (!ap.folios || !iov_page)
goto out;
- fuse_page_descs_length_init(ap.descs, 0, fm->fc->max_pages);
+ fuse_folio_descs_length_init(ap.folio_descs, 0, fm->fc->max_pages);
/*
* If restricted, initialize IO parameters as encoded in @cmd.
@@ -306,14 +306,14 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
err = -ENOMEM;
if (max_pages > fm->fc->max_pages)
goto out;
- while (ap.num_pages < max_pages) {
- ap.pages[ap.num_pages] = alloc_page(GFP_KERNEL | __GFP_HIGHMEM);
- if (!ap.pages[ap.num_pages])
+ 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])
goto out;
- ap.num_pages++;
+ ap.num_folios++;
}
-
/* okay, let's send it to the client */
ap.args.opcode = FUSE_IOCTL;
ap.args.nodeid = ff->nodeid;
@@ -327,8 +327,8 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
err = -EFAULT;
iov_iter_init(&ii, ITER_SOURCE, in_iov, in_iovs, in_size);
- for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {
- c = copy_page_from_iter(ap.pages[i], 0, PAGE_SIZE, &ii);
+ for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_folios); i++) {
+ c = copy_folio_from_iter(ap.folios[i], 0, PAGE_SIZE, &ii);
if (c != PAGE_SIZE && iov_iter_count(&ii))
goto out;
}
@@ -366,7 +366,7 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
in_iovs + out_iovs > FUSE_IOCTL_MAX_IOV)
goto out;
- vaddr = kmap_local_page(ap.pages[0]);
+ vaddr = kmap_local_folio(ap.folios[0], 0);
err = fuse_copy_ioctl_iovec(fm->fc, iov_page, vaddr,
transferred, in_iovs + out_iovs,
(flags & FUSE_IOCTL_COMPAT) != 0);
@@ -394,17 +394,17 @@ long fuse_do_ioctl(struct file *file, unsigned int cmd, unsigned long arg,
err = -EFAULT;
iov_iter_init(&ii, ITER_DEST, out_iov, out_iovs, transferred);
- for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_pages); i++) {
- c = copy_page_to_iter(ap.pages[i], 0, PAGE_SIZE, &ii);
+ for (i = 0; iov_iter_count(&ii) && !WARN_ON(i >= ap.num_folios); i++) {
+ c = copy_folio_to_iter(ap.folios[i], 0, PAGE_SIZE, &ii);
if (c != PAGE_SIZE && iov_iter_count(&ii))
goto out;
}
err = 0;
out:
free_page((unsigned long) iov_page);
- while (ap.num_pages)
- __free_page(ap.pages[--ap.num_pages]);
- kfree(ap.pages);
+ while (ap.num_folios)
+ folio_put(ap.folios[--ap.num_folios]);
+ kfree(ap.folios);
return err ? err : outarg.result;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 09/13] fuse: convert retrieves to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (7 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 08/13] fuse: convert ioctls " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-23 17:23 ` Joanne Koong
2024-10-23 20:53 ` kernel test robot
2024-10-22 18:54 ` [PATCH v2 10/13] fuse: convert writebacks " Joanne Koong
` (3 subsequent siblings)
12 siblings, 2 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert retrieve requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/dev.c | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 9f860bd655a4..220b1bddb74e 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1728,7 +1728,7 @@ static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
struct fuse_retrieve_args *ra =
container_of(args, typeof(*ra), ap.args);
- release_pages(ra->ap.pages, ra->ap.num_pages);
+ release_pages(ra->ap.folios, ra->ap.num_folios);
kfree(ra);
}
@@ -1742,7 +1742,8 @@ 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;
+ unsigned int num_folios;
+ unsigned int num_pages, cur_pages = 0;
struct fuse_conn *fc = fm->fc;
struct fuse_retrieve_args *ra;
size_t args_size = sizeof(*ra);
@@ -1761,15 +1762,16 @@ 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->pages[0]) + sizeof(ap->descs[0]));
+ args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->folio_descs[0]));
ra = kzalloc(args_size, GFP_KERNEL);
if (!ra)
return -ENOMEM;
ap = &ra->ap;
- ap->pages = (void *) (ra + 1);
- ap->descs = (void *) (ap->pages + num_pages);
+ ap->folios = (void *) (ra + 1);
+ ap->folio_descs = (void *) (ap->folios + num_folios);
+ ap->uses_folios = true;
args = &ap->args;
args->nodeid = outarg->nodeid;
@@ -1780,7 +1782,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
index = outarg->offset >> PAGE_SHIFT;
- while (num && ap->num_pages < num_pages) {
+ while (num && cur_pages < num_pages) {
struct folio *folio;
unsigned int this_num;
@@ -1789,10 +1791,11 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
break;
this_num = min_t(unsigned, num, PAGE_SIZE - offset);
- ap->pages[ap->num_pages] = &folio->page;
- ap->descs[ap->num_pages].offset = offset;
- ap->descs[ap->num_pages].length = this_num;
- ap->num_pages++;
+ ap->folios[ap->num_folios] = folio;
+ ap->folio_descs[ap->num_folios].offset = offset;
+ ap->folio_descs[ap->num_folios].length = this_num;
+ ap->num_folios++;
+ cur_pages++;
offset = 0;
num -= this_num;
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 10/13] fuse: convert writebacks to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (8 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 09/13] fuse: convert retrieves " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 11/13] mm/writeback: add folio_mark_dirty_lock() Joanne Koong
` (2 subsequent siblings)
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert writeback requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/file.c | 126 +++++++++++++++++++++++++------------------------
1 file changed, 64 insertions(+), 62 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index b3d5b7b5da52..99af3c39e529 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -436,7 +436,7 @@ static struct fuse_writepage_args *fuse_find_writeback(struct fuse_inode *fi,
wpa = rb_entry(n, struct fuse_writepage_args, writepages_entry);
WARN_ON(get_fuse_inode(wpa->inode) != fi);
curr_index = wpa->ia.write.in.offset >> PAGE_SHIFT;
- if (idx_from >= curr_index + wpa->ia.ap.num_pages)
+ if (idx_from >= curr_index + wpa->ia.ap.num_folios)
n = n->rb_right;
else if (idx_to < curr_index)
n = n->rb_left;
@@ -1837,12 +1837,12 @@ static void fuse_writepage_free(struct fuse_writepage_args *wpa)
if (wpa->bucket)
fuse_sync_bucket_dec(wpa->bucket);
- for (i = 0; i < ap->num_pages; i++)
- __free_page(ap->pages[i]);
+ for (i = 0; i < ap->num_folios; i++)
+ folio_put(ap->folios[i]);
fuse_file_put(wpa->ia.ff, false);
- kfree(ap->pages);
+ kfree(ap->folios);
kfree(wpa);
}
@@ -1862,8 +1862,8 @@ static void fuse_writepage_finish(struct fuse_writepage_args *wpa)
struct fuse_inode *fi = get_fuse_inode(inode);
int i;
- for (i = 0; i < ap->num_pages; i++)
- fuse_writepage_finish_stat(inode, page_folio(ap->pages[i]));
+ for (i = 0; i < ap->num_folios; i++)
+ fuse_writepage_finish_stat(inode, ap->folios[i]);
wake_up(&fi->page_waitq);
}
@@ -1878,7 +1878,8 @@ __acquires(fi->lock)
struct fuse_inode *fi = get_fuse_inode(wpa->inode);
struct fuse_write_in *inarg = &wpa->ia.write.in;
struct fuse_args *args = &wpa->ia.ap.args;
- __u64 data_size = wpa->ia.ap.num_pages * PAGE_SIZE;
+ /* Currently, all folios in FUSE are one page */
+ __u64 data_size = wpa->ia.ap.num_folios * PAGE_SIZE;
int err;
fi->writectr++;
@@ -1919,7 +1920,7 @@ __acquires(fi->lock)
next = aux->next;
aux->next = NULL;
fuse_writepage_finish_stat(aux->inode,
- page_folio(aux->ia.ap.pages[0]));
+ aux->ia.ap.folios[0]);
fuse_writepage_free(aux);
}
@@ -1954,11 +1955,11 @@ static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root,
struct fuse_writepage_args *wpa)
{
pgoff_t idx_from = wpa->ia.write.in.offset >> PAGE_SHIFT;
- pgoff_t idx_to = idx_from + wpa->ia.ap.num_pages - 1;
+ pgoff_t idx_to = idx_from + wpa->ia.ap.num_folios - 1;
struct rb_node **p = &root->rb_node;
struct rb_node *parent = NULL;
- WARN_ON(!wpa->ia.ap.num_pages);
+ WARN_ON(!wpa->ia.ap.num_folios);
while (*p) {
struct fuse_writepage_args *curr;
pgoff_t curr_index;
@@ -1969,7 +1970,7 @@ static struct fuse_writepage_args *fuse_insert_writeback(struct rb_root *root,
WARN_ON(curr->inode != wpa->inode);
curr_index = curr->ia.write.in.offset >> PAGE_SHIFT;
- if (idx_from >= curr_index + curr->ia.ap.num_pages)
+ if (idx_from >= curr_index + curr->ia.ap.num_folios)
p = &(*p)->rb_right;
else if (idx_to < curr_index)
p = &(*p)->rb_left;
@@ -2101,9 +2102,10 @@ static struct fuse_writepage_args *fuse_writepage_args_alloc(void)
wpa = kzalloc(sizeof(*wpa), GFP_NOFS);
if (wpa) {
ap = &wpa->ia.ap;
- ap->num_pages = 0;
- ap->pages = fuse_pages_alloc(1, GFP_NOFS, &ap->descs);
- if (!ap->pages) {
+ ap->num_folios = 0;
+ ap->uses_folios = true;
+ ap->folios = fuse_folios_alloc(1, GFP_NOFS, &ap->folio_descs);
+ if (!ap->folios) {
kfree(wpa);
wpa = NULL;
}
@@ -2127,16 +2129,16 @@ static void fuse_writepage_add_to_bucket(struct fuse_conn *fc,
}
static void fuse_writepage_args_page_fill(struct fuse_writepage_args *wpa, struct folio *folio,
- struct folio *tmp_folio, uint32_t page_index)
+ struct folio *tmp_folio, uint32_t folio_index)
{
struct inode *inode = folio->mapping->host;
struct fuse_args_pages *ap = &wpa->ia.ap;
folio_copy(tmp_folio, folio);
- ap->pages[page_index] = &tmp_folio->page;
- ap->descs[page_index].offset = 0;
- ap->descs[page_index].length = PAGE_SIZE;
+ ap->folios[folio_index] = tmp_folio;
+ ap->folio_descs[folio_index].offset = 0;
+ ap->folio_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);
@@ -2193,7 +2195,7 @@ static int fuse_writepage_locked(struct folio *folio)
goto err_writepage_args;
ap = &wpa->ia.ap;
- ap->num_pages = 1;
+ ap->num_folios = 1;
folio_start_writeback(folio);
fuse_writepage_args_page_fill(wpa, folio, tmp_folio, 0);
@@ -2221,32 +2223,32 @@ struct fuse_fill_wb_data {
struct fuse_writepage_args *wpa;
struct fuse_file *ff;
struct inode *inode;
- struct page **orig_pages;
- unsigned int max_pages;
+ struct folio **orig_folios;
+ unsigned int max_folios;
};
static bool fuse_pages_realloc(struct fuse_fill_wb_data *data)
{
struct fuse_args_pages *ap = &data->wpa->ia.ap;
struct fuse_conn *fc = get_fuse_conn(data->inode);
- struct page **pages;
- struct fuse_page_desc *descs;
- unsigned int npages = min_t(unsigned int,
- max_t(unsigned int, data->max_pages * 2,
- FUSE_DEFAULT_MAX_PAGES_PER_REQ),
+ struct folio **folios;
+ struct fuse_folio_desc *descs;
+ unsigned int nfolios = min_t(unsigned int,
+ max_t(unsigned int, data->max_folios * 2,
+ FUSE_DEFAULT_MAX_PAGES_PER_REQ),
fc->max_pages);
- WARN_ON(npages <= data->max_pages);
+ WARN_ON(nfolios <= data->max_folios);
- pages = fuse_pages_alloc(npages, GFP_NOFS, &descs);
- if (!pages)
+ folios = fuse_folios_alloc(nfolios, GFP_NOFS, &descs);
+ if (!folios)
return false;
- memcpy(pages, ap->pages, sizeof(struct page *) * ap->num_pages);
- memcpy(descs, ap->descs, sizeof(struct fuse_page_desc) * ap->num_pages);
- kfree(ap->pages);
- ap->pages = pages;
- ap->descs = descs;
- data->max_pages = npages;
+ memcpy(folios, ap->folios, sizeof(struct folio *) * ap->num_folios);
+ memcpy(descs, ap->folio_descs, sizeof(struct fuse_folio_desc) * ap->num_folios);
+ kfree(ap->folios);
+ ap->folios = folios;
+ ap->folio_descs = descs;
+ data->max_folios = nfolios;
return true;
}
@@ -2256,7 +2258,7 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data)
struct fuse_writepage_args *wpa = data->wpa;
struct inode *inode = data->inode;
struct fuse_inode *fi = get_fuse_inode(inode);
- int num_pages = wpa->ia.ap.num_pages;
+ int num_folios = wpa->ia.ap.num_folios;
int i;
spin_lock(&fi->lock);
@@ -2264,8 +2266,8 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data)
fuse_flush_writepages(inode);
spin_unlock(&fi->lock);
- for (i = 0; i < num_pages; i++)
- end_page_writeback(data->orig_pages[i]);
+ for (i = 0; i < num_folios; i++)
+ folio_end_writeback(data->orig_folios[i]);
}
/*
@@ -2276,15 +2278,15 @@ static void fuse_writepages_send(struct fuse_fill_wb_data *data)
* swapping the new temp page with the old one.
*/
static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
- struct page *page)
+ struct folio *folio)
{
struct fuse_inode *fi = get_fuse_inode(new_wpa->inode);
struct fuse_writepage_args *tmp;
struct fuse_writepage_args *old_wpa;
struct fuse_args_pages *new_ap = &new_wpa->ia.ap;
- WARN_ON(new_ap->num_pages != 0);
- new_ap->num_pages = 1;
+ WARN_ON(new_ap->num_folios != 0);
+ new_ap->num_folios = 1;
spin_lock(&fi->lock);
old_wpa = fuse_insert_writeback(&fi->writepages, new_wpa);
@@ -2298,9 +2300,9 @@ static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
WARN_ON(tmp->inode != new_wpa->inode);
curr_index = tmp->ia.write.in.offset >> PAGE_SHIFT;
- if (curr_index == page->index) {
- WARN_ON(tmp->ia.ap.num_pages != 1);
- swap(tmp->ia.ap.pages[0], new_ap->pages[0]);
+ if (curr_index == folio->index) {
+ WARN_ON(tmp->ia.ap.num_folios != 1);
+ swap(tmp->ia.ap.folios[0], new_ap->folios[0]);
break;
}
}
@@ -2314,7 +2316,7 @@ static bool fuse_writepage_add(struct fuse_writepage_args *new_wpa,
if (tmp) {
fuse_writepage_finish_stat(new_wpa->inode,
- page_folio(new_ap->pages[0]));
+ folio);
fuse_writepage_free(new_wpa);
}
@@ -2325,7 +2327,7 @@ static bool fuse_writepage_need_send(struct fuse_conn *fc, struct folio *folio,
struct fuse_args_pages *ap,
struct fuse_fill_wb_data *data)
{
- WARN_ON(!ap->num_pages);
+ WARN_ON(!ap->num_folios);
/*
* Being under writeback is unlikely but possible. For example direct
@@ -2337,19 +2339,19 @@ static bool fuse_writepage_need_send(struct fuse_conn *fc, struct folio *folio,
return true;
/* Reached max pages */
- if (ap->num_pages == fc->max_pages)
+ if (ap->num_folios == fc->max_pages)
return true;
/* Reached max write bytes */
- if ((ap->num_pages + 1) * PAGE_SIZE > fc->max_write)
+ if ((ap->num_folios + 1) * PAGE_SIZE > fc->max_write)
return true;
/* Discontinuity */
- if (data->orig_pages[ap->num_pages - 1]->index + 1 != folio_index(folio))
+ if (data->orig_folios[ap->num_folios - 1]->index + 1 != folio_index(folio))
return true;
/* Need to grow the pages array? If so, did the expansion fail? */
- if (ap->num_pages == data->max_pages && !fuse_pages_realloc(data))
+ if (ap->num_folios == data->max_folios && !fuse_pages_realloc(data))
return true;
return false;
@@ -2393,7 +2395,7 @@ static int fuse_writepages_fill(struct folio *folio,
* This is ensured by holding the page lock in page_mkwrite() while
* checking fuse_page_is_writeback(). We already hold the page lock
* since clear_page_dirty_for_io() and keep it held until we add the
- * request to the fi->writepages list and increment ap->num_pages.
+ * request to the fi->writepages list and increment ap->num_folios.
* After this fuse_page_is_writeback() will indicate that the page is
* under writeback, so we can release the page lock.
*/
@@ -2405,13 +2407,13 @@ static int fuse_writepages_fill(struct folio *folio,
goto out_unlock;
}
fuse_file_get(wpa->ia.ff);
- data->max_pages = 1;
+ data->max_folios = 1;
ap = &wpa->ia.ap;
}
folio_start_writeback(folio);
- fuse_writepage_args_page_fill(wpa, folio, tmp_folio, ap->num_pages);
- data->orig_pages[ap->num_pages] = &folio->page;
+ fuse_writepage_args_page_fill(wpa, folio, tmp_folio, ap->num_folios);
+ data->orig_folios[ap->num_folios] = folio;
err = 0;
if (data->wpa) {
@@ -2420,9 +2422,9 @@ static int fuse_writepages_fill(struct folio *folio,
* fuse_page_is_writeback().
*/
spin_lock(&fi->lock);
- ap->num_pages++;
+ ap->num_folios++;
spin_unlock(&fi->lock);
- } else if (fuse_writepage_add(wpa, &folio->page)) {
+ } else if (fuse_writepage_add(wpa, folio)) {
data->wpa = wpa;
} else {
folio_end_writeback(folio);
@@ -2454,21 +2456,21 @@ static int fuse_writepages(struct address_space *mapping,
data.ff = NULL;
err = -ENOMEM;
- data.orig_pages = kcalloc(fc->max_pages,
- sizeof(struct page *),
- GFP_NOFS);
- if (!data.orig_pages)
+ data.orig_folios = kcalloc(fc->max_pages,
+ sizeof(struct folio *),
+ GFP_NOFS);
+ if (!data.orig_folios)
goto out;
err = write_cache_pages(mapping, wbc, fuse_writepages_fill, &data);
if (data.wpa) {
- WARN_ON(!data.wpa->ia.ap.num_pages);
+ WARN_ON(!data.wpa->ia.ap.num_folios);
fuse_writepages_send(&data);
}
if (data.ff)
fuse_file_put(data.ff, false);
- kfree(data.orig_pages);
+ kfree(data.orig_folios);
out:
return err;
}
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 11/13] mm/writeback: add folio_mark_dirty_lock()
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (9 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 10/13] fuse: convert writebacks " Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 12/13] fuse: convert direct io to use folios Joanne Koong
2024-10-22 18:54 ` [PATCH v2 13/13] fuse: remove pages for requests and exclusively " Joanne Koong
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Add a new convenience helper folio_mark_dirty_lock() that grabs the
folio lock before calling folio_mark_dirty().
Refactor set_page_dirty_lock() to directly use folio_mark_dirty_lock().
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
---
include/linux/mm.h | 1 +
mm/folio-compat.c | 6 ++++++
mm/page-writeback.c | 22 +++++++++++-----------
3 files changed, 18 insertions(+), 11 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ecf63d2b0582..446d7096c48f 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2539,6 +2539,7 @@ struct kvec;
struct page *get_dump_page(unsigned long addr);
bool folio_mark_dirty(struct folio *folio);
+bool folio_mark_dirty_lock(struct folio *folio);
bool set_page_dirty(struct page *page);
int set_page_dirty_lock(struct page *page);
diff --git a/mm/folio-compat.c b/mm/folio-compat.c
index 80746182e9e8..1d1832e2a599 100644
--- a/mm/folio-compat.c
+++ b/mm/folio-compat.c
@@ -52,6 +52,12 @@ bool set_page_dirty(struct page *page)
}
EXPORT_SYMBOL(set_page_dirty);
+int set_page_dirty_lock(struct page *page)
+{
+ return folio_mark_dirty_lock(page_folio(page));
+}
+EXPORT_SYMBOL(set_page_dirty_lock);
+
bool clear_page_dirty_for_io(struct page *page)
{
return folio_clear_dirty_for_io(page_folio(page));
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index fcd4c1439cb9..db00a66d8b84 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2914,25 +2914,25 @@ bool folio_mark_dirty(struct folio *folio)
EXPORT_SYMBOL(folio_mark_dirty);
/*
- * set_page_dirty() is racy if the caller has no reference against
- * page->mapping->host, and if the page is unlocked. This is because another
- * CPU could truncate the page off the mapping and then free the mapping.
+ * folio_mark_dirty() is racy if the caller has no reference against
+ * folio->mapping->host, and if the folio is unlocked. This is because another
+ * CPU could truncate the folio off the mapping and then free the mapping.
*
- * Usually, the page _is_ locked, or the caller is a user-space process which
+ * Usually, the folio _is_ locked, or the caller is a user-space process which
* holds a reference on the inode by having an open file.
*
- * In other cases, the page should be locked before running set_page_dirty().
+ * In other cases, the folio should be locked before running folio_mark_dirty().
*/
-int set_page_dirty_lock(struct page *page)
+bool folio_mark_dirty_lock(struct folio *folio)
{
- int ret;
+ bool ret;
- lock_page(page);
- ret = set_page_dirty(page);
- unlock_page(page);
+ folio_lock(folio);
+ ret = folio_mark_dirty(folio);
+ folio_unlock(folio);
return ret;
}
-EXPORT_SYMBOL(set_page_dirty_lock);
+EXPORT_SYMBOL(folio_mark_dirty_lock);
/*
* This cancels just the dirty bit on the kernel page itself, it does NOT
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 12/13] fuse: convert direct io to use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (10 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 11/13] mm/writeback: add folio_mark_dirty_lock() Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
2024-10-22 18:54 ` [PATCH v2 13/13] fuse: remove pages for requests and exclusively " Joanne Koong
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
Convert direct io requests to use folios instead of pages.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/file.c | 80 +++++++++++++++++++++---------------------------
fs/fuse/fuse_i.h | 22 -------------
2 files changed, 35 insertions(+), 67 deletions(-)
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 99af3c39e529..14af8c41fc83 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -665,11 +665,11 @@ static void fuse_release_user_pages(struct fuse_args_pages *ap, ssize_t nres,
{
unsigned int i;
- for (i = 0; i < ap->num_pages; i++) {
+ for (i = 0; i < ap->num_folios; i++) {
if (should_dirty)
- set_page_dirty_lock(ap->pages[i]);
+ folio_mark_dirty_lock(ap->folios[i]);
if (ap->args.is_pinned)
- unpin_user_page(ap->pages[i]);
+ unpin_folio(ap->folios[i]);
}
if (nres > 0 && ap->args.invalidate_vmap)
@@ -742,24 +742,6 @@ 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_alloc(struct fuse_io_priv *io,
- unsigned int npages)
-{
- struct fuse_io_args *ia;
-
- ia = kzalloc(sizeof(*ia), GFP_KERNEL);
- if (ia) {
- ia->io = io;
- ia->ap.pages = fuse_pages_alloc(npages, GFP_KERNEL,
- &ia->ap.descs);
- if (!ia->ap.pages) {
- kfree(ia);
- ia = NULL;
- }
- }
- return ia;
-}
-
static struct fuse_io_args *fuse_io_folios_alloc(struct fuse_io_priv *io,
unsigned int nfolios)
{
@@ -779,12 +761,6 @@ static struct fuse_io_args *fuse_io_folios_alloc(struct fuse_io_priv *io,
return ia;
}
-static void fuse_io_free(struct fuse_io_args *ia)
-{
- kfree(ia->ap.pages);
- kfree(ia);
-}
-
static void fuse_io_folios_free(struct fuse_io_args *ia)
{
kfree(ia->ap.folios);
@@ -821,7 +797,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_free(ia);
+ fuse_io_folios_free(ia);
}
static ssize_t fuse_async_req_send(struct fuse_mount *fm,
@@ -1531,6 +1507,7 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
bool use_pages_for_kvec_io)
{
bool flush_or_invalidate = false;
+ unsigned int nr_pages = 0;
size_t nbytes = 0; /* # bytes already packed in req */
ssize_t ret = 0;
@@ -1560,15 +1537,23 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
}
}
- while (nbytes < *nbytesp && ap->num_pages < max_pages) {
- unsigned npages;
+ /*
+ * Until there is support for iov_iter_extract_folios(), we have to
+ * manually extract pages using iov_iter_extract_pages() and then
+ * copy that to a folios array.
+ */
+ struct page **pages = kzalloc(max_pages * sizeof(struct page *),
+ GFP_KERNEL);
+ if (!pages)
+ return -ENOMEM;
+
+ while (nbytes < *nbytesp && nr_pages < max_pages) {
+ unsigned nfolios, i;
size_t start;
- struct page **pt_pages;
- pt_pages = &ap->pages[ap->num_pages];
- ret = iov_iter_extract_pages(ii, &pt_pages,
+ ret = iov_iter_extract_pages(ii, &pages,
*nbytesp - nbytes,
- max_pages - ap->num_pages,
+ max_pages - nr_pages,
0, &start);
if (ret < 0)
break;
@@ -1576,15 +1561,20 @@ static int fuse_get_user_pages(struct fuse_args_pages *ap, struct iov_iter *ii,
nbytes += ret;
ret += start;
- npages = DIV_ROUND_UP(ret, PAGE_SIZE);
+ /* Currently, all folios in FUSE are one page */
+ nfolios = DIV_ROUND_UP(ret, PAGE_SIZE);
- ap->descs[ap->num_pages].offset = start;
- fuse_page_descs_length_init(ap->descs, ap->num_pages, npages);
+ ap->folio_descs[ap->num_folios].offset = start;
+ fuse_folio_descs_length_init(ap->folio_descs, ap->num_folios, nfolios);
+ for (i = 0; i < nfolios; i++)
+ ap->folios[i + ap->num_folios] = page_folio(pages[i]);
- ap->num_pages += npages;
- ap->descs[ap->num_pages - 1].length -=
+ ap->num_folios += nfolios;
+ ap->folio_descs[ap->num_folios - 1].length -=
(PAGE_SIZE - ret) & (PAGE_SIZE - 1);
+ nr_pages += nfolios;
}
+ kfree(pages);
if (write && flush_or_invalidate)
flush_kernel_vmap_range(ap->args.vmap_base, nbytes);
@@ -1624,14 +1614,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_alloc(io, max_pages);
+ ia = fuse_io_folios_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_free(ia);
+ fuse_io_folios_free(ia);
return res;
}
}
@@ -1646,7 +1636,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_free(ia);
+ fuse_io_folios_free(ia);
return res;
}
}
@@ -1673,7 +1663,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_free(ia);
+ fuse_io_folios_free(ia);
}
ia = NULL;
if (nres < 0) {
@@ -1692,13 +1682,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_alloc(io, max_pages);
+ ia = fuse_io_folios_alloc(io, max_pages);
if (!ia)
break;
}
}
if (ia)
- fuse_io_free(ia);
+ fuse_io_folios_free(ia);
if (res > 0)
*ppos = pos;
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index c1c7def8ee4b..d26d278da886 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -1017,18 +1017,6 @@ static inline bool fuse_is_bad(struct inode *inode)
return unlikely(test_bit(FUSE_I_BAD, &get_fuse_inode(inode)->state));
}
-static inline struct page **fuse_pages_alloc(unsigned int npages, gfp_t flags,
- struct fuse_page_desc **desc)
-{
- struct page **pages;
-
- pages = kzalloc(npages * (sizeof(struct page *) +
- sizeof(struct fuse_page_desc)), flags);
- *desc = (void *) (pages + npages);
-
- return pages;
-}
-
static inline struct folio **fuse_folios_alloc(unsigned int nfolios, gfp_t flags,
struct fuse_folio_desc **desc)
{
@@ -1041,16 +1029,6 @@ static inline struct folio **fuse_folios_alloc(unsigned int nfolios, gfp_t flags
return folios;
}
-static inline void fuse_page_descs_length_init(struct fuse_page_desc *descs,
- unsigned int index,
- unsigned int nr_pages)
-{
- int i;
-
- for (i = index; i < index + nr_pages; i++)
- descs[i].length = PAGE_SIZE - descs[i].offset;
-}
-
static inline void fuse_folio_descs_length_init(struct fuse_folio_desc *descs,
unsigned int index,
unsigned int nr_folios)
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v2 13/13] fuse: remove pages for requests and exclusively use folios
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
` (11 preceding siblings ...)
2024-10-22 18:54 ` [PATCH v2 12/13] fuse: convert direct io to use folios Joanne Koong
@ 2024-10-22 18:54 ` Joanne Koong
12 siblings, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-22 18:54 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
All fuse requests use folios instead of pages for transferring data.
Remove pages from the requests and exclusively use folios.
No functional changes.
Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
Reviewed-by: Josef Bacik <josef@toxicpanda.com>
---
fs/fuse/cuse.c | 1 -
fs/fuse/dev.c | 49 ++++++++---------------
fs/fuse/dir.c | 1 -
fs/fuse/file.c | 4 --
fs/fuse/fuse_i.h | 16 ++------
fs/fuse/ioctl.c | 1 -
fs/fuse/readdir.c | 1 -
fs/fuse/virtio_fs.c | 95 +++++++++++++++++----------------------------
8 files changed, 56 insertions(+), 112 deletions(-)
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index eed78e303139..ef9fb30b9bdc 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -460,7 +460,6 @@ 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;
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 220b1bddb74e..faf083f27739 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1028,41 +1028,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->folio_descs[i].offset;
+ unsigned int count = min(nbytes, ap->folio_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;
}
@@ -1771,7 +1757,6 @@ 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_folios);
- ap->uses_folios = true;
args = &ap->args;
args->nodeid = outarg->nodeid;
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index a08c532068d0..2661f0cab349 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1590,7 +1590,6 @@ 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,
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index 14af8c41fc83..070db159ba7b 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -750,7 +750,6 @@ 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);
if (!ia->ap.folios) {
@@ -880,7 +879,6 @@ 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,
@@ -1318,7 +1316,6 @@ 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);
if (!ap->folios) {
err = -ENOMEM;
@@ -2093,7 +2090,6 @@ 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);
if (!ap->folios) {
kfree(wpa);
diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h
index d26d278da886..55d371016c97 100644
--- a/fs/fuse/fuse_i.h
+++ b/fs/fuse/fuse_i.h
@@ -325,19 +325,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;
+ unsigned int num_folios;
+ struct fuse_folio_desc *folio_descs;
};
struct fuse_release_args {
diff --git a/fs/fuse/ioctl.c b/fs/fuse/ioctl.c
index 1c77d8a27950..28138c838d49 100644
--- a/fs/fuse/ioctl.c
+++ b/fs/fuse/ioctl.c
@@ -306,7 +306,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 fd0eff1b9f2d..aeb5ea534c96 100644
--- a/fs/fuse/readdir.c
+++ b/fs/fuse/readdir.c
@@ -346,7 +346,6 @@ 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;
diff --git a/fs/fuse/virtio_fs.c b/fs/fuse/virtio_fs.c
index 9f0d98cc20d3..b8d31a93f2d6 100644
--- a/fs/fuse/virtio_fs.c
+++ b/fs/fuse/virtio_fs.c
@@ -765,7 +765,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;
/*
@@ -778,29 +777,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->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;
}
}
}
@@ -1287,22 +1272,16 @@ static void virtio_fs_send_interrupt(struct fuse_iqueue *fiq, struct fuse_req *r
}
/* 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;
@@ -1320,7 +1299,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->folio_descs, ap->num_folios,
+ size);
}
if (!test_bit(FR_ISREPLY, &req->flags))
@@ -1333,35 +1313,29 @@ 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->folio_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;
@@ -1385,8 +1359,11 @@ 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->folio_descs,
+ ap->num_folios,
+ args[numargs - 1].size);
if (len_used)
*len_used = len;
--
2.43.5
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v2 09/13] fuse: convert retrieves to use folios
2024-10-22 18:54 ` [PATCH v2 09/13] fuse: convert retrieves " Joanne Koong
@ 2024-10-23 17:23 ` Joanne Koong
2024-10-23 20:53 ` kernel test robot
1 sibling, 0 replies; 16+ messages in thread
From: Joanne Koong @ 2024-10-23 17:23 UTC (permalink / raw)
To: miklos, linux-fsdevel; +Cc: josef, bernd.schubert, willy, kernel-team
On Tue, Oct 22, 2024 at 11:54 AM Joanne Koong <joannelkoong@gmail.com> wrote:
>
> Convert retrieve requests to use folios instead of pages.
>
> No functional changes.
>
> Signed-off-by: Joanne Koong <joannelkoong@gmail.com>
> Reviewed-by: Josef Bacik <josef@toxicpanda.com>
> ---
> fs/fuse/dev.c | 23 +++++++++++++----------
> 1 file changed, 13 insertions(+), 10 deletions(-)
>
> diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
> index 9f860bd655a4..220b1bddb74e 100644
> --- a/fs/fuse/dev.c
> +++ b/fs/fuse/dev.c
> @@ -1728,7 +1728,7 @@ static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
> struct fuse_retrieve_args *ra =
> container_of(args, typeof(*ra), ap.args);
>
> - release_pages(ra->ap.pages, ra->ap.num_pages);
> + release_pages(ra->ap.folios, ra->ap.num_folios);
> kfree(ra);
> }
>
> @@ -1742,7 +1742,8 @@ 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;
> + unsigned int num_folios;
> + unsigned int num_pages, cur_pages = 0;
> struct fuse_conn *fc = fm->fc;
> struct fuse_retrieve_args *ra;
> size_t args_size = sizeof(*ra);
> @@ -1761,15 +1762,16 @@ 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->pages[0]) + sizeof(ap->descs[0]));
> + args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->folio_descs[0]));
>
> ra = kzalloc(args_size, GFP_KERNEL);
> if (!ra)
> return -ENOMEM;
>
> ap = &ra->ap;
> - ap->pages = (void *) (ra + 1);
> - ap->descs = (void *) (ap->pages + num_pages);
> + ap->folios = (void *) (ra + 1);
> + ap->folio_descs = (void *) (ap->folios + num_folios);
Agh, I messed this up in the refactoring I did between v1 -> v2. This
should be ap->folios + num_pages. Will fix this in v3.
> + ap->uses_folios = true;
>
> args = &ap->args;
> args->nodeid = outarg->nodeid;
> @@ -1780,7 +1782,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
>
> index = outarg->offset >> PAGE_SHIFT;
>
> - while (num && ap->num_pages < num_pages) {
> + while (num && cur_pages < num_pages) {
> struct folio *folio;
> unsigned int this_num;
>
> @@ -1789,10 +1791,11 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
> break;
>
> this_num = min_t(unsigned, num, PAGE_SIZE - offset);
> - ap->pages[ap->num_pages] = &folio->page;
> - ap->descs[ap->num_pages].offset = offset;
> - ap->descs[ap->num_pages].length = this_num;
> - ap->num_pages++;
> + ap->folios[ap->num_folios] = folio;
> + ap->folio_descs[ap->num_folios].offset = offset;
> + ap->folio_descs[ap->num_folios].length = this_num;
> + ap->num_folios++;
> + cur_pages++;
>
> offset = 0;
> num -= this_num;
> --
> 2.43.5
>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH v2 09/13] fuse: convert retrieves to use folios
2024-10-22 18:54 ` [PATCH v2 09/13] fuse: convert retrieves " Joanne Koong
2024-10-23 17:23 ` Joanne Koong
@ 2024-10-23 20:53 ` kernel test robot
1 sibling, 0 replies; 16+ messages in thread
From: kernel test robot @ 2024-10-23 20:53 UTC (permalink / raw)
To: Joanne Koong, miklos, linux-fsdevel
Cc: llvm, oe-kbuild-all, josef, bernd.schubert, willy, kernel-team
Hi Joanne,
kernel test robot noticed the following build warnings:
[auto build test WARNING on mszeredi-fuse/for-next]
[also build test WARNING on next-20241023]
[cannot apply to akpm-mm/mm-everything linus/master v6.12-rc4]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Joanne-Koong/fuse-support-folios-in-struct-fuse_args_pages-and-fuse_copy_pages/20241023-025923
base: https://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse.git for-next
patch link: https://lore.kernel.org/r/20241022185443.1891563-10-joannelkoong%40gmail.com
patch subject: [PATCH v2 09/13] fuse: convert retrieves to use folios
config: x86_64-kexec (https://download.01.org/0day-ci/archive/20241024/202410240414.YVec3s6S-lkp@intel.com/config)
compiler: clang version 18.1.8 (https://github.com/llvm/llvm-project 3b5b5c1ec4a3095ab096dd780e84d7ab81f3d7ff)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20241024/202410240414.YVec3s6S-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202410240414.YVec3s6S-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> fs/fuse/dev.c:1773:43: warning: variable 'num_folios' is uninitialized when used here [-Wuninitialized]
1773 | ap->folio_descs = (void *) (ap->folios + num_folios);
| ^~~~~~~~~~
fs/fuse/dev.c:1745:25: note: initialize the variable 'num_folios' to silence this warning
1745 | unsigned int num_folios;
| ^
| = 0
1 warning generated.
vim +/num_folios +1773 fs/fuse/dev.c
1734
1735 static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
1736 struct fuse_notify_retrieve_out *outarg)
1737 {
1738 int err;
1739 struct address_space *mapping = inode->i_mapping;
1740 pgoff_t index;
1741 loff_t file_size;
1742 unsigned int num;
1743 unsigned int offset;
1744 size_t total_len = 0;
1745 unsigned int num_folios;
1746 unsigned int num_pages, cur_pages = 0;
1747 struct fuse_conn *fc = fm->fc;
1748 struct fuse_retrieve_args *ra;
1749 size_t args_size = sizeof(*ra);
1750 struct fuse_args_pages *ap;
1751 struct fuse_args *args;
1752
1753 offset = outarg->offset & ~PAGE_MASK;
1754 file_size = i_size_read(inode);
1755
1756 num = min(outarg->size, fc->max_write);
1757 if (outarg->offset > file_size)
1758 num = 0;
1759 else if (outarg->offset + num > file_size)
1760 num = file_size - outarg->offset;
1761
1762 num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
1763 num_pages = min(num_pages, fc->max_pages);
1764
1765 args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->folio_descs[0]));
1766
1767 ra = kzalloc(args_size, GFP_KERNEL);
1768 if (!ra)
1769 return -ENOMEM;
1770
1771 ap = &ra->ap;
1772 ap->folios = (void *) (ra + 1);
> 1773 ap->folio_descs = (void *) (ap->folios + num_folios);
1774 ap->uses_folios = true;
1775
1776 args = &ap->args;
1777 args->nodeid = outarg->nodeid;
1778 args->opcode = FUSE_NOTIFY_REPLY;
1779 args->in_numargs = 2;
1780 args->in_pages = true;
1781 args->end = fuse_retrieve_end;
1782
1783 index = outarg->offset >> PAGE_SHIFT;
1784
1785 while (num && cur_pages < num_pages) {
1786 struct folio *folio;
1787 unsigned int this_num;
1788
1789 folio = filemap_get_folio(mapping, index);
1790 if (IS_ERR(folio))
1791 break;
1792
1793 this_num = min_t(unsigned, num, PAGE_SIZE - offset);
1794 ap->folios[ap->num_folios] = folio;
1795 ap->folio_descs[ap->num_folios].offset = offset;
1796 ap->folio_descs[ap->num_folios].length = this_num;
1797 ap->num_folios++;
1798 cur_pages++;
1799
1800 offset = 0;
1801 num -= this_num;
1802 total_len += this_num;
1803 index++;
1804 }
1805 ra->inarg.offset = outarg->offset;
1806 ra->inarg.size = total_len;
1807 args->in_args[0].size = sizeof(ra->inarg);
1808 args->in_args[0].value = &ra->inarg;
1809 args->in_args[1].size = total_len;
1810
1811 err = fuse_simple_notify_reply(fm, args, outarg->notify_unique);
1812 if (err)
1813 fuse_retrieve_end(fm, args, err);
1814
1815 return err;
1816 }
1817
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-10-23 20:54 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-10-22 18:54 [PATCH v2 00/13] fuse: use folios instead of pages for requests Joanne Koong
2024-10-22 18:54 ` [PATCH v2 01/13] fuse: support folios in struct fuse_args_pages and fuse_copy_pages() Joanne Koong
2024-10-22 18:54 ` [PATCH v2 02/13] fuse: add support in virtio for requests using folios Joanne Koong
2024-10-22 18:54 ` [PATCH v2 03/13] fuse: convert cuse to use folios Joanne Koong
2024-10-22 18:54 ` [PATCH v2 04/13] fuse: convert readlink " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 05/13] fuse: convert readdir " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 06/13] fuse: convert reads " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 07/13] fuse: convert writes (non-writeback) " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 08/13] fuse: convert ioctls " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 09/13] fuse: convert retrieves " Joanne Koong
2024-10-23 17:23 ` Joanne Koong
2024-10-23 20:53 ` kernel test robot
2024-10-22 18:54 ` [PATCH v2 10/13] fuse: convert writebacks " Joanne Koong
2024-10-22 18:54 ` [PATCH v2 11/13] mm/writeback: add folio_mark_dirty_lock() Joanne Koong
2024-10-22 18:54 ` [PATCH v2 12/13] fuse: convert direct io to use folios Joanne Koong
2024-10-22 18:54 ` [PATCH v2 13/13] fuse: remove pages for requests and exclusively " Joanne Koong
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).