On 8/16/25 12:16 AM, Joanne Koong wrote: > On Fri, Aug 15, 2025 at 4:01 AM Jingbo Xu <jefflexu@xxxxxxxxxxxxxxxxx> wrote: >> >> >> >> On 8/12/25 4:40 AM, Joanne Koong wrote: >>> Large folios are only enabled if the writeback cache isn't on. >>> (Strictlimiting needs to be turned off if the writeback cache is used in >>> conjunction with large folios, else this tanks performance.) >>> >>> Benchmarks showed noticeable improvements for writes (both sequential >>> and random). There were no performance differences seen for random reads >>> or direct IO. For sequential reads, there was no performance difference >>> seen for the first read (which populates the page cache) but subsequent >>> sequential reads showed a huge speedup. >>> >>> Benchmarks were run using fio on the passthrough_hp fuse server: >>> ~/libfuse/build/example/passthrough_hp ~/libfuse ~/fuse_mnt --nopassthrough --nocache >>> >>> run fio in ~/fuse_mnt: >>> fio --name=test --ioengine=sync --rw=write --bs=1M --size=5G --numjobs=2 --ramp_time=30 --group_reporting=1 >>> >>> Results (tested on bs=256K, 1M, 5M) showed roughly a 15-20% increase in >>> write throughput and for sequential reads after the page cache has >>> already been populated, there was a ~800% speedup seen. >>> >>> Signed-off-by: Joanne Koong <joannelkoong@xxxxxxxxx> >>> --- >>> fs/fuse/file.c | 18 ++++++++++++++++-- >>> 1 file changed, 16 insertions(+), 2 deletions(-) >>> >>> diff --git a/fs/fuse/file.c b/fs/fuse/file.c >>> index adc4aa6810f5..2e7aae294c9e 100644 >>> --- a/fs/fuse/file.c >>> +++ b/fs/fuse/file.c >>> @@ -1167,9 +1167,10 @@ static ssize_t fuse_fill_write_pages(struct fuse_io_args *ia, >>> pgoff_t index = pos >> PAGE_SHIFT; >>> unsigned int bytes; >>> unsigned int folio_offset; >>> + fgf_t fgp = FGP_WRITEBEGIN | fgf_set_order(num); >>> >>> again: >>> - folio = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN, >>> + folio = __filemap_get_folio(mapping, index, fgp, >>> mapping_gfp_mask(mapping)); >>> if (IS_ERR(folio)) { >>> err = PTR_ERR(folio); >>> @@ -3155,11 +3156,24 @@ void fuse_init_file_inode(struct inode *inode, unsigned int flags) >>> { >>> struct fuse_inode *fi = get_fuse_inode(inode); >>> struct fuse_conn *fc = get_fuse_conn(inode); >>> + unsigned int max_pages, max_order; >>> >>> inode->i_fop = &fuse_file_operations; >>> inode->i_data.a_ops = &fuse_file_aops; >>> - if (fc->writeback_cache) >>> + if (fc->writeback_cache) { >>> mapping_set_writeback_may_deadlock_on_reclaim(&inode->i_data); >>> + } else { >>> + /* >>> + * Large folios are only enabled if the writeback cache isn't on. >>> + * If the writeback cache is on, large folios should only be >>> + * enabled in conjunction with strictlimiting turned off, else >>> + * performance tanks. >>> + */ >>> + max_pages = min(min(fc->max_write, fc->max_read) >> PAGE_SHIFT, >>> + fc->max_pages); >>> + max_order = ilog2(max_pages); >>> + mapping_set_folio_order_range(inode->i_mapping, 0, max_order); >>> + } >> >> JFYI fc->max_read shall also be honored when calculating max_order, >> otherwise the following warning in fuse_readahead() may be triggered. >> > Hi Jingbo, > > I think fc->max_read gets honored in the "min(fc->max_write, > fc->max_read)" part of the max_pages calculation above. > Opps, yeah. My fault, sorry for the noise. -- Thanks, Jingbo