[PATCH RFC 25/32] mm/workingset, lru_gen: simplify lru_gen recent
From: Kairui Song via B4 Relay
Date: Fri May 01 2026 - 17:07:10 EST
From: Kairui Song <kasong@xxxxxxxxxxx>
Move the commont part in the common caller. Also let it return early if
the memcg doesn't match.
Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
mm/workingset.c | 55 ++++++++++++++++++++++++++-----------------------------
1 file changed, 26 insertions(+), 29 deletions(-)
diff --git a/mm/workingset.c b/mm/workingset.c
index a77a6c0c3e15..b472ac34943e 100644
--- a/mm/workingset.c
+++ b/mm/workingset.c
@@ -277,44 +277,41 @@ static void *lru_gen_eviction(struct folio *folio)
/*
* Tests if the shadow entry is for a folio that was recently evicted.
- * Fills in @lruvec, @token, @workingset with the values unpacked from shadow.
*/
-static bool lru_gen_test_recent(void *shadow, struct lruvec **lruvec,
- unsigned long *token, bool *workingset, bool file)
+static bool lru_gen_test_recent(struct lruvec *lruvec,
+ unsigned long token, bool file)
{
- int memcg_id;
unsigned long max_seq;
- struct mem_cgroup *memcg;
- struct pglist_data *pgdat;
-
- unpack_shadow(shadow, &memcg_id, &pgdat, token, workingset);
- memcg = mem_cgroup_from_private_id(memcg_id);
- *lruvec = mem_cgroup_lruvec(memcg, pgdat);
-
- max_seq = READ_ONCE((*lruvec)->lrugen.max_seq);
+ max_seq = READ_ONCE((lruvec)->lrugen.max_seq);
max_seq &= (file ? EVICTION_MASK : EVICTION_MASK_ANON) >> LRU_REFS_BITS;
- return abs_diff(max_seq, *token >> LRU_REFS_BITS) < MAX_NR_GENS;
+ return abs_diff(max_seq, token >> LRU_REFS_BITS) < MAX_NR_GENS;
}
static void lru_gen_refault(struct folio *folio, void *shadow)
{
bool recent;
+ int memcg_id;
int hist, tier, refs;
bool workingset;
unsigned long token;
struct lruvec *lruvec;
+ struct mem_cgroup *memcg;
+ struct pglist_data *pgdat;
struct lru_gen_folio *lrugen;
int type = folio_is_file_lru(folio);
int delta = folio_nr_pages(folio);
- rcu_read_lock();
+ unpack_shadow(shadow, &memcg_id, &pgdat, &token, &workingset);
- recent = lru_gen_test_recent(shadow, &lruvec, &token, &workingset, type);
+ rcu_read_lock();
+ memcg = mem_cgroup_from_private_id(memcg_id);
+ lruvec = mem_cgroup_lruvec(memcg, pgdat);
if (lruvec != folio_lruvec(folio))
goto unlock;
+ recent = lru_gen_test_recent(lruvec, token, type);
mod_lruvec_state(lruvec, WORKINGSET_REFAULT_BASE + type, delta);
if (!recent)
@@ -347,8 +344,8 @@ static void *lru_gen_eviction(struct folio *folio)
return NULL;
}
-static bool lru_gen_test_recent(void *shadow, struct lruvec **lruvec,
- unsigned long *token, bool *workingset, bool file)
+static bool lru_gen_test_recent(struct lruvec *lruvec,
+ unsigned long token, bool file)
{
return false;
}
@@ -445,19 +442,8 @@ bool workingset_test_recent(void *shadow, bool file, bool *workingset,
unsigned long eviction;
int memcgid;
- if (lru_gen_enabled()) {
- bool recent;
-
- rcu_read_lock();
- recent = lru_gen_test_recent(shadow, &eviction_lruvec, &eviction,
- workingset, file);
- rcu_read_unlock();
- return recent;
- }
-
rcu_read_lock();
unpack_shadow(shadow, &memcgid, &pgdat, &eviction, workingset);
- eviction <<= bucket_order[file];
/*
* Look up the memcg associated with the stored ID. It might
@@ -482,6 +468,17 @@ bool workingset_test_recent(void *shadow, bool file, bool *workingset,
if (!mem_cgroup_disabled() && !eviction_memcg)
return false;
+
+ eviction_lruvec = mem_cgroup_lruvec(eviction_memcg, pgdat);
+
+ if (lru_gen_enabled()) {
+ bool recent;
+
+ recent = lru_gen_test_recent(eviction_lruvec, eviction, file);
+ mem_cgroup_put(eviction_memcg);
+ return recent;
+ }
+
/*
* Flush stats (and potentially sleep) outside the RCU read section.
*
@@ -495,7 +492,6 @@ bool workingset_test_recent(void *shadow, bool file, bool *workingset,
if (flush)
mem_cgroup_flush_stats_ratelimited(eviction_memcg);
- eviction_lruvec = mem_cgroup_lruvec(eviction_memcg, pgdat);
refault = atomic_long_read(&eviction_lruvec->evictions);
/*
@@ -514,6 +510,7 @@ bool workingset_test_recent(void *shadow, bool file, bool *workingset,
* longest time, so the occasional inappropriate activation
* leading to pressure on the active list is not a problem.
*/
+ eviction <<= bucket_order[file];
distance = ((refault - eviction) &
(file ? EVICTION_MASK : EVICTION_MASK_ANON));
--
2.54.0