Re: [RFC PATCH 0/1] mm/swap: keep reclaim batches contiguous on swap
From: Kairui Song
Date: Mon Oct 26 2026 - 09:46:54 EST
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 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.