[PATCH RFC v2 08/15] mm/smap: convert to LRU refs based operations

From: Kairui Song via B4 Relay

Date: Fri Sep 11 2026 - 08:07:38 EST


From: Kairui Song <kasong@xxxxxxxxxxx>

For MGLRU, switch smap to use the folio refs count API so smap will
report all folio with referenced count >= 1 as "Referenced". Current
smap checking PG_referenced is causing folios to flick between
referenced and not-reference status, because for both MGLRU and
active/inactive LRU, PG_referenced may got cleared on second access.
(Increase of LRU referenced times count for MGLRU, and movig to active
list active/inactive all clears that bit).

After this, we will have a more reliable and useful reading for MGLRU
after the FG change. The behavior is basically identical to what we had
before the series. And there is no behavior change for classical LRU.

Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
fs/proc/task_mmu.c | 22 +++++++++++++++++++---
1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index e671b4fd8ded..9cc47efbaa51 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -880,6 +880,22 @@ static void smaps_page_accumulate(struct mem_size_stats *mss,
}
}

+static bool smap_check_folio_referenced(struct folio *folio)
+{
+ if (lru_gen_enabled())
+ return folio_lru_refs(folio);
+ else
+ return folio_test_referenced(folio);
+}
+
+static void smap_clear_folio_referenced(struct folio *folio)
+{
+ if (lru_gen_enabled())
+ folio_set_lru_refs(folio, 0);
+ else
+ folio_clear_referenced(folio);
+}
+
static void smaps_account(struct mem_size_stats *mss, struct page *page,
bool compound, bool young, bool dirty, bool locked,
bool present)
@@ -906,7 +922,7 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,

mss->resident += size;
/* Accumulate the size in pages that have been accessed. */
- if (young || folio_test_young(folio) || folio_test_referenced(folio))
+ if (young || folio_test_young(folio) || smap_check_folio_referenced(folio))
mss->referenced += size;

/*
@@ -1709,7 +1725,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
/* Clear accessed and referenced bits. */
pmdp_test_and_clear_young(vma, addr, pmd);
folio_test_clear_young(folio);
- folio_clear_referenced(folio);
+ smap_clear_folio_referenced(folio);
out:
spin_unlock(ptl);
return 0;
@@ -1738,7 +1754,7 @@ static int clear_refs_pte_range(pmd_t *pmd, unsigned long addr,
/* Clear accessed and referenced bits. */
ptep_test_and_clear_young(vma, addr, pte);
folio_test_clear_young(folio);
- folio_clear_referenced(folio);
+ smap_clear_folio_referenced(folio);
}
pte_unmap_unlock(pte - 1, ptl);
cond_resched();

--
2.55.0