Re: [PATCH v2] fuse: allow larger read requests by setting bdi->io_pages
From: Joanne Koong
Date: Tue Jun 23 2026 - 13:49:42 EST
On Mon, Jun 22, 2026 at 5:42 PM Jim Harris <jim.harris@xxxxxxxxxx> wrote:
>
> A FUSE server that advertises a large max_pages and max_write (e.g.
> max_pages=256, max_write=1MB) cannot currently obtain matching
> FUSE_READ request sizes from the kernel. Buffered sequential writes
> arrive at the server at the negotiated max_write size, but a large
> buffered read() is split into several smaller FUSE_READ requests.
>
> For a buffered read, filemap_get_pages() -> page_cache_sync_ra() sizes
> the read against ractl_max_pages():
>
> max_pages = ractl->ra->ra_pages;
> if (req_size > max_pages && bdi->io_pages > max_pages)
> max_pages = min(req_size, bdi->io_pages);
>
> fuse leaves bdi->io_pages at the default VM_READAHEAD_PAGES (128KB), so
> a 1MB read() (req_size = 256 pages) is clamped to the readahead window
> (128KB, or 256KB for POSIX_FADV_SEQUENTIAL), producing four 256KB
> FUSE_READ round-trips instead of one.
>
> Set bdi->io_pages to fc->max_pages after feature negotiation. As the
> code above shows, io_pages only raises the limit when the request size
> already exceeds the readahead window, so it enlarges explicitly
> requested reads without enlarging the speculative readahead window.
> This avoids increasing speculative page-cache readahead on behalf of
> an unprivileged server. NFS does the same, setting io_pages from
> rpages while leaving ra_pages at the default.
>
> fc->max_pages is already bounded by fc->max_pages_limit (and, for
> virtio-fs, by the virtqueue descriptor count), so io_pages inherits
> the same bound.
>
> Suggested-by: Joanne Koong <joannelkoong@xxxxxxxxx>
> Signed-off-by: Jim Harris <jim.harris@xxxxxxxxxx>
> Assisted-by: Cursor:claude-opus-4.8
> ---
> Changes since v1 [1]:
> - Set bdi->io_pages instead of bdi->ra_pages, per Joanne's review.
> Raising ra_pages would also enlarge the speculative readahead
> window for all workloads (including small sequential reads),
> increasing page-cache readahead on behalf of the server. Setting
> io_pages enlarges only explicitly requested reads larger than the
> readahead window, leaving speculative readahead unchanged.
>
> [1] https://lore.kernel.org/linux-fsdevel/20260602204430.18427-1-jim.harris@xxxxxxxxxx/
>
> Notes on AI assistance:
>
> The mm/readahead analysis (confirming ractl_max_pages() consults
> io_pages only when the request exceeds the readahead window) and the
> bulk of this changelog were drafted with an AI coding assistant (see
> Assisted-by trailer). The one-line code change was reviewed by me.
> The motivating performance observation was made by me on a real
> virtio-fs workload, and verification was performed by me.
>
> fs/fuse/inode.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
> index deddfffb037f..c8373e537d2b 100644
> --- a/fs/fuse/inode.c
> +++ b/fs/fuse/inode.c
> @@ -1495,6 +1495,7 @@ static void process_init_reply(struct fuse_mount *fm, struct fuse_args *args,
>
> fm->sb->s_bdi->ra_pages =
> min(fm->sb->s_bdi->ra_pages, ra_pages);
> + fm->sb->s_bdi->io_pages = fc->max_pages;
> fc->minor = arg->minor;
> fc->max_write = arg->minor < 5 ? 4096 : arg->max_write;
> fc->max_write = max_t(unsigned, 4096, fc->max_write);
> --
> 2.43.0
>
Reviewed-by: Joanne Koong <joannelkoong@xxxxxxxxx>