[PATCH 17/28] fuse: use an unrestricted backing device with iomap pagecache io

Darrick J. Wong
2025-09-16T00:32:24Z

With iomap support turned on for the pagecache, the kernel issues
writeback to directly to block devices and we no longer have to push all
those pages through the fuse device to userspace. Therefore, we don't
need the tight dirty limits (~1M) that are used for regular fuse. This
dramatically increases the performance of fuse's pagecache IO.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
fs/fuse/file_iomap.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)

diff --git a/fs/fuse/file_iomap.c b/fs/fuse/file_iomap.c
index c09e00c7de2694..6cc1f91fe3d5a4 100644
--- a/fs/fuse/file_iomap.c
+++ b/fs/fuse/file_iomap.c
@@ -711,6 +711,27 @@ const struct fuse_backing_ops fuse_iomap_backing_ops = {
void fuse_iomap_mount(struct fuse_mount *fm)
{
struct fuse_conn *fc = fm->fc;
+ struct super_block *sb = fm->sb;
+ struct backing_dev_info *old_bdi = sb->s_bdi;
+ char *suffix = sb->s_bdev ? "-fuseblk" : "-fuse";
+ int res;
+
+ /*
+ * sb->s_bdi points to the initial private bdi. However, we want to
+ * redirect it to a new private bdi with default dirty and readahead
+ * settings because iomap writeback won't be pushing a ton of dirty
+ * data through the fuse device. If this fails we fall back to the
+ * initial fuse bdi.
+ */
+ sb->s_bdi = &noop_backing_dev_info;
+ res = super_setup_bdi_name(sb, "%u:%u%s.iomap", MAJOR(fc->dev),
+ MINOR(fc->dev), suffix);
+ if (res) {
+ sb->s_bdi = old_bdi;
+ } else {
+ bdi_unregister(old_bdi);
+ bdi_put(old_bdi);
+ }

/*
* Enable syncfs for iomap fuse servers so that we can send a final