[RFC PATCH v5 02/14] mm/mglru: extract lruvec_populated_min_seq() helper

From: Barry Song (Xiaomi)

Date: Thu Oct 22 2026 - 18:05:07 EST


From: Kairui Song <kasong@xxxxxxxxxxx>

The search for the oldest populated generation of a type, previously
embedded in try_to_inc_min_seq(), is extracted into the new
lruvec_populated_min_seq() helper. It returns the oldest populated seq
of a given type, bounded by the given max_seq so the search never goes
beyond it.

No functional change.

Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
Signed-off-by: Barry Song (Xiaomi) <baohua@xxxxxxxxxx>
---
mm/vmscan.c | 43 +++++++++++++++++++++++++++++--------------
1 file changed, 29 insertions(+), 14 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 3be0d6c04a82..500ef23949fd 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4131,30 +4131,45 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
return true;
}

+/* Similar to lruvec_evictable_size, return the oldest populated seq of the type */
+static unsigned long lruvec_populated_min_seq(struct lruvec *lruvec, int type,
+ unsigned long max_seq)
+{
+ int gen, zone;
+ unsigned long min_seq;
+ struct lru_gen_folio *lrugen = &lruvec->lrugen;
+
+ lockdep_assert_held(&lruvec->lru_lock);
+
+ min_seq = READ_ONCE(lrugen->min_seq[type]);
+ while (min_seq <= max_seq) {
+ gen = lru_gen_from_seq(min_seq);
+ for (zone = 0; zone < MAX_NR_ZONES; zone++) {
+ if (!list_empty(&lrugen->folios[gen][type][zone]))
+ return min_seq;
+ }
+ min_seq++;
+ }
+
+ return max_seq;
+}
+
static void try_to_inc_min_seq(struct lruvec *lruvec, int swappiness)
{
- int gen, type, zone;
+ int type;
bool seq_inc_flag = false;
struct lru_gen_folio *lrugen = &lruvec->lrugen;
DEFINE_MIN_SEQ(lruvec);
+ unsigned long seq;

VM_WARN_ON_ONCE(!seq_is_valid(lruvec));

- /* find the oldest populated generation */
+ /* Requires at least MIN_NR_GENS gens for basic functionality */
+ seq = lrugen->max_seq - MIN_NR_GENS;
for_each_evictable_type(type, swappiness) {
- while (min_seq[type] + MIN_NR_GENS <= lrugen->max_seq) {
- gen = lru_gen_from_seq(min_seq[type]);
-
- for (zone = 0; zone < MAX_NR_ZONES; zone++) {
- if (!list_empty(&lrugen->folios[gen][type][zone]))
- goto next;
- }
-
- min_seq[type]++;
+ min_seq[type] = lruvec_populated_min_seq(lruvec, type, seq + 1);
+ if (min_seq[type] > lrugen->min_seq[type])
seq_inc_flag = true;
- }
-next:
- ;
}

/*
--
2.34.1