Re: [PATCH] mm: madvise: drop MADV_PAGEOUT folios at swap writeback completion
From: Kairui Song
Date: Tue Sep 22 2026 - 05:47:39 EST
On Tue, Sep 22, 2026 at 12:00 AM Barry Song <baohua@xxxxxxxxxx> wrote:
>
> On Mon, Sep 21, 2026 at 11:37 PM David Hildenbrand (Arm)
> <david@xxxxxxxxxx> wrote:
> >
> > On 9/21/26 17:24, Alexandre Ghiti wrote:
> > > On an asynchronous swap device MADV_PAGEOUT only marks the folio
> > > PG_reclaim and rotates it to the tail of the inactive list once its
> > > writeback completes, so the memory is not actually freed until a later
> > > reclaim scan removes the by then clean swap cache folio.
> > But we have the same behavior when just reclaiming memory ordinarily? It's added
> > to the swapcache and only the next scan actually frees up the memory.
> >
> > Wouldn't we memory we reclaim ... just gone, like in the sync case?
>
> For synchronous I/O, such as zswap and zram, the memory is released
> immediately after sync I/O is done.
>
> For asynchronous I/O, such as NVMe, the swapcache is currently
> expected to be rotated back to the tail of the LRU and wait for
> another scan. Alexandre once mentioned that when he tried handling
> async I/O the same way as sync I/O—releasing the memory once the I/O
> completed—he saw some regression. So, delaying the release until a
> later scan may allow swapcache hits before the folios are eventually
> reclaimed.
>
> But we actually have a problem here: this rotation, which puts
> writeback folios at the tail of the LRU, is not reliable at all.
>
> `folio_rotate_reclaimable()` would only work reliably if the endio
> happens after the folio has been put back on the LRU head, rather than
> while it is still isolated.
I think we might better fix this instead? Or is this really a problem?
If it has PG_reclaim, it should be putback to the tail instead of
head, right?
> But nowadays NVMe is very fast. If we isolate N pages and perform
> shrink on them, M pages may finish writeback during the isolation,
> while the remaining N-M pages are still under writeback. M can easily
> be more than 50% of N.
>
> As a result, we can end up with the following cold/hot inversion:
>
> LRU head
> ----- M pages whose writeback completed during isolation
> ----- other pages
> ----- N-M pages that are successfully rotated to the LRU tail
> LRU tail
>
> Now we can see that the M pages were expected to be reclaimed, but
> they are not only left unreclaimed, but are effectively promoted to
> the LRU head.
>
> For MGLRU, commit 359a5e1416ca ("mm: multi-gen LRU: retry folios
> written back while isolated") added the following code to reclaim
> those M pages that finish writeback during isolation by retrying
> `shrink_folio_list()` on them:
>
> /* retry folios that may have missed
> folio_rotate_reclaimable() */
> if (!skip_retry && !folio_test_active(folio) &&
> !folio_mapped(folio) &&
> !folio_test_dirty(folio) && !folio_test_writeback(folio)) {
> list_move(&folio->lru, &clean);
> continue;
> }
>
> This somehow resolves the cold/hot inversion, but leaves the M and
> N-M pages with inconsistent behavior: some are actually reclaimed,
> while others remain at the tail of the LRU.
>
> For the active/inactive LRU and `MADV_PAGEOUT`, we don't have a
> mechanism to restore the missed reclaim opportunity. Ridong's patch[1]
> addresses this cold/hot inversion in the active/inactive LRU reclaim
> path. To my knowledge, there has never been a patch to address the
> same cold/hot inversion in `MADV_PAGEOUT`.
MADV_PAGEOUT is a bit different from the reclaim under pressure,
reclaim underpressure can easily overshoot the amount of anon folios
reclaimed, because however fast the writeback it, it can be faster by
scanning the LRU and dropping clean file folios. So before LRU
reclaimed enough clean file folios, we can't stop the reclaim.
I think the better fix is to have a separate watermark for anon / file
or a new way to handle reclaim. Reclaiming an anon folio is hardly
helpful in the short term when under heavy pressure and the device is
not a synchronous device.
The overshoot is a real issue, it's very common to see many folios
stuck in the swap cache after memory pressure. If we drop all of them,
we will see significant regressions. Treating MADV_PAGEOUT differently
here seems better.