[PATCH v2 6/7] mm/mglru: move folios from oldest gen to second-oldest gen from head to tail

From: Barry Song (Xiaomi)

Date: Thu Aug 27 2026 - 19:50:02 EST


For reclamation, it makes sense to reclaim folios from tail to
head, as folios near the head are relatively hot. However, when
moving folios from the oldest generation to the second-oldest
generation, using the tail-to-head order would effectively cause
a cold/hot inversion.

Signed-off-by: Barry Song (Xiaomi) <baohua@xxxxxxxxxx>
Reviewed-by: Baoquan He <baoquan.he@xxxxxxxxx>
Tested-by: Xueyuan Chen <xueyuan.chen21@xxxxxxxxx>
---
mm/vmscan.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)

diff --git a/mm/vmscan.c b/mm/vmscan.c
index 81f95a968447..17524e96fe64 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -192,11 +192,27 @@ static inline void prefetchw_prev_lru_folio(struct folio *folio,
prefetchw(&prev->flags);
}
}
+
+static inline void prefetchw_next_lru_folio(struct folio *folio,
+ struct list_head *base)
+{
+ if (folio->lru.next != base) {
+ struct folio *next;
+
+ next = list_entry(folio->lru.next, struct folio, lru);
+ prefetchw(&next->flags);
+ }
+}
#else
static inline void prefetchw_prev_lru_folio(struct folio *folio,
struct list_head *base)
{
}
+
+static inline void prefetchw_next_lru_folio(struct folio *folio,
+ struct list_head *base)
+{
+}
#endif

/*
@@ -3938,10 +3954,11 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
/* prevent cold/hot inversion if the type is evictable */
for (zone = 0; zone < MAX_NR_ZONES; zone++) {
struct list_head *head = &lrugen->folios[old_gen][type][zone];
+ struct list_head *pos = head->next;
long delta = 0;

- while (!list_empty(head)) {
- struct folio *folio = lru_to_folio(head);
+ while (pos != head) {
+ struct folio *folio = list_entry(pos, struct folio, lru);
long nr_pages = folio_nr_pages(folio);
int refs = folio_lru_refs(folio);
bool workingset = folio_test_workingset(folio);
@@ -3952,6 +3969,8 @@ static bool inc_min_seq(struct lruvec *lruvec, int type, int swappiness)
VM_WARN_ON_ONCE_FOLIO(folio_is_file_lru(folio) != type, folio);
VM_WARN_ON_ONCE_FOLIO(folio_zonenum(folio) != zone, folio);

+ prefetchw_next_lru_folio(folio, head);
+ pos = pos->next;
new_gen = __folio_inc_gen(folio, old_gen, &gen_increased);
if (gen_increased) {
delta += nr_pages;
--
2.34.1