Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Barry Song (Xiaomi)" <baohua@kernel.org>
To: akpm@linux-foundation.org, linux-mm@kvack.org
Cc: axelrasmussen@google.com, chenridong@xiaomi.com,
	david@kernel.org, hannes@cmpxchg.org, kasong@tencent.com,
	lianux.mm@gmail.com, linux-kernel@vger.kernel.org,
	ljs@kernel.org, lyugaofei@xiaomi.com, mhocko@kernel.org,
	qi.zheng@linux.dev, shakeel.butt@linux.dev,
	stevensd@chromium.org, wangzicheng@honor.com, weixugc@google.com,
	yuanchu@google.com, zhangbo56@xiaomi.com,
	baolin.wang@linux.alibaba.com, baoquan.he@linux.dev,
	"Barry Song (Xiaomi)" <baohua@kernel.org>
Subject: [RFC PATCH v4 02/16] mm/mglru: improve scan_folios() exhaustion detection
Date: Wed, 12 Aug 2026 20:16:44 +0800	[thread overview]
Message-ID: <20260812121658.69965-3-baohua@kernel.org> (raw)
In-Reply-To: <20260812121658.69965-1-baohua@kernel.org>

Commit 16b475d2ac3c ("mm/mglru: avoid reclaim type fall back when
isolation makes no progress") uses scanned == 0 to determine
whether scan_folios() has exhausted a reclaim type. However,
this is not always sufficient. It is possible for scanned > 0,
while the oldest reclaimable generation is exhausted after the
first scan_folios() call.

We detect early_stop in scan_folios(). If we stop early for any reason,
it means the current reclaim type is not exhausted yet. If early_stop is
never reached, it means we have exhausted the current oldest generation
without hitting any scanning limit.

Another issue is that if the lruvec has 4 generations, we might have
exhausted the oldest generation while the second oldest generation is
still reclaimable. In that case, this type is not exhausted yet.

Add an exhausted output argument to scan_folios() so it can
explicitly report whether the reclaimable lists for the current
type have been exhausted.

Signed-off-by: Barry Song (Xiaomi) <baohua@kernel.org>
---
 mm/vmscan.c | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index ea058692b9a5..0670a25d3a7e 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4727,7 +4727,8 @@ static bool isolate_folio(struct lruvec *lruvec, struct folio *folio, struct sca
 
 static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 		       struct scan_control *sc, int type, int tier,
-		       struct list_head *list, int *isolatedp)
+		       struct list_head *list, int *isolatedp,
+		       bool *exhausted)
 {
 	int i;
 	int gen;
@@ -4738,12 +4739,15 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 	int skipped = 0;
 	unsigned long remaining = nr_to_scan;
 	struct lru_gen_folio *lrugen = &lruvec->lrugen;
+	bool early_stop = false;
 
 	VM_WARN_ON_ONCE(nr_to_scan > MAX_LRU_BATCH);
 	VM_WARN_ON_ONCE(!list_empty(list));
 
-	if (get_nr_gens(lruvec, type) == MIN_NR_GENS)
+	if (get_nr_gens(lruvec, type) == MIN_NR_GENS) {
+		*exhausted = true;
 		return 0;
+	}
 
 	gen = lru_gen_from_seq(lrugen->min_seq[type]);
 
@@ -4774,8 +4778,10 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 				skipped_zone += delta;
 			}
 
-			if (!--remaining || max(isolated, skipped_zone) >= MIN_LRU_BATCH)
+			if (!--remaining || max(isolated, skipped_zone) >= MIN_LRU_BATCH) {
+				early_stop = true;
 				break;
+			}
 		}
 
 		if (skipped_zone) {
@@ -4784,8 +4790,10 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 			skipped += skipped_zone;
 		}
 
-		if (!remaining || isolated >= MIN_LRU_BATCH)
+		if (!remaining || isolated >= MIN_LRU_BATCH) {
+			early_stop = true;
 			break;
+		}
 	}
 
 	item = PGSCAN_KSWAPD + reclaimer_offset(sc);
@@ -4796,6 +4804,13 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 				scanned, skipped, isolated,
 				type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON);
 
+	/*
+	 * If we didn't stop early, all reclaimable folios in the current
+	 * generation have been scanned. We are exhausted if this is the last
+	 * reclaimable generation.
+	 */
+	*exhausted = !early_stop &&
+		     lrugen->min_seq[type] + MIN_NR_GENS == lrugen->max_seq;
 	*isolatedp = isolated;
 	return scanned;
 }
@@ -4853,11 +4868,12 @@ static int isolate_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 	bool type_fallback_allowed = !is_single_type_reclaim(swappiness);
 	int type = get_type_to_scan(lruvec, swappiness);
 	int total_scanned = 0, scanned, tier;
+	bool exhausted;
 
 retry:
 	tier = get_tier_idx(lruvec, type);
 	scanned = scan_folios(nr_to_scan, lruvec, sc,
-			      type, tier, list, isolated);
+			      type, tier, list, isolated, &exhausted);
 
 	total_scanned += scanned;
 	if (*isolated) {
@@ -4870,7 +4886,7 @@ static int isolate_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
 	 * We are running out of the current reclaim type. Fall back to
 	 * the other type if allowed.
 	 */
-	if (!scanned && type_fallback_allowed) {
+	if (exhausted && type_fallback_allowed) {
 		type = !type;
 		type_fallback_allowed = false;
 		goto retry;
-- 
2.34.1



  parent reply	other threads:[~2026-08-12 12:18 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-12 12:16 [RFC PATCH v4 00/16] mm: mglru: fix swappiness behavior Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 01/16] mm/mglru: improve readability of isolate_folios() Barry Song (Xiaomi)
2026-08-12 12:16 ` Barry Song (Xiaomi) [this message]
2026-08-12 12:16 ` [RFC PATCH v4 03/16] mm/mglru: retry the same type once if isolation fails due to races Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 04/16] mm/mglru: boost swappiness responsiveness in get_type_to_scan() Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 05/16] mm/mglru: batch update lrugen->nr_pages in inc_min_seq() Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 06/16] mm/mglru: batch update lrugen->protected " Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 07/16] mm/mglru: enhance cold/hot inversion handling " Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 08/16] mm/mglru: exclude folios promoted by aging from protected " Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 09/16] mm/mglru: move folios from oldest gen to second-oldest gen from head to tail Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 10/16] mm/mglru: batch move folios to the second-oldest gen's LRU Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 11/16] mm/mglru: skip gentle reclaim at DEF_PRIORITY for extreme swappiness Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 12/16] mm/mglru: run aging if the preferred type has no reclaimable gens Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 13/16] mm/mglru: remove redundant gens <= MIN_NR_GENS check in should_run_aging() Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 14/16] mm/mglru: run aging when pages are severely imbalanced across gens Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 15/16] mm/mglru: dynamically scale aging threshold in lru_gen_imbalanced() Barry Song (Xiaomi)
2026-08-12 12:16 ` [RFC PATCH v4 16/16] mm/mglru: reduce folios pulled from the oldest gen in inc_min_seq() Barry Song (Xiaomi)

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=20260812121658.69965-3-baohua@kernel.org \
    --to=baohua@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=axelrasmussen@google.com \
    --cc=baolin.wang@linux.alibaba.com \
    --cc=baoquan.he@linux.dev \
    --cc=chenridong@xiaomi.com \
    --cc=david@kernel.org \
    --cc=hannes@cmpxchg.org \
    --cc=kasong@tencent.com \
    --cc=lianux.mm@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=lyugaofei@xiaomi.com \
    --cc=mhocko@kernel.org \
    --cc=qi.zheng@linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=stevensd@chromium.org \
    --cc=wangzicheng@honor.com \
    --cc=weixugc@google.com \
    --cc=yuanchu@google.com \
    --cc=zhangbo56@xiaomi.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