On 11/3/2026 2:48 PM, Barry Song wrote:
On Tue, Nov 3, 2026 at 10:58 AM Ridong Chen <[email protected]> wrote:
From: Ridong Chen <[email protected]>
Aging in MGLRU advances max_seq via inc_max_seq(), creating a new
youngest generation. There is currently no tracepoint on this path, so
the moment a new generation is created, and how the min_seq of each type
trails behind it, cannot be observed as it happens.
We might be more interested in why aging is triggered rather
than the exact moment when max_seq is advanced.
With your patch, we get:
~ # cat /sys/kernel/tracing/trace | grep mglru_inc_max_seq
a.out-93 [001] d..1. 278.276539:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=4 anon_min_seq=2
file_min_seq=1 nr_anon={0x0,0xf016,0x12,0x0}
nr_file={0x1886,0xb,0x4c,0x0}
kswapd0-50 [000] d..1. 278.422400:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=5 anon_min_seq=2
file_min_seq=2 nr_anon={0x5,0xccb6,0x3439,0x0}
nr_file={0x4ae,0x4f,0x55,0x0}
kswapd0-50 [000] d..1. 278.508003:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=6 anon_min_seq=3
file_min_seq=4 nr_anon={0xccb6,0x3d29,0x1,0x0}
nr_file={0x0,0x59,0x7,0x0}
kswapd0-50 [000] d..1. 280.046056:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=7 anon_min_seq=4
file_min_seq=5 nr_anon={0x3bf3,0xcbbd,0x23e,0x0}
nr_file={0x0,0xb,0x1,0x0}
kswapd0-50 [000] d..1. 280.124876:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=8 anon_min_seq=5
file_min_seq=6 nr_anon={0xcafd,0x3e31,0x0,0x0}
nr_file={0x0,0x5,0x7,0x0}
a.out-96 [001] d..1. 290.629014:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=9 anon_min_seq=7
file_min_seq=6 nr_anon={0x0,0x10615,0xb,0x0}
nr_file={0x331,0xb,0x9a,0x0}
kswapd0-50 [000] d..1. 290.653098:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=10 anon_min_seq=7
file_min_seq=7 nr_anon={0x15,0xef23,0x18c4,0x0}
nr_file={0xb,0xb8,0x55,0x0}
a.out-96 [001] d..1. 290.684875:
mm_mglru_inc_max_seq: nid=0 memcg_id=1 max_seq=11 anon_min_seq=8
file_min_seq=9 nr_anon={0xeee3,0x1afb,0x2,0x0}
nr_file={0x0,0x76,0x4,0x0}
You can see that the youngest generation is always zero,
because you're just getting the newly added youngest
generation :-)
Hi Barry,
Thank you very much for testing and reviewing.
This somehow suggests that the information is redundant, as
there is always a zero there.
I suspect we'll need an additional tracepoint to show why
aging is triggered and at what sc->priority it happens.
But do you know why you trace the moment just after aging
is completed, rather than the reason why aging is needed?
My original goal was to pair it with mm_mglru_scan_folios, to see how
the aging window of each memcg moves. The per-generation anon/file
nr_pages were added following your suggestion on v1. I put it at the
end of inc_max_seq() because of the restart there, as max_seq and
min_seq are only final after that.
You make a very good point that the reason for aging is also
important. So I'd like to discuss which way is better:
1) Keep mm_mglru_inc_max_seq, and add another tracepoint at the aging
decision in try_to_shrink_lruvec(), reporting why aging is needed
and at what sc->priority.
2) Replace mm_mglru_inc_max_seq with a single tracepoint in
try_to_shrink_lruvec(), right before try_to_inc_max_seq(), reporting
the reason, sc->priority, swappiness, max_seq/min_seq and the
per-generation nr_pages before aging. The youngest generation is
not empty at that point, and the new window after aging can still
be seen from the following mm_mglru_scan_folios.
Which one do you prefer?
--
Best regards
Ridong