Re: [PATCH 1/1] iomap: avoid compaction for costly folio order allocation
From: Dave Chinner
Date: Sun Apr 05 2026 - 18:44:14 EST
On Fri, Apr 03, 2026 at 07:35:34PM +0000, Salvatore Dipietro wrote:
> Commit 5d8edfb900d5 ("iomap: Copy larger chunks from userspace")
> introduced high-order folio allocations in the buffered write
> path. When memory is fragmented, each failed allocation triggers
> compaction and drain_all_pages() via __alloc_pages_slowpath(),
> causing a 0.75x throughput drop on pgbench (simple-update) with
> 1024 clients on a 96-vCPU arm64 system.
>
> Strip __GFP_DIRECT_RECLAIM from folio allocations in
> iomap_get_folio() when the order exceeds PAGE_ALLOC_COSTLY_ORDER,
> making them purely opportunistic.
>
> Fixes: 5d8edfb900d5 ("iomap: Copy larger chunks from userspace")
> Cc: stable@xxxxxxxxxxxxxxx
> Signed-off-by: Salvatore Dipietro <dipiets@xxxxxxxxx>
> ---
> fs/iomap/buffered-io.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
> index 92a831cf4bf1..cb843d54b4d9 100644
> --- a/fs/iomap/buffered-io.c
> +++ b/fs/iomap/buffered-io.c
> @@ -715,6 +715,7 @@ EXPORT_SYMBOL_GPL(iomap_is_partially_uptodate);
> struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos, size_t len)
> {
> fgf_t fgp = FGP_WRITEBEGIN | FGP_NOFS;
> + gfp_t gfp;
>
> if (iter->flags & IOMAP_NOWAIT)
> fgp |= FGP_NOWAIT;
> @@ -722,8 +723,20 @@ struct folio *iomap_get_folio(struct iomap_iter *iter, loff_t pos, size_t len)
> fgp |= FGP_DONTCACHE;
> fgp |= fgf_set_order(len);
>
> + gfp = mapping_gfp_mask(iter->inode->i_mapping);
> +
> + /*
> + * If the folio order hint exceeds PAGE_ALLOC_COSTLY_ORDER,
> + * strip __GFP_DIRECT_RECLAIM to make the allocation purely
> + * opportunistic. This avoids compaction + drain_all_pages()
> + * in __alloc_pages_slowpath() that devastate throughput
> + * on large systems during buffered writes.
> + */
> + if (FGF_GET_ORDER(fgp) > PAGE_ALLOC_COSTLY_ORDER)
> + gfp &= ~__GFP_DIRECT_RECLAIM;
Adding these "gfp &= ~__GFP_DIRECT_RECLAIM" hacks everywhere
we need to do high order folio allocation is getting out of hand.
Compaction improves long term system performance, so we don't really
just want to turn it off whenever we have demand for high order
folios.
We should be doing is getting rid of compaction out of the direct
reclaim path - it is -clearly- way too costly for hot paths that use
large allocations, especially those with fallbacks to smaller
allocations or vmalloc.
Instead, memory reclaim should kick background compaction and let it
do the work. If the allocation path really, really needs high order
allocation to succeed, then it can direct the allocation to retry
until it succeeds and the allocator itself can wait for background
compaction to make progress.
For code that has fallbacks to smaller allocations, then there is no
need to wait for compaction - we can attempt fast smaller allocations
and continue that way until an allocation succeeds....
-Dave.
--
Dave Chinner
dgc@xxxxxxxxxx