From: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>
To: intel-xe@lists.freedesktop.org
Cc: "Thomas Hellström" <thomas.hellstrom@linux.intel.com>,
"Andrew Morton" <akpm@linux-foundation.org>,
"David Hildenbrand" <david@kernel.org>,
"Michal Hocko" <mhocko@kernel.org>,
"Qi Zheng" <zhengqi.arch@bytedance.com>,
"Shakeel Butt" <shakeel.butt@linux.dev>,
"Lorenzo Stoakes" <ljs@kernel.org>,
"Axel Rasmussen" <axelrasmussen@google.com>,
"Yuanchu Xie" <yuanchu@google.com>, "Wei Xu" <weixugc@google.com>,
"Brian Geffon" <bgeffon@google.com>,
"Steven Barrett" <steven@liquorix.net>,
"Oleksandr Natalenko" <oleksandr@natalenko.name>,
linux-mm@kvack.org, linux-kernel@vger.kernel.org
Subject: [RFC PATCH 1/1] mm: vmscan: keep anon scanning enabled when swapcache folios are present
Date: Mon, 27 Apr 2026 12:35:32 +0200 [thread overview]
Message-ID: <20260427103532.5623-2-thomas.hellstrom@linux.intel.com> (raw)
In-Reply-To: <20260427103532.5623-1-thomas.hellstrom@linux.intel.com>
Two separate guards in the reclaim path suppress all anon-LRU scanning
when swap space is exhausted or nearly so:
can_reclaim_anon_pages() – returns false when get_nr_swap_pages()==0
(or the memcg swap limit is reached);
used by the non-MGLRU get_scan_count() and
several MGLRU helper estimations.
get_swappiness() [MGLRU] – returns 0 when the above condition holds AND
the per-memcg free-swap count drops below
MIN_LRU_BATCH, causing for_each_evictable_type()
to skip LRU_GEN_ANON entirely.
Both guards exist for a good reason: if there is no swap space, trying to
write out an anon folio is pointless because folio_alloc_swap() will fail
before a slot can be assigned. The scan overhead is wasted and may delay
reclaiming more useful file-backed pages.
However, both guards conflate two conceptually different populations of
anon pages:
1. Anon pages that have never been backed by swap.
These require a free slot before they can be reclaimed.
The guards are correct for this group.
2. Anon folios that are already in the swap cache (PG_swapcache set).
These carry a pre-allocated swap slot. Writing them back and
dropping their RAM backing does NOT consume a new slot: the slot
already exists and its map-count is held at >= 1 (via
folio_dup_swap()) until the content has been safely stored.
Reclaiming such a folio frees nr_pages of RAM while leaving the
slot count unchanged.
Because the two guards do not distinguish between these groups, they
suppress anon scanning for the entire LRU once swap becomes scarce,
even when swapcache folios are present that could be reclaimed for free.
The practical consequence is that those folios remain in RAM,
blocking forward progress under memory pressure.
Fix this by continuing the scan while there are pages in the swap cache
RFC:
This might actually be intentional: accepting a presumably small number
of freeable pages in the swap cache to avoid costly LRU scans?
There might also be more efficient fixes, like introducing a separate
LRU list for swapcache pages?
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: David Hildenbrand <david@kernel.org>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Qi Zheng <zhengqi.arch@bytedance.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Brian Geffon <bgeffon@google.com>
Cc: Steven Barrett <steven@liquorix.net>
Cc: Oleksandr Natalenko <oleksandr@natalenko.name>
Cc: linux-mm@kvack.org
Cc: linux-kernel@vger.kernel.org
Fixes: ac35a4902374 ("mm: multi-gen LRU: minimal implementation")
Fixes: a2a36488a61c ("mm/vmscan: Consider anonymous pages without swap")
Assisted-by: GitHub Copilot:claude-sonnet-4.6
Signed-off-by: Thomas Hellström <thomas.hellstrom@linux.intel.com>
---
mm/vmscan.c | 21 +++++++++++++++++++--
1 file changed, 19 insertions(+), 2 deletions(-)
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 0fc9373e8251..f50a5fc99fc9 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -377,6 +377,15 @@ static inline bool can_reclaim_anon_pages(struct mem_cgroup *memcg,
return true;
}
+ /*
+ * Even with no free swap slots, anon folios already in the swap cache
+ * carry a pre-allocated slot and can be written back and freed from RAM
+ * without consuming a new one. Do not suppress anon scanning when such
+ * folios are present on this node.
+ */
+ if (node_page_state(NODE_DATA(nid), NR_SWAPCACHE) > 0)
+ return true;
+
/*
* The page can not be swapped.
*
@@ -2736,8 +2745,16 @@ static int get_swappiness(struct lruvec *lruvec, struct scan_control *sc)
return 0;
if (!can_demote(pgdat->node_id, sc, memcg) &&
- mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH)
- return 0;
+ mem_cgroup_get_nr_swap_pages(memcg) < MIN_LRU_BATCH) {
+ /*
+ * Even with few free swap slots, folios already in the swap
+ * cache carry a pre-allocated slot and can be written back and
+ * freed from RAM without consuming a new one. Keep anon
+ * scanning enabled while such folios remain in this lruvec.
+ */
+ if (!lruvec_page_state(lruvec, NR_SWAPCACHE))
+ return 0;
+ }
return sc_swappiness(sc, memcg);
}
--
2.53.0
prev parent reply other threads:[~2026-04-27 10:36 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-27 10:35 [RFC PATCH 0/1] Fix halted scanning of swap-cache folios Thomas Hellström
2026-04-27 10:35 ` Thomas Hellström [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260427103532.5623-2-thomas.hellstrom@linux.intel.com \
--to=thomas.hellstrom@linux.intel.com \
--cc=akpm@linux-foundation.org \
--cc=axelrasmussen@google.com \
--cc=bgeffon@google.com \
--cc=david@kernel.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=ljs@kernel.org \
--cc=mhocko@kernel.org \
--cc=oleksandr@natalenko.name \
--cc=shakeel.butt@linux.dev \
--cc=steven@liquorix.net \
--cc=weixugc@google.com \
--cc=yuanchu@google.com \
--cc=zhengqi.arch@bytedance.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox