[PATCH 3/7] mm/migrate: copy the referenced state via folio_migrate_refs()
From: Kairui Song via B4 Relay
Date: Tue Aug 18 2026 - 01:38:34 EST
From: Kairui Song <kasong@xxxxxxxxxxx>
folio_migrate_flags() copies PG_referenced separately, while
folio_migrate_refs() copies the rest of the reference state. Make
folio_migrate_refs() copy the complete state, i.e., PG_referenced plus
the MGLRU refs counter, in both LRU implementations, and drop the
open-coded copy so the reference state is transferred in one place.
Signed-off-by: Kairui Song <kasong@xxxxxxxxxxx>
---
include/linux/mm_inline.h | 16 +++++++++++++---
mm/migrate.c | 4 ++--
2 files changed, 15 insertions(+), 5 deletions(-)
diff --git a/include/linux/mm_inline.h b/include/linux/mm_inline.h
index 93bf3fa221f8..df62daaa2ee7 100644
--- a/include/linux/mm_inline.h
+++ b/include/linux/mm_inline.h
@@ -366,11 +366,19 @@ static inline bool lru_gen_del_folio(struct lruvec *lruvec, struct folio *folio,
return true;
}
+/**
+ * folio_migrate_refs - copy the reference state to a new folio
+ * @new: the destination folio
+ * @old: the source folio
+ *
+ * Transfer the reference state to @new during migration: the MGLRU
+ * refs count, including PG_referenced, or just PG_referenced for the
+ * active/inactive LRU.
+ */
static inline void folio_migrate_refs(struct folio *new, const struct folio *old)
{
- unsigned long refs = READ_ONCE(old->flags.f) & LRU_REFS_MASK;
-
- set_mask_bits(&new->flags.f, LRU_REFS_MASK, refs);
+ BUILD_BUG_ON(LRU_REFS_MASK & BIT(PG_referenced));
+ folio_set_lru_refs(new, folio_lru_refs(old));
}
#else /* !CONFIG_LRU_GEN */
@@ -401,6 +409,8 @@ static inline bool lru_gen_del_folio(struct lruvec *lruvec, struct folio *folio,
static inline void folio_migrate_refs(struct folio *new, const struct folio *old)
{
+ if (folio_test_referenced(old))
+ folio_set_referenced(new);
}
#endif /* CONFIG_LRU_GEN */
diff --git a/mm/migrate.c b/mm/migrate.c
index 15b45832bcfa..82307332711f 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -776,8 +776,6 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio)
{
int cpupid;
- if (folio_test_referenced(folio))
- folio_set_referenced(newfolio);
if (folio_test_uptodate(folio))
folio_mark_uptodate(newfolio);
if (folio_test_clear_active(folio)) {
@@ -807,7 +805,9 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio)
if (folio_test_idle(folio))
folio_set_idle(newfolio);
+ /* Copy the reference state, including PG_referenced */
folio_migrate_refs(newfolio, folio);
+
/*
* Copy NUMA information to the new page, to prevent over-eager
* future migrations of this same page.
--
2.55.0