Skip to content

Commit fb527fc

Browse files
committed
Merge tag 'fuse-update-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse
Pull fuse updates from Miklos Szeredi: - Add page -> folio conversions (Joanne Koong, Josef Bacik) - Allow max size of fuse requests to be configurable with a sysctl (Joanne Koong) - Allow FOPEN_DIRECT_IO to take advantage of async code path (yangyun) - Fix large kernel reads (like a module load) in virtio_fs (Hou Tao) - Fix attribute inconsistency in case readdirplus (and plain lookup in corner cases) is racing with inode eviction (Zhang Tianci) - Fix a WARN_ON triggered by virtio_fs (Asahi Lina) * tag 'fuse-update-6.13' of git://git.kernel.org/pub/scm/linux/kernel/git/mszeredi/fuse: (30 commits) virtiofs: dax: remove ->writepages() callback fuse: check attributes staleness on fuse_iget() fuse: remove pages for requests and exclusively use folios fuse: convert direct io to use folios mm/writeback: add folio_mark_dirty_lock() fuse: convert writebacks to use folios fuse: convert retrieves to use folios fuse: convert ioctls to use folios fuse: convert writes (non-writeback) to use folios fuse: convert reads to use folios fuse: convert readdir to use folios fuse: convert readlink to use folios fuse: convert cuse to use folios fuse: add support in virtio for requests using folios fuse: support folios in struct fuse_args_pages and fuse_copy_pages() fuse: convert fuse_notify_store to use folios fuse: convert fuse_retrieve to use folios fuse: use the folio based vmstat helpers fuse: convert fuse_writepage_need_send to take a folio fuse: convert fuse_do_readpage to use folios ...
2 parents ff2a7a0 + d1dfb5f commit fb527fc

File tree

16 files changed

+578
-374
lines changed

16 files changed

+578
-374
lines changed

Documentation/admin-guide/sysctl/fs.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -337,3 +337,13 @@ Each "watch" costs roughly 90 bytes on a 32-bit kernel, and roughly 160 bytes
337337
on a 64-bit one.
338338
The current default value for ``max_user_watches`` is 4% of the
339339
available low memory, divided by the "watch" cost in bytes.
340+
341+
5. /proc/sys/fs/fuse - Configuration options for FUSE filesystems
342+
=====================================================================
343+
344+
This directory contains the following configuration options for FUSE
345+
filesystems:
346+
347+
``/proc/sys/fs/fuse/max_pages_limit`` is a read/write file for
348+
setting/getting the maximum number of pages that can be used for servicing
349+
requests in FUSE.

fs/fuse/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,5 +14,6 @@ fuse-y := dev.o dir.o file.o inode.o control.o xattr.o acl.o readdir.o ioctl.o
1414
fuse-y += iomode.o
1515
fuse-$(CONFIG_FUSE_DAX) += dax.o
1616
fuse-$(CONFIG_FUSE_PASSTHROUGH) += passthrough.o
17+
fuse-$(CONFIG_SYSCTL) += sysctl.o
1718

1819
virtiofs-y := virtio_fs.o

fs/fuse/cuse.c

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -303,8 +303,8 @@ struct cuse_init_args {
303303
struct fuse_args_pages ap;
304304
struct cuse_init_in in;
305305
struct cuse_init_out out;
306-
struct page *page;
307-
struct fuse_page_desc desc;
306+
struct folio *folio;
307+
struct fuse_folio_desc desc;
308308
};
309309

310310
/**
@@ -326,7 +326,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
326326
struct fuse_args_pages *ap = &ia->ap;
327327
struct cuse_conn *cc = fc_to_cc(fc), *pos;
328328
struct cuse_init_out *arg = &ia->out;
329-
struct page *page = ap->pages[0];
329+
struct folio *folio = ap->folios[0];
330330
struct cuse_devinfo devinfo = { };
331331
struct device *dev;
332332
struct cdev *cdev;
@@ -343,7 +343,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
343343
/* parse init reply */
344344
cc->unrestricted_ioctl = arg->flags & CUSE_UNRESTRICTED_IOCTL;
345345

346-
rc = cuse_parse_devinfo(page_address(page), ap->args.out_args[1].size,
346+
rc = cuse_parse_devinfo(folio_address(folio), ap->args.out_args[1].size,
347347
&devinfo);
348348
if (rc)
349349
goto err;
@@ -411,7 +411,7 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
411411
kobject_uevent(&dev->kobj, KOBJ_ADD);
412412
out:
413413
kfree(ia);
414-
__free_page(page);
414+
folio_put(folio);
415415
return;
416416

417417
err_cdev:
@@ -429,21 +429,22 @@ static void cuse_process_init_reply(struct fuse_mount *fm,
429429
static int cuse_send_init(struct cuse_conn *cc)
430430
{
431431
int rc;
432-
struct page *page;
432+
struct folio *folio;
433433
struct fuse_mount *fm = &cc->fm;
434434
struct cuse_init_args *ia;
435435
struct fuse_args_pages *ap;
436436

437437
BUILD_BUG_ON(CUSE_INIT_INFO_MAX > PAGE_SIZE);
438438

439439
rc = -ENOMEM;
440-
page = alloc_page(GFP_KERNEL | __GFP_ZERO);
441-
if (!page)
440+
441+
folio = folio_alloc(GFP_KERNEL | __GFP_ZERO, 0);
442+
if (!folio)
442443
goto err;
443444

444445
ia = kzalloc(sizeof(*ia), GFP_KERNEL);
445446
if (!ia)
446-
goto err_free_page;
447+
goto err_free_folio;
447448

448449
ap = &ia->ap;
449450
ia->in.major = FUSE_KERNEL_VERSION;
@@ -459,18 +460,18 @@ static int cuse_send_init(struct cuse_conn *cc)
459460
ap->args.out_args[1].size = CUSE_INIT_INFO_MAX;
460461
ap->args.out_argvar = true;
461462
ap->args.out_pages = true;
462-
ap->num_pages = 1;
463-
ap->pages = &ia->page;
463+
ap->num_folios = 1;
464+
ap->folios = &ia->folio;
464465
ap->descs = &ia->desc;
465-
ia->page = page;
466+
ia->folio = folio;
466467
ia->desc.length = ap->args.out_args[1].size;
467468
ap->args.end = cuse_process_init_reply;
468469

469470
rc = fuse_simple_background(fm, &ap->args, GFP_KERNEL);
470471
if (rc) {
471472
kfree(ia);
472-
err_free_page:
473-
__free_page(page);
473+
err_free_folio:
474+
folio_put(folio);
474475
}
475476
err:
476477
return rc;

fs/fuse/dax.c

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -774,16 +774,6 @@ ssize_t fuse_dax_write_iter(struct kiocb *iocb, struct iov_iter *from)
774774
return ret;
775775
}
776776

777-
static int fuse_dax_writepages(struct address_space *mapping,
778-
struct writeback_control *wbc)
779-
{
780-
781-
struct inode *inode = mapping->host;
782-
struct fuse_conn *fc = get_fuse_conn(inode);
783-
784-
return dax_writeback_mapping_range(mapping, fc->dax->dev, wbc);
785-
}
786-
787777
static vm_fault_t __fuse_dax_fault(struct vm_fault *vmf, unsigned int order,
788778
bool write)
789779
{
@@ -1323,7 +1313,6 @@ bool fuse_dax_inode_alloc(struct super_block *sb, struct fuse_inode *fi)
13231313
}
13241314

13251315
static const struct address_space_operations fuse_dax_file_aops = {
1326-
.writepages = fuse_dax_writepages,
13271316
.direct_IO = noop_direct_IO,
13281317
.dirty_folio = noop_dirty_folio,
13291318
};

fs/fuse/dev.c

Lines changed: 39 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1028,17 +1028,27 @@ static int fuse_copy_pages(struct fuse_copy_state *cs, unsigned nbytes,
10281028
struct fuse_req *req = cs->req;
10291029
struct fuse_args_pages *ap = container_of(req->args, typeof(*ap), args);
10301030

1031-
1032-
for (i = 0; i < ap->num_pages && (nbytes || zeroing); i++) {
1031+
for (i = 0; i < ap->num_folios && (nbytes || zeroing); i++) {
10331032
int err;
10341033
unsigned int offset = ap->descs[i].offset;
10351034
unsigned int count = min(nbytes, ap->descs[i].length);
1035+
struct page *orig, *pagep;
1036+
1037+
orig = pagep = &ap->folios[i]->page;
10361038

1037-
err = fuse_copy_page(cs, &ap->pages[i], offset, count, zeroing);
1039+
err = fuse_copy_page(cs, &pagep, offset, count, zeroing);
10381040
if (err)
10391041
return err;
10401042

10411043
nbytes -= count;
1044+
1045+
/*
1046+
* fuse_copy_page may have moved a page from a pipe instead of
1047+
* copying into our given page, so update the folios if it was
1048+
* replaced.
1049+
*/
1050+
if (pagep != orig)
1051+
ap->folios[i] = page_folio(pagep);
10421052
}
10431053
return 0;
10441054
}
@@ -1654,24 +1664,25 @@ static int fuse_notify_store(struct fuse_conn *fc, unsigned int size,
16541664

16551665
num = outarg.size;
16561666
while (num) {
1667+
struct folio *folio;
16571668
struct page *page;
16581669
unsigned int this_num;
16591670

1660-
err = -ENOMEM;
1661-
page = find_or_create_page(mapping, index,
1662-
mapping_gfp_mask(mapping));
1663-
if (!page)
1671+
folio = filemap_grab_folio(mapping, index);
1672+
err = PTR_ERR(folio);
1673+
if (IS_ERR(folio))
16641674
goto out_iput;
16651675

1666-
this_num = min_t(unsigned, num, PAGE_SIZE - offset);
1676+
page = &folio->page;
1677+
this_num = min_t(unsigned, num, folio_size(folio) - offset);
16671678
err = fuse_copy_page(cs, &page, offset, this_num, 0);
1668-
if (!PageUptodate(page) && !err && offset == 0 &&
1669-
(this_num == PAGE_SIZE || file_size == end)) {
1670-
zero_user_segment(page, this_num, PAGE_SIZE);
1671-
SetPageUptodate(page);
1679+
if (!folio_test_uptodate(folio) && !err && offset == 0 &&
1680+
(this_num == folio_size(folio) || file_size == end)) {
1681+
folio_zero_segment(folio, this_num, folio_size(folio));
1682+
folio_mark_uptodate(folio);
16721683
}
1673-
unlock_page(page);
1674-
put_page(page);
1684+
folio_unlock(folio);
1685+
folio_put(folio);
16751686

16761687
if (err)
16771688
goto out_iput;
@@ -1703,7 +1714,7 @@ static void fuse_retrieve_end(struct fuse_mount *fm, struct fuse_args *args,
17031714
struct fuse_retrieve_args *ra =
17041715
container_of(args, typeof(*ra), ap.args);
17051716

1706-
release_pages(ra->ap.pages, ra->ap.num_pages);
1717+
release_pages(ra->ap.folios, ra->ap.num_folios);
17071718
kfree(ra);
17081719
}
17091720

@@ -1717,7 +1728,7 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
17171728
unsigned int num;
17181729
unsigned int offset;
17191730
size_t total_len = 0;
1720-
unsigned int num_pages;
1731+
unsigned int num_pages, cur_pages = 0;
17211732
struct fuse_conn *fc = fm->fc;
17221733
struct fuse_retrieve_args *ra;
17231734
size_t args_size = sizeof(*ra);
@@ -1736,15 +1747,15 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
17361747
num_pages = (num + offset + PAGE_SIZE - 1) >> PAGE_SHIFT;
17371748
num_pages = min(num_pages, fc->max_pages);
17381749

1739-
args_size += num_pages * (sizeof(ap->pages[0]) + sizeof(ap->descs[0]));
1750+
args_size += num_pages * (sizeof(ap->folios[0]) + sizeof(ap->descs[0]));
17401751

17411752
ra = kzalloc(args_size, GFP_KERNEL);
17421753
if (!ra)
17431754
return -ENOMEM;
17441755

17451756
ap = &ra->ap;
1746-
ap->pages = (void *) (ra + 1);
1747-
ap->descs = (void *) (ap->pages + num_pages);
1757+
ap->folios = (void *) (ra + 1);
1758+
ap->descs = (void *) (ap->folios + num_pages);
17481759

17491760
args = &ap->args;
17501761
args->nodeid = outarg->nodeid;
@@ -1755,19 +1766,20 @@ static int fuse_retrieve(struct fuse_mount *fm, struct inode *inode,
17551766

17561767
index = outarg->offset >> PAGE_SHIFT;
17571768

1758-
while (num && ap->num_pages < num_pages) {
1759-
struct page *page;
1769+
while (num && cur_pages < num_pages) {
1770+
struct folio *folio;
17601771
unsigned int this_num;
17611772

1762-
page = find_get_page(mapping, index);
1763-
if (!page)
1773+
folio = filemap_get_folio(mapping, index);
1774+
if (IS_ERR(folio))
17641775
break;
17651776

17661777
this_num = min_t(unsigned, num, PAGE_SIZE - offset);
1767-
ap->pages[ap->num_pages] = page;
1768-
ap->descs[ap->num_pages].offset = offset;
1769-
ap->descs[ap->num_pages].length = this_num;
1770-
ap->num_pages++;
1778+
ap->folios[ap->num_folios] = folio;
1779+
ap->descs[ap->num_folios].offset = offset;
1780+
ap->descs[ap->num_folios].length = this_num;
1781+
ap->num_folios++;
1782+
cur_pages++;
17711783

17721784
offset = 0;
17731785
num -= this_num;

fs/fuse/dir.c

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
366366
struct fuse_mount *fm = get_fuse_mount_super(sb);
367367
FUSE_ARGS(args);
368368
struct fuse_forget_link *forget;
369-
u64 attr_version;
369+
u64 attr_version, evict_ctr;
370370
int err;
371371

372372
*inode = NULL;
@@ -381,6 +381,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
381381
goto out;
382382

383383
attr_version = fuse_get_attr_version(fm->fc);
384+
evict_ctr = fuse_get_evict_ctr(fm->fc);
384385

385386
fuse_lookup_init(fm->fc, &args, nodeid, name, outarg);
386387
err = fuse_simple_request(fm, &args);
@@ -398,7 +399,7 @@ int fuse_lookup_name(struct super_block *sb, u64 nodeid, const struct qstr *name
398399

399400
*inode = fuse_iget(sb, outarg->nodeid, outarg->generation,
400401
&outarg->attr, ATTR_TIMEOUT(outarg),
401-
attr_version);
402+
attr_version, evict_ctr);
402403
err = -ENOMEM;
403404
if (!*inode) {
404405
fuse_queue_forget(fm->fc, forget, outarg->nodeid, 1);
@@ -691,7 +692,7 @@ static int fuse_create_open(struct mnt_idmap *idmap, struct inode *dir,
691692
ff->nodeid = outentry.nodeid;
692693
ff->open_flags = outopenp->open_flags;
693694
inode = fuse_iget(dir->i_sb, outentry.nodeid, outentry.generation,
694-
&outentry.attr, ATTR_TIMEOUT(&outentry), 0);
695+
&outentry.attr, ATTR_TIMEOUT(&outentry), 0, 0);
695696
if (!inode) {
696697
flags &= ~(O_CREAT | O_EXCL | O_TRUNC);
697698
fuse_sync_release(NULL, ff, flags);
@@ -822,7 +823,7 @@ static int create_new_entry(struct mnt_idmap *idmap, struct fuse_mount *fm,
822823
goto out_put_forget_req;
823824

824825
inode = fuse_iget(dir->i_sb, outarg.nodeid, outarg.generation,
825-
&outarg.attr, ATTR_TIMEOUT(&outarg), 0);
826+
&outarg.attr, ATTR_TIMEOUT(&outarg), 0, 0);
826827
if (!inode) {
827828
fuse_queue_forget(fm->fc, forget, outarg.nodeid, 1);
828829
return -ENOMEM;
@@ -1585,13 +1586,13 @@ static int fuse_permission(struct mnt_idmap *idmap,
15851586
return err;
15861587
}
15871588

1588-
static int fuse_readlink_page(struct inode *inode, struct page *page)
1589+
static int fuse_readlink_page(struct inode *inode, struct folio *folio)
15891590
{
15901591
struct fuse_mount *fm = get_fuse_mount(inode);
1591-
struct fuse_page_desc desc = { .length = PAGE_SIZE - 1 };
1592+
struct fuse_folio_desc desc = { .length = PAGE_SIZE - 1 };
15921593
struct fuse_args_pages ap = {
1593-
.num_pages = 1,
1594-
.pages = &page,
1594+
.num_folios = 1,
1595+
.folios = &folio,
15951596
.descs = &desc,
15961597
};
15971598
char *link;
@@ -1614,7 +1615,7 @@ static int fuse_readlink_page(struct inode *inode, struct page *page)
16141615
if (WARN_ON(res >= PAGE_SIZE))
16151616
return -EIO;
16161617

1617-
link = page_address(page);
1618+
link = folio_address(folio);
16181619
link[res] = '\0';
16191620

16201621
return 0;
@@ -1624,7 +1625,7 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
16241625
struct delayed_call *callback)
16251626
{
16261627
struct fuse_conn *fc = get_fuse_conn(inode);
1627-
struct page *page;
1628+
struct folio *folio;
16281629
int err;
16291630

16301631
err = -EIO;
@@ -1638,20 +1639,20 @@ static const char *fuse_get_link(struct dentry *dentry, struct inode *inode,
16381639
if (!dentry)
16391640
goto out_err;
16401641

1641-
page = alloc_page(GFP_KERNEL);
1642+
folio = folio_alloc(GFP_KERNEL, 0);
16421643
err = -ENOMEM;
1643-
if (!page)
1644+
if (!folio)
16441645
goto out_err;
16451646

1646-
err = fuse_readlink_page(inode, page);
1647+
err = fuse_readlink_page(inode, folio);
16471648
if (err) {
1648-
__free_page(page);
1649+
folio_put(folio);
16491650
goto out_err;
16501651
}
16511652

1652-
set_delayed_call(callback, page_put_link, page);
1653+
set_delayed_call(callback, page_put_link, &folio->page);
16531654

1654-
return page_address(page);
1655+
return folio_address(folio);
16551656

16561657
out_err:
16571658
return ERR_PTR(err);
@@ -2028,7 +2029,7 @@ int fuse_do_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
20282029

20292030
fuse_change_attributes_common(inode, &outarg.attr, NULL,
20302031
ATTR_TIMEOUT(&outarg),
2031-
fuse_get_cache_mask(inode));
2032+
fuse_get_cache_mask(inode), 0);
20322033
oldsize = inode->i_size;
20332034
/* see the comment in fuse_change_attributes() */
20342035
if (!is_wb || is_truncate)
@@ -2231,7 +2232,7 @@ void fuse_init_dir(struct inode *inode)
22312232

22322233
static int fuse_symlink_read_folio(struct file *null, struct folio *folio)
22332234
{
2234-
int err = fuse_readlink_page(folio->mapping->host, &folio->page);
2235+
int err = fuse_readlink_page(folio->mapping->host, folio);
22352236

22362237
if (!err)
22372238
folio_mark_uptodate(folio);

0 commit comments

Comments
 (0)