Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: "Barry Song (Xiaomi)" <baohua@kernel.org>
To: sashiko-bot@kernel.org
Cc: akpm@linux-foundation.org, axelrasmussen@google.com,
	baohua@kernel.org, baolin.wang@linux.alibaba.com,
	baoquan.he@linux.dev, hannes@cmpxchg.org, hui.zhu@linux.dev,
	kasong@tencent.com, kunwu.chan@gmail.com, liam@infradead.org,
	lianux.mm@gmail.com, linux-mm@kvack.org,
	liuxiang.277@bytedance.com, lyugaofei@xiaomi.com,
	mhocko@kernel.org, mhocko@suse.com, qi.zheng@linux.dev,
	ridong.chen@linux.dev, rppt@kernel.org, ryncsn@gmail.com,
	sashiko-reviews@lists.linux.dev, shakeel.butt@linux.dev,
	sidchintamaneni@gmail.com, surenb@google.com,
	wangzicheng@honor.com, weixugc@google.com, yuanchu@google.com,
	zhangbo56@xiaomi.com, zhuhui@kylinos.cn
Subject: Re: [PATCH v8 11/16] mm/mglru: Run aging when one type has no populatable folios
Date: Sat, 14 Nov 2026 16:49:03 +0800	[thread overview]
Message-ID: <20261114084904.91735-1-baohua@kernel.org> (raw)
In-Reply-To: <sashiko-outbox-214030@kernel.org>

On Sat, Nov 14, 2026 at 10:02 AM <sashiko-bot@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 2 potential
> issues to consider:
> - [High] mm/mglru: premature loop exit after aging in
>   try_to_shrink_lruvec()
> - [Medium] mm/mglru: late max_seq read in try_to_shrink_lruvec() causes
>   redundant aging
> --

We can add a bounded retry for this case, along with a concurrency
check to avoid concurrent aging mentioned above. Then I made the
patch as below:


Subject: [PATCH 11/16] mm/mglru: Run aging when one type has no populatable
 folios

We may have scan budget remaining for anon or file but no
folios in populatable generations to scan. In this case,
`scan_folios()` may waste time scanning that type while
the other type still has populatable folios.

Run aging in this case to make more folios populatable.
This also helps respect the scan budget distribution
determined by swappiness.

Move aging after eviction to detect a lack of scan progress
and avoid unnecessary aging when reclaim can already make progress.

To avoid excessive aging, allow no-populatable aging only once per
`try_to_shrink_lruvec()` invocation.

With extreme swappiness values such as 1 and 200, reclaim initially
focuses exclusively on the preferred type. Defer aging the lagging
type until sc->priority reaches DEF_PRIORITY / 2, where imbalanced
aging is allowed. This avoids unnecessary aging at extreme
swappiness values and has shown better performance in testing.

If evict_folio_lists() returns 0, retry once if aging has
successfully advanced the generation.

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

diff --git a/mm/vmscan.c b/mm/vmscan.c
index cb806ce0a8e6..d68fc456ca7b 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -5198,9 +5198,15 @@ static long evict_folio_lists(unsigned long nr_to_scan[], struct lruvec *lruvec,
 static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 {
 	unsigned long nr[ANON_AND_FILE];
-	bool need_rotate = false, should_age = false;
+	bool need_rotate = false, should_age = false, retried = false;
 	int swappiness = get_swappiness(lruvec, sc);
 	struct mem_cgroup *memcg = lruvec_memcg(lruvec);
+	/*
+	 * Avoid aging the lagging, unpreferred type at extreme swappiness;
+	 * rely on imbalanced aging once priority reaches DEF_PRIORITY / 2
+	 */
+	bool allow_no_populatable_age = (sc->priority < DEF_PRIORITY) &&
+		(swappiness > MIN_SWAPPINESS + 1 && swappiness < MAX_SWAPPINESS);
 
 	/*
 	 * Proactive reclaim initiated by userspace for anonymous memory only.
@@ -5218,22 +5224,19 @@ static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 	lru_gen_prepare_scan(lruvec, sc, memcg, swappiness, nr);
 
 	while (nr[LRU_GEN_ANON] > 0 || nr[LRU_GEN_FILE] > 0) {
+		unsigned long orig_file, orig_anon, new_seq;
 		DEFINE_MAX_SEQ(lruvec);
+		bool no_populatable;
+		long scanned;
 
 		if (mem_cgroup_below_min(sc->target_mem_cgroup, memcg)) {
 			need_rotate = true;
 			break;
 		}
 
-		if (should_run_aging(lruvec, max_seq, sc, swappiness)) {
-			trace_mm_mglru_aging(lruvec, sc, swappiness);
-			if (try_to_inc_max_seq(lruvec, max_seq, swappiness, false))
-				need_rotate = true;
-			should_age = true;
-		}
-
-		if (!evict_folio_lists(nr, lruvec, sc, swappiness, MIN_LRU_BATCH))
-			break;
+		orig_anon = nr[LRU_GEN_ANON];
+		orig_file = nr[LRU_GEN_FILE];
+		scanned = evict_folio_lists(nr, lruvec, sc, swappiness, MIN_LRU_BATCH);
 
 		if (should_abort_scan(lruvec, sc))
 			break;
@@ -5245,6 +5248,26 @@ static bool try_to_shrink_lruvec(struct lruvec *lruvec, struct scan_control *sc)
 		if (root_reclaim(sc) && should_age)
 			break;
 
+		/* Limit no_populatable aging to once per try_to_shrink_lruvec() */
+		new_seq = READ_ONCE(lruvec->lrugen.max_seq);
+		no_populatable = allow_no_populatable_age && max_seq == new_seq &&
+			((nr[LRU_GEN_ANON] && nr[LRU_GEN_ANON] == orig_anon) ||
+			(nr[LRU_GEN_FILE] && nr[LRU_GEN_FILE] == orig_file));
+		allow_no_populatable_age &= !no_populatable;
+		if (no_populatable || should_run_aging(lruvec, new_seq, sc, swappiness)) {
+			trace_mm_mglru_aging(lruvec, sc, swappiness);
+			if (try_to_inc_max_seq(lruvec, new_seq, swappiness, false))
+				need_rotate = true;
+			should_age = true;
+		}
+
+		if (!scanned) {
+			/* Retry once if aging advanced max_seq */
+			if (retried || new_seq == READ_ONCE(lruvec->lrugen.max_seq))
+				break;
+			retried = true;
+		}
+
 		cond_resched();
 	}
 
-- 
2.34.1


> In addition, calling evict_folio_lists() and should_abort_scan() before
> should_run_aging() causes scan_folios() at sc->priority <=
> DEF_PRIORITY / 2 to evict directly from max_seq before
> lru_gen_imbalanced() can age page tables to separate hot folios from cold
> ones, and skips aging altogether when the first batch satisfies
> should_abort_scan().

I think this is fine. We only reclaim a small batch of folios
(MIN_LRU_BATCH) before checking should_run_aging(). If reclaim
satisfies the request, we can avoid an unnecessary aging pass.

>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20261113185541.70203-1-baohua@kernel.org?part=11



  reply	other threads:[~2026-11-14  8:49 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-11-13 18:55 [PATCH v8 00/16] mm: mglru: fix swappiness behavior Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 01/16] mm/mglru: report evictable sizes per type Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 02/16] mm/mglru: extract lruvec_populated_min_seq() helper Barry Song (Xiaomi)
2026-11-14  2:02   ` sashiko-bot
2026-11-14  2:27     ` Barry Song
2026-11-14  8:27       ` Barry Song
2026-11-13 18:55 ` [PATCH v8 03/16] mm/mglru: reclaim from the oldest populated gen Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 04/16] mm/mglru: lift the forced protection of reclaimer Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 05/16] mm/mglru: skip zones above reclaim_idx instead of rotating them Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 06/16] mm/mglru: return for unavailable anon reclaim earlier Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 07/16] mm/mglru: balance anon and file scan budget by refault rate Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 08/16] mm/mglru: lift youngest gen protection for higher priority Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 09/16] mm/mglru: Avoid placing rejected folios below populated gen Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 10/16] mm/mglru: Run aging when pages are rare outside the youngest gen Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 11/16] mm/mglru: Run aging when one type has no populatable folios Barry Song (Xiaomi)
2026-11-14  2:02   ` sashiko-bot
2026-11-14  8:49     ` Barry Song (Xiaomi) [this message]
2026-11-13 18:55 ` [PATCH v8 12/16] mm/mglru: Restrict eviction accounting to eligible zones Barry Song (Xiaomi)
2026-11-14  2:02   ` sashiko-bot
2026-11-14  3:13     ` Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 13/16] mm/mglru: Reduce LRU lock contention by shrinking folio batches in inc_min_seq Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 14/16] mm/mglru: Avoid prolonged anon reclaim with swappiness=200 Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 15/16] mm/mglru: Make swappiness=1 file reclaim more aggressive Barry Song (Xiaomi)
2026-11-13 18:55 ` [PATCH v8 16/16] mm/mglru: Avoid scan anon while swapcache is low for GFP_NOIO allocation Barry Song (Xiaomi)
2026-11-13 19:50 ` [PATCH v8 00/16] mm: mglru: fix swappiness behavior Andrew Morton

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=20261114084904.91735-1-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=hannes@cmpxchg.org \
    --cc=hui.zhu@linux.dev \
    --cc=kasong@tencent.com \
    --cc=kunwu.chan@gmail.com \
    --cc=liam@infradead.org \
    --cc=lianux.mm@gmail.com \
    --cc=linux-mm@kvack.org \
    --cc=liuxiang.277@bytedance.com \
    --cc=lyugaofei@xiaomi.com \
    --cc=mhocko@kernel.org \
    --cc=mhocko@suse.com \
    --cc=qi.zheng@linux.dev \
    --cc=ridong.chen@linux.dev \
    --cc=rppt@kernel.org \
    --cc=ryncsn@gmail.com \
    --cc=sashiko-bot@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=shakeel.butt@linux.dev \
    --cc=sidchintamaneni@gmail.com \
    --cc=surenb@google.com \
    --cc=wangzicheng@honor.com \
    --cc=weixugc@google.com \
    --cc=yuanchu@google.com \
    --cc=zhangbo56@xiaomi.com \
    --cc=zhuhui@kylinos.cn \
    /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