Re: [RFC PATCH 0/1] mm/swap: keep reclaim batches contiguous on swap
From: Alexandre Ghiti
Date: Mon Nov 02 2026 - 04:42:17 EST
Hi Kairui,
Back from holidays, sorry for the late answer.
On Mon, Oct 26, 2026 at 2:38 PM Kairui Song <ryncsn@xxxxxxxxx> wrote:
>
> >
> On Fri, Oct 23, 2026 at 12:17 AM Alexandre Ghiti <alexghiti@xxxxxxxx> wrote:
> >
> > Hi Kairui,
> >
> > On Thu, Oct 22, 2026 at 5:27 PM Kairui Song <ryncsn@xxxxxxxxx> wrote:
> > >
> > > >
> > > On Thu, Oct 22, 2026 at 11:00 PM Alexandre Ghiti <alex@xxxxxxxx> wrote:
> > > >
> > > > 7.3 regressed swap I/O: for the same swap volume, a workload that
> > > > rewrites swapped out memory sends many more requests to the device.
> > > > mysql/sysbench in a 256M memcg swapping to an NVMe partition, 7.3
> > > > compared to the previous version:
> > > >
> > > > device read requests per transaction +59%
> > > > device write requests per transaction +27%
> > > > throughput, iocost off no change
> > > > throughput, iocost on -19%
> > > >
> > > > Two commits interact:
> > > >
> > > > - Commit 9a42aed48421 ("mm, swap: prefer nonfull over free clusters"),
> > > > in 6.18, makes order-0 allocations fill nonfull clusters before
> > > > taking a free one.
> > > >
> > > > - Commit 3cedb745d354 ("mm: clarify the folio_free_swap() for
> > > > do_swap_page()"), in 7.3, frees the swap slot on an exclusive write
> > > > fault. 7.0 to 7.2 kept the slot, but only as a side effect of commit
> > > > 4b34f1d82c65 ("mm, swap: free the swap cache after folio is
> > > > mapped").
> > > >
> > > > The freed slots leave holes in full clusters, which then go back on
> > > > the nonfull list. Reclaim allocates slots one folio at a time and
> > > > merges the writes afterwards, so a batch of LRU-adjacent folios gets
> > > > scattered over those holes and is written with many small requests.
> > > > Readahead later finds those pages scattered as well, and needs more
> > > > read requests to bring them back.
> > > >
> > > > I tried three fixes, which perform similarly:
> > > >
> > > > A. Revert 3cedb745d354. This keeps the slot on write fault, but undoes
> > > > the intent of that commit and keeps swap space pinned under dirty
> > > > pages.
> > > >
> > > > B. Below 50% swap usage, make order-0 allocations take a free cluster
> > > > before a nonfull one. This is what the allocator already does, at
> > > > any usage, on swap devices with discard enabled (swapon
> > > > --discard=pages). It is about five lines, but the threshold is
> > > > arbitrary, it stops working as swap fills up, and it applies to
> > > > every order-0 allocation, using up the free clusters that
> > > > nonfull-first keeps for mTHP.
> > >
> > > Hi Alexandre,
> > >
> > > That's a interesting problem. I think the real problem is with commit
> > > 9a42aed48421 ("mm, swap: prefer nonfull over free clusters"), right?
> > >
> > > It's more like a balance between fragmentation and contiguity of small
> > > order allocation issue.
> > >
> > > Perhaps we should instead always scan the full clusters and revert
> > > that one commit? That commit was only following the idea of keeping
> > > the allocation more compacted for that series, it looked good at that
> > > time. Since fragmentation issues can be solved in other ways,
> > > contiguity seems to matter more for large physical swap devices.
> > >
> >
>
> Hi,
>
> > Oh, okay. I thought reverting it wasn't an option given the good
> > numbers the patch provides.
>
> That patch is 1/3 of a series, that series yields really nice
> results, but that one patch plays only a small part in them. Or
> perhaps we can limit that to SYNC devices?
I'm a bit scared it would not help zswap with writeback on, unless you
mean actual SWP_SYNCHRONOUS_IO devices?
> I hope there are simpler
> ways to avoid the problem you encountered. I think the ~4% reduction
> of 64k mTHP failure is kind of trivial compared to the problem you
> encountered, and 2M swapout is still not easily doable, as the
> main blocker is from the page allocator.
>
> >
> > What are the other fragmentation solutions you are referring to?
>
> Right, nothing has landed in upstream for that yet, but with larger
> swap space the fragmentation issue will be largely solved. And before
> that we might be able to sort the clusters by the continues size of
> slots on it instead just blindly move then back to nonfull on any
> freeing.
Sorting would only help the current patch since reclaim allocates swap
slots per folio, not per batch.
What do you think the next move should be? Should we implement your
sorting idea on top of this patch or revert the nonfull cluster first
allocation? IMO, trying to fill the holes before allocating a new
cluster is the best solution. Doing that in reclaim, as I do here
avoids distinguishing between sync/async devices, so I'd favor a v2.
Let me know what you think and I'd go with your preferred idea,
Alex