public inbox for linux-mm@kvack.org
 help / color / mirror / Atom feed
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



      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