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. Thanks, Joanne > /* > * Large folios belonging to fuse will never > * have more pages than max_pages. > */ > WARN_ON(!pages); > > > -- > Thanks, > Jingbo >