* [PATCH v4 1/9] mm/memcontrol: drop unused vmscan tracepoint include
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
@ 2026-10-19 3:52 ` Ridong Chen
2026-10-19 3:52 ` [PATCH v4 2/9] mm/vmscan: move vmscan tracepoints to a local header Ridong Chen
` (7 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 3:52 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
memcontrol.c includes <trace/events/vmscan.h> but does not use any of
the tracepoints or macros it defines: all tracepoints invoked here come
from memcg.h and writeback.h.
Drop it ahead of moving the vmscan trace header under mm/, after which
<trace/events/vmscan.h> will no longer exist.
No functional change.
Assisted-by: LLM
Acked-by: Muchun Song <muchun.song@linux.dev>
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/memcontrol.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/mm/memcontrol.c b/mm/memcontrol.c
index aad0498a7bd6..95c2322d4a6f 100644
--- a/mm/memcontrol.c
+++ b/mm/memcontrol.c
@@ -77,8 +77,6 @@
#include <trace/events/memcg.h>
#undef CREATE_TRACE_POINTS
-#include <trace/events/vmscan.h>
-
struct cgroup_subsys memory_cgrp_subsys __read_mostly;
EXPORT_SYMBOL(memory_cgrp_subsys);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 2/9] mm/vmscan: move vmscan tracepoints to a local header
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
2026-10-19 3:52 ` [PATCH v4 1/9] mm/memcontrol: drop unused vmscan tracepoint include Ridong Chen
@ 2026-10-19 3:52 ` Ridong Chen
2026-10-19 3:52 ` [PATCH v4 3/9] mm/vmscan: move struct scan_control to a dedicated header Ridong Chen
` (6 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 3:52 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
Move include/trace/events/vmscan.h to mm/trace_vmscan.h so that the
tracepoints can be extended to reference vmscan-internal structures such
as struct scan_control, which is not visible outside mm/. This mirrors
what several other subsystems already do with their trace headers (e.g.
fs/fuse/fuse_trace.h, fs/gfs2/trace_gfs2.h, fs/lockd/trace.h). As they
do, set TRACE_INCLUDE_PATH to "." and add mm/ to the include path of
vmscan.o, the only user that defines CREATE_TRACE_POINTS.
No functional change.
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
MAINTAINERS | 2 ++
mm/Makefile | 1 +
mm/shrinker.c | 2 +-
include/trace/events/vmscan.h => mm/trace_vmscan.h | 4 ++++
mm/vmscan.c | 2 +-
5 files changed, 9 insertions(+), 2 deletions(-)
rename include/trace/events/vmscan.h => mm/trace_vmscan.h (99%)
diff --git a/MAINTAINERS b/MAINTAINERS
index 6f1f35a017a6..c41af07e870e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17231,6 +17231,7 @@ F: Documentation/admin-guide/mm/multigen_lru.rst
F: Documentation/mm/multigen_lru.rst
F: include/linux/mm_inline.h
F: include/linux/mmzone.h
+F: mm/trace_vmscan.h
F: mm/vmscan.c
F: mm/workingset.c
@@ -17380,6 +17381,7 @@ R: Shakeel Butt <shakeel.butt@linux.dev>
R: Lorenzo Stoakes <ljs@kernel.org>
L: linux-mm@kvack.org
S: Maintained
+F: mm/trace_vmscan.h
F: mm/vmscan.c
F: mm/workingset.c
diff --git a/mm/Makefile b/mm/Makefile
index 2a3ec53d62ee..277b97f7f8d7 100644
--- a/mm/Makefile
+++ b/mm/Makefile
@@ -32,6 +32,7 @@ KCOV_INSTRUMENT_vmstat.o := n
KCOV_INSTRUMENT_failslab.o := n
CFLAGS_init-mm.o += -Wno-override-init
+CFLAGS_vmscan.o += -I$(src)
mmu-y := nommu.o
mmu-$(CONFIG_MMU) := highmem.o memory.o mincore.o \
diff --git a/mm/shrinker.c b/mm/shrinker.c
index 7ec2a9704f6f..3c3e87c4b61c 100644
--- a/mm/shrinker.c
+++ b/mm/shrinker.c
@@ -3,7 +3,7 @@
#include <linux/rwsem.h>
#include <linux/shrinker.h>
#include <linux/rculist.h>
-#include <trace/events/vmscan.h>
+#include "trace_vmscan.h"
#include "internal.h"
diff --git a/include/trace/events/vmscan.h b/mm/trace_vmscan.h
similarity index 99%
rename from include/trace/events/vmscan.h
rename to mm/trace_vmscan.h
index 8a872990b4be..ad90f0e9bf2e 100644
--- a/include/trace/events/vmscan.h
+++ b/mm/trace_vmscan.h
@@ -648,4 +648,8 @@ TRACE_EVENT(mm_vmscan_kswapd_clear_hopeless,
#endif /* _TRACE_VMSCAN_H */
/* This part must be outside protection */
+#undef TRACE_INCLUDE_FILE
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_FILE trace_vmscan
#include <trace/define_trace.h>
diff --git a/mm/vmscan.c b/mm/vmscan.c
index e82ba737c028..a3538484f8da 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -71,7 +71,7 @@
#include "swap.h"
#define CREATE_TRACE_POINTS
-#include <trace/events/vmscan.h>
+#include "trace_vmscan.h"
struct scan_control {
/* How many pages shrink_list() should reclaim */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 3/9] mm/vmscan: move struct scan_control to a dedicated header
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
2026-10-19 3:52 ` [PATCH v4 1/9] mm/memcontrol: drop unused vmscan tracepoint include Ridong Chen
2026-10-19 3:52 ` [PATCH v4 2/9] mm/vmscan: move vmscan tracepoints to a local header Ridong Chen
@ 2026-10-19 3:52 ` Ridong Chen
2026-10-19 3:52 ` [PATCH v4 4/9] mm/vmscan: pass scan_control to the reclaim-begin tracepoints Ridong Chen
` (5 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 3:52 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
The definition of struct scan_control has lived inline at the top of
mm/vmscan.c. Move it out to a new mm/vmscan.h so the reclaim-internal
state can be referenced from other reclaim translation units without
duplicating the definition.
The header uses an ordinary include guard and pulls in only what the
struct needs (nodemask_t, gfp_t and struct reclaim_state).
mm/trace_vmscan.h includes the new header directly so that any
translation unit pulling in the trace events (mm/vmscan.c, mm/shrinker.c)
sees the full definition of struct scan_control regardless of include
order.
No functional change.
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
MAINTAINERS | 2 +
mm/trace_vmscan.h | 2 +
mm/vmscan.c | 108 ------------------------------------------
mm/vmscan.h | 118 ++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 122 insertions(+), 108 deletions(-)
create mode 100644 mm/vmscan.h
diff --git a/MAINTAINERS b/MAINTAINERS
index c41af07e870e..9785aa2b9c6c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -17233,6 +17233,7 @@ F: include/linux/mm_inline.h
F: include/linux/mmzone.h
F: mm/trace_vmscan.h
F: mm/vmscan.c
+F: mm/vmscan.h
F: mm/workingset.c
MEMORY MANAGEMENT - MIGRATION
@@ -17383,6 +17384,7 @@ L: linux-mm@kvack.org
S: Maintained
F: mm/trace_vmscan.h
F: mm/vmscan.c
+F: mm/vmscan.h
F: mm/workingset.c
MEMORY MANAGEMENT - RMAP (REVERSE MAPPING)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index ad90f0e9bf2e..3917e1b62dfa 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -11,6 +11,8 @@
#include <linux/memcontrol.h>
#include <trace/events/mmflags.h>
+#include "vmscan.h"
+
#define RECLAIM_WB_ANON 0x0001u
#define RECLAIM_WB_FILE 0x0002u
#define RECLAIM_WB_MIXED 0x0010u
diff --git a/mm/vmscan.c b/mm/vmscan.c
index a3538484f8da..8b8f4049e278 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -73,114 +73,6 @@
#define CREATE_TRACE_POINTS
#include "trace_vmscan.h"
-struct scan_control {
- /* How many pages shrink_list() should reclaim */
- unsigned long nr_to_reclaim;
-
- /*
- * Nodemask of nodes allowed by the caller. If NULL, all nodes
- * are scanned.
- */
- const nodemask_t *nodemask;
-
- /*
- * The memory cgroup that hit its limit and as a result is the
- * primary target of this reclaim invocation.
- */
- struct mem_cgroup *target_mem_cgroup;
-
- /*
- * Scan pressure balancing between anon and file LRUs
- */
- unsigned long anon_cost;
- unsigned long file_cost;
-
- /* Swappiness value for proactive reclaim. Always use sc_swappiness()! */
- int *proactive_swappiness;
-
- /* Can active folios be deactivated as part of reclaim? */
-#define DEACTIVATE_ANON 1
-#define DEACTIVATE_FILE 2
- unsigned int may_deactivate:2;
- unsigned int force_deactivate:1;
- unsigned int skipped_deactivate:1;
-
- /* zone_reclaim_mode, boost reclaim */
- unsigned int may_writepage:1;
-
- /* zone_reclaim_mode */
- unsigned int may_unmap:1;
-
- /* zone_reclaim_mode, boost reclaim, cgroup restrictions */
- unsigned int may_swap:1;
-
- /* Not allow cache_trim_mode to be turned on as part of reclaim? */
- unsigned int no_cache_trim_mode:1;
-
- /* Has cache_trim_mode failed at least once? */
- unsigned int cache_trim_mode_failed:1;
-
- /* Proactive reclaim invoked by userspace */
- unsigned int proactive:1;
-
- /*
- * Cgroup memory below memory.low is protected as long as we
- * don't threaten to OOM. If any cgroup is reclaimed at
- * reduced force or passed over entirely due to its memory.low
- * setting (memcg_low_skipped), and nothing is reclaimed as a
- * result, then go back for one more cycle that reclaims the protected
- * memory (memcg_low_reclaim) to avert OOM.
- */
- unsigned int memcg_low_reclaim:1;
- unsigned int memcg_low_skipped:1;
-
- /* Shared cgroup tree walk failed, rescan the whole tree */
- unsigned int memcg_full_walk:1;
-
- unsigned int hibernation_mode:1;
-
- /* One of the zones is ready for compaction */
- unsigned int compaction_ready:1;
-
- /* There is easily reclaimable cold cache in the current node */
- unsigned int cache_trim_mode:1;
-
- /* The file folios on the current node are dangerously low */
- unsigned int file_is_tiny:1;
-
- /* Always discard instead of demoting to lower tier memory */
- unsigned int no_demotion:1;
-
- /* Allocation order */
- s8 order;
-
- /* Scan (total_size >> priority) pages at once */
- s8 priority;
-
- /* The highest zone to isolate folios for reclaim from */
- s8 reclaim_idx;
-
- /* This context's GFP mask */
- gfp_t gfp_mask;
-
- /* Incremented by the number of inactive pages that were scanned */
- unsigned long nr_scanned;
-
- /* Number of pages freed so far during a call to shrink_zones() */
- unsigned long nr_reclaimed;
-
- struct {
- unsigned int dirty;
- unsigned int congested;
- unsigned int writeback;
- unsigned int immediate;
- unsigned int taken;
- } nr;
-
- /* for recording the reclaimed slab by now */
- struct reclaim_state reclaim_state;
-};
-
#ifdef ARCH_HAS_PREFETCHW
static inline void prefetchw_prev_lru_folio(struct folio *folio,
struct list_head *base)
diff --git a/mm/vmscan.h b/mm/vmscan.h
new file mode 100644
index 000000000000..adb22e80d760
--- /dev/null
+++ b/mm/vmscan.h
@@ -0,0 +1,118 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _MM_VMSCAN_H
+#define _MM_VMSCAN_H
+
+#include <linux/gfp_types.h>
+#include <linux/nodemask.h>
+#include <linux/swap.h>
+#include <linux/types.h>
+
+struct scan_control {
+ /* How many pages shrink_list() should reclaim */
+ unsigned long nr_to_reclaim;
+
+ /*
+ * Nodemask of nodes allowed by the caller. If NULL, all nodes
+ * are scanned.
+ */
+ const nodemask_t *nodemask;
+
+ /*
+ * The memory cgroup that hit its limit and as a result is the
+ * primary target of this reclaim invocation.
+ */
+ struct mem_cgroup *target_mem_cgroup;
+
+ /*
+ * Scan pressure balancing between anon and file LRUs
+ */
+ unsigned long anon_cost;
+ unsigned long file_cost;
+
+ /* Swappiness value for proactive reclaim. Always use sc_swappiness()! */
+ int *proactive_swappiness;
+
+ /* Can active folios be deactivated as part of reclaim? */
+#define DEACTIVATE_ANON 1
+#define DEACTIVATE_FILE 2
+ unsigned int may_deactivate:2;
+ unsigned int force_deactivate:1;
+ unsigned int skipped_deactivate:1;
+
+ /* zone_reclaim_mode, boost reclaim */
+ unsigned int may_writepage:1;
+
+ /* zone_reclaim_mode */
+ unsigned int may_unmap:1;
+
+ /* zone_reclaim_mode, boost reclaim, cgroup restrictions */
+ unsigned int may_swap:1;
+
+ /* Not allow cache_trim_mode to be turned on as part of reclaim? */
+ unsigned int no_cache_trim_mode:1;
+
+ /* Has cache_trim_mode failed at least once? */
+ unsigned int cache_trim_mode_failed:1;
+
+ /* Proactive reclaim invoked by userspace */
+ unsigned int proactive:1;
+
+ /*
+ * Cgroup memory below memory.low is protected as long as we
+ * don't threaten to OOM. If any cgroup is reclaimed at
+ * reduced force or passed over entirely due to its memory.low
+ * setting (memcg_low_skipped), and nothing is reclaimed as a
+ * result, then go back for one more cycle that reclaims the protected
+ * memory (memcg_low_reclaim) to avert OOM.
+ */
+ unsigned int memcg_low_reclaim:1;
+ unsigned int memcg_low_skipped:1;
+
+ /* Shared cgroup tree walk failed, rescan the whole tree */
+ unsigned int memcg_full_walk:1;
+
+ unsigned int hibernation_mode:1;
+
+ /* One of the zones is ready for compaction */
+ unsigned int compaction_ready:1;
+
+ /* There is easily reclaimable cold cache in the current node */
+ unsigned int cache_trim_mode:1;
+
+ /* The file folios on the current node are dangerously low */
+ unsigned int file_is_tiny:1;
+
+ /* Always discard instead of demoting to lower tier memory */
+ unsigned int no_demotion:1;
+
+ /* Allocation order */
+ s8 order;
+
+ /* Scan (total_size >> priority) pages at once */
+ s8 priority;
+
+ /* The highest zone to isolate folios for reclaim from */
+ s8 reclaim_idx;
+
+ /* This context's GFP mask */
+ gfp_t gfp_mask;
+
+ /* Incremented by the number of inactive pages that were scanned */
+ unsigned long nr_scanned;
+
+ /* Number of pages freed so far during a call to shrink_zones() */
+ unsigned long nr_reclaimed;
+
+ struct {
+ unsigned int dirty;
+ unsigned int congested;
+ unsigned int writeback;
+ unsigned int immediate;
+ unsigned int taken;
+ } nr;
+
+ /* for recording the reclaimed slab by now */
+ struct reclaim_state reclaim_state;
+};
+
+#endif /* _MM_VMSCAN_H */
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 4/9] mm/vmscan: pass scan_control to the reclaim-begin tracepoints
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (2 preceding siblings ...)
2026-10-19 3:52 ` [PATCH v4 3/9] mm/vmscan: move struct scan_control to a dedicated header Ridong Chen
@ 2026-10-19 3:52 ` Ridong Chen
2026-10-19 3:52 ` [PATCH v4 5/9] mm/vmscan: pass scan_control to the LRU isolate/shrink tracepoints Ridong Chen
` (4 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 3:52 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
The reclaim-begin tracepoints describe the entry conditions of a reclaim
invocation, which struct scan_control already carries. Now that the struct
is visible from the trace header, pass sc directly and pick the fields out
in TP_fast_assign instead of spelling out gfp_mask and order at every
callsite.
No functional change. The tracefs event format (TP_STRUCT__entry and
TP_printk) is unchanged, so tracefs-based consumers are unaffected.
BPF programs attached via raw_tp/tp_btf see the new TP_PROTO and need
to be adjusted; tracepoints are not a stable ABI (see
Documentation/bpf/bpf_design_QA.rst).
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 24 ++++++++++++------------
mm/vmscan.c | 7 +++----
2 files changed, 15 insertions(+), 16 deletions(-)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index 3917e1b62dfa..db4590356845 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -178,9 +178,9 @@ TRACE_EVENT(mm_vmscan_wakeup_kswapd,
DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template,
- TP_PROTO(gfp_t gfp_flags, int order, struct mem_cgroup *memcg),
+ TP_PROTO(struct scan_control *sc, struct mem_cgroup *memcg),
- TP_ARGS(gfp_flags, order, memcg),
+ TP_ARGS(sc, memcg),
TP_STRUCT__entry(
__field( unsigned long, gfp_flags )
@@ -189,8 +189,8 @@ DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template,
),
TP_fast_assign(
- __entry->gfp_flags = (__force unsigned long)gfp_flags;
- __entry->order = order;
+ __entry->gfp_flags = (__force unsigned long)sc->gfp_mask;
+ __entry->order = sc->order;
__entry->memcg_id = mem_cgroup_id(memcg);
),
@@ -204,17 +204,17 @@ DECLARE_EVENT_CLASS(mm_vmscan_direct_reclaim_begin_template,
DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_direct_reclaim_begin,
- TP_PROTO(gfp_t gfp_flags, int order, struct mem_cgroup *memcg),
+ TP_PROTO(struct scan_control *sc, struct mem_cgroup *memcg),
- TP_ARGS(gfp_flags, order, memcg)
+ TP_ARGS(sc, memcg)
);
#ifdef CONFIG_MEMCG
DEFINE_EVENT(mm_vmscan_direct_reclaim_begin_template, mm_vmscan_memcg_reclaim_begin,
- TP_PROTO(gfp_t gfp_flags, int order, struct mem_cgroup *memcg),
+ TP_PROTO(struct scan_control *sc, struct mem_cgroup *memcg),
- TP_ARGS(gfp_flags, order, memcg)
+ TP_ARGS(sc, memcg)
);
#endif /* CONFIG_MEMCG */
@@ -551,9 +551,9 @@ TRACE_EVENT(mm_vmscan_lru_shrink_active,
TRACE_EVENT(mm_vmscan_node_reclaim_begin,
- TP_PROTO(int nid, int order, gfp_t gfp_flags),
+ TP_PROTO(int nid, struct scan_control *sc),
- TP_ARGS(nid, order, gfp_flags),
+ TP_ARGS(nid, sc),
TP_STRUCT__entry(
__field(int, nid)
@@ -563,8 +563,8 @@ TRACE_EVENT(mm_vmscan_node_reclaim_begin,
TP_fast_assign(
__entry->nid = nid;
- __entry->order = order;
- __entry->gfp_flags = (__force unsigned long)gfp_flags;
+ __entry->order = sc->order;
+ __entry->gfp_flags = (__force unsigned long)sc->gfp_mask;
),
TP_printk("nid=%d order=%d gfp_flags=%s",
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 8b8f4049e278..e064354ea24f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -6884,7 +6884,7 @@ unsigned long try_to_free_pages(struct zonelist *zonelist, int order,
return 1;
set_task_reclaim_state(current, &sc.reclaim_state);
- trace_mm_vmscan_direct_reclaim_begin(sc.gfp_mask, order, NULL);
+ trace_mm_vmscan_direct_reclaim_begin(&sc, NULL);
nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
@@ -6925,7 +6925,7 @@ unsigned long try_to_free_mem_cgroup_pages(struct mem_cgroup *memcg,
struct zonelist *zonelist = node_zonelist(numa_node_id(), sc.gfp_mask);
set_task_reclaim_state(current, &sc.reclaim_state);
- trace_mm_vmscan_memcg_reclaim_begin(sc.gfp_mask, 0, memcg);
+ trace_mm_vmscan_memcg_reclaim_begin(&sc, memcg);
noreclaim_flag = memalloc_noreclaim_save();
nr_reclaimed = do_try_to_free_pages(zonelist, &sc);
@@ -7881,8 +7881,7 @@ static unsigned long __node_reclaim(struct pglist_data *pgdat,
unsigned int noreclaim_flag;
unsigned long pflags;
- trace_mm_vmscan_node_reclaim_begin(pgdat->node_id, sc->order,
- sc->gfp_mask);
+ trace_mm_vmscan_node_reclaim_begin(pgdat->node_id, sc);
cond_resched();
if (!sc->proactive)
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 5/9] mm/vmscan: pass scan_control to the LRU isolate/shrink tracepoints
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (3 preceding siblings ...)
2026-10-19 3:52 ` [PATCH v4 4/9] mm/vmscan: pass scan_control to the reclaim-begin tracepoints Ridong Chen
@ 2026-10-19 3:52 ` Ridong Chen
2026-10-19 4:23 ` [PATCH v4 6/9] mm/vmscan: pass scan_control to mm_vmscan_reclaim_pages Ridong Chen
` (3 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 3:52 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
mm_vmscan_lru_isolate, mm_vmscan_lru_shrink_inactive and
mm_vmscan_lru_shrink_active spell out reclaim state (reclaim_idx, order,
priority) as individual arguments, all of which the caller already holds
in struct scan_control. Now that the struct is visible from the trace
header, pass sc directly and pick the fields out in TP_fast_assign.
No functional change. The tracefs event format (TP_STRUCT__entry and
TP_printk) is unchanged, so tracefs-based consumers are unaffected.
BPF programs attached via raw_tp/tp_btf see the new TP_PROTO and need
to be adjusted; tracepoints are not a stable ABI (see
Documentation/bpf/bpf_design_QA.rst).
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 31 +++++++++++++++----------------
mm/vmscan.c | 14 +++++++-------
2 files changed, 22 insertions(+), 23 deletions(-)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index db4590356845..b1b329039e14 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -350,15 +350,14 @@ TRACE_EVENT(mm_shrink_slab_end,
);
TRACE_EVENT(mm_vmscan_lru_isolate,
- TP_PROTO(int highest_zoneidx,
- int order,
- unsigned long nr_requested,
- unsigned long nr_scanned,
- unsigned long nr_skipped,
- unsigned long nr_taken,
- int lru),
+ TP_PROTO(struct scan_control *sc,
+ unsigned long nr_requested,
+ unsigned long nr_scanned,
+ unsigned long nr_skipped,
+ unsigned long nr_taken,
+ int lru),
- TP_ARGS(highest_zoneidx, order, nr_requested, nr_scanned, nr_skipped, nr_taken, lru),
+ TP_ARGS(sc, nr_requested, nr_scanned, nr_skipped, nr_taken, lru),
TP_STRUCT__entry(
__field(int, highest_zoneidx)
@@ -371,8 +370,8 @@ TRACE_EVENT(mm_vmscan_lru_isolate,
),
TP_fast_assign(
- __entry->highest_zoneidx = highest_zoneidx;
- __entry->order = order;
+ __entry->highest_zoneidx = sc->reclaim_idx;
+ __entry->order = sc->order;
__entry->nr_requested = nr_requested;
__entry->nr_scanned = nr_scanned;
__entry->nr_skipped = nr_skipped;
@@ -466,9 +465,9 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
TP_PROTO(int nid,
unsigned long nr_scanned, unsigned long nr_reclaimed,
- struct reclaim_stat *stat, int priority, int file),
+ struct reclaim_stat *stat, struct scan_control *sc, int file),
- TP_ARGS(nid, nr_scanned, nr_reclaimed, stat, priority, file),
+ TP_ARGS(nid, nr_scanned, nr_reclaimed, stat, sc, file),
TP_STRUCT__entry(
__field(int, nid)
@@ -498,7 +497,7 @@ TRACE_EVENT(mm_vmscan_lru_shrink_inactive,
__entry->nr_activate1 = stat->nr_activate[1];
__entry->nr_ref_keep = stat->nr_ref_keep;
__entry->nr_unmap_fail = stat->nr_unmap_fail;
- __entry->priority = priority;
+ __entry->priority = sc->priority;
__entry->reclaim_flags = trace_reclaim_flags(file);
),
@@ -517,9 +516,9 @@ TRACE_EVENT(mm_vmscan_lru_shrink_active,
TP_PROTO(int nid, unsigned long nr_taken,
unsigned long nr_active, unsigned long nr_deactivated,
- unsigned long nr_referenced, int priority, int file),
+ unsigned long nr_referenced, struct scan_control *sc, int file),
- TP_ARGS(nid, nr_taken, nr_active, nr_deactivated, nr_referenced, priority, file),
+ TP_ARGS(nid, nr_taken, nr_active, nr_deactivated, nr_referenced, sc, file),
TP_STRUCT__entry(
__field(int, nid)
@@ -537,7 +536,7 @@ TRACE_EVENT(mm_vmscan_lru_shrink_active,
__entry->nr_active = nr_active;
__entry->nr_deactivated = nr_deactivated;
__entry->nr_referenced = nr_referenced;
- __entry->priority = priority;
+ __entry->priority = sc->priority;
__entry->reclaim_flags = trace_reclaim_flags(file);
),
diff --git a/mm/vmscan.c b/mm/vmscan.c
index e064354ea24f..5d5eee757c61 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -1759,7 +1759,7 @@ static unsigned long isolate_lru_folios(unsigned long nr_to_scan,
}
}
*nr_scanned = total_scan;
- trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan,
+ trace_mm_vmscan_lru_isolate(sc, nr_to_scan,
total_scan, skipped, nr_taken, lru);
update_lru_sizes(lruvec, lru, nr_zone_taken);
return nr_taken;
@@ -2048,7 +2048,7 @@ static unsigned long shrink_inactive_list(unsigned long nr_to_scan,
handle_reclaim_writeback(nr_taken, pgdat, sc, &stat);
trace_mm_vmscan_lru_shrink_inactive(pgdat->node_id,
- nr_scanned, nr_reclaimed, &stat, sc->priority, file);
+ nr_scanned, nr_reclaimed, &stat, sc, file);
return nr_reclaimed;
}
@@ -2155,7 +2155,7 @@ static void shrink_active_list(unsigned long nr_to_scan,
mod_lruvec_state(lruvec, PGROTATE_ANON + file, nr_rotated);
trace_mm_vmscan_lru_shrink_active(pgdat->node_id, nr_taken, nr_activate,
- nr_deactivate, nr_rotated, sc->priority, file);
+ nr_deactivate, nr_rotated, sc, file);
}
static unsigned int reclaim_folio_list(struct list_head *folio_list,
@@ -4844,9 +4844,9 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
mod_lruvec_state(lruvec, item, isolated);
mod_lruvec_state(lruvec, PGREFILL, sorted);
mod_lruvec_state(lruvec, PGSCAN_ANON + type, isolated);
- trace_mm_vmscan_lru_isolate(sc->reclaim_idx, sc->order, nr_to_scan,
- scanned, skipped, isolated,
- type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON);
+ trace_mm_vmscan_lru_isolate(sc, nr_to_scan,
+ scanned, skipped, isolated,
+ type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON);
*isolatedp = isolated;
return scanned;
@@ -4988,7 +4988,7 @@ static int evict_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
if (isolated)
handle_reclaim_writeback(isolated, pgdat, sc, &stat);
trace_mm_vmscan_lru_shrink_inactive(pgdat->node_id,
- type_scanned, reclaimed, &stat, sc->priority,
+ type_scanned, reclaimed, &stat, sc,
type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON);
list_for_each_entry_safe_reverse(folio, next, &list, lru) {
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 6/9] mm/vmscan: pass scan_control to mm_vmscan_reclaim_pages
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (4 preceding siblings ...)
2026-10-19 3:52 ` [PATCH v4 5/9] mm/vmscan: pass scan_control to the LRU isolate/shrink tracepoints Ridong Chen
@ 2026-10-19 4:23 ` Ridong Chen
2026-10-19 4:23 ` [PATCH v4 7/9] mm/vmscan: pass scan_control to mm_vmscan_balance_pgdat_end Ridong Chen
` (2 subsequent siblings)
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 4:23 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
reclaim_folio_list() passes sc.nr_scanned to mm_vmscan_reclaim_pages as
a bare argument. Pass the enclosing struct scan_control instead and read
nr_scanned out in TP_fast_assign, consistent with the other reclaim
tracepoints. nr_reclaimed stays a separate argument: it is the return
value of shrink_folio_list(), which does not update sc->nr_reclaimed.
No functional change. The tracefs event format (TP_STRUCT__entry and
TP_printk) is unchanged, so tracefs-based consumers are unaffected.
BPF programs attached via raw_tp/tp_btf see the new TP_PROTO and need
to be adjusted; tracepoints are not a stable ABI (see
Documentation/bpf/bpf_design_QA.rst).
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 10 +++++-----
mm/vmscan.c | 2 +-
2 files changed, 6 insertions(+), 6 deletions(-)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index b1b329039e14..54168ad45f6e 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -418,11 +418,11 @@ TRACE_EVENT(mm_vmscan_write_folio,
TRACE_EVENT(mm_vmscan_reclaim_pages,
- TP_PROTO(int nid,
- unsigned long nr_scanned, unsigned long nr_reclaimed,
- struct reclaim_stat *stat),
+ TP_PROTO(int nid, struct scan_control *sc,
+ unsigned long nr_reclaimed,
+ struct reclaim_stat *stat),
- TP_ARGS(nid, nr_scanned, nr_reclaimed, stat),
+ TP_ARGS(nid, sc, nr_reclaimed, stat),
TP_STRUCT__entry(
__field(int, nid)
@@ -440,7 +440,7 @@ TRACE_EVENT(mm_vmscan_reclaim_pages,
TP_fast_assign(
__entry->nid = nid;
- __entry->nr_scanned = nr_scanned;
+ __entry->nr_scanned = sc->nr_scanned;
__entry->nr_reclaimed = nr_reclaimed;
__entry->nr_dirty = stat->nr_dirty;
__entry->nr_writeback = stat->nr_writeback;
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5d5eee757c61..4bb00371a67f 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -2178,7 +2178,7 @@ static unsigned int reclaim_folio_list(struct list_head *folio_list,
list_del(&folio->lru);
folio_putback_lru(folio);
}
- trace_mm_vmscan_reclaim_pages(pgdat->node_id, sc.nr_scanned, nr_reclaimed, &stat);
+ trace_mm_vmscan_reclaim_pages(pgdat->node_id, &sc, nr_reclaimed, &stat);
return nr_reclaimed;
}
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 7/9] mm/vmscan: pass scan_control to mm_vmscan_balance_pgdat_end
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (5 preceding siblings ...)
2026-10-19 4:23 ` [PATCH v4 6/9] mm/vmscan: pass scan_control to mm_vmscan_reclaim_pages Ridong Chen
@ 2026-10-19 4:23 ` Ridong Chen
2026-10-19 4:23 ` [PATCH v4 8/9] mm/mglru: add tracepoint for scan_folios() Ridong Chen
2026-10-19 4:23 ` [PATCH v4 9/9] mm/mglru: add tracepoint for inc_max_seq() Ridong Chen
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 4:23 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
balance_pgdat() passes sc.order and sc.nr_reclaimed to
mm_vmscan_balance_pgdat_end as bare arguments. Pass the enclosing
struct scan_control instead and read the fields out in TP_fast_assign,
consistent with the other reclaim tracepoints. highest_zoneidx stays a
separate argument: it is a balance_pgdat() parameter, and
sc.reclaim_idx may differ from it by the time the end event fires.
No functional change. The tracefs event format (TP_STRUCT__entry and
TP_printk) is unchanged, so tracefs-based consumers are unaffected.
BPF programs attached via raw_tp/tp_btf see the new TP_PROTO and need
to be adjusted; tracepoints are not a stable ABI (see
Documentation/bpf/bpf_design_QA.rst).
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 9 ++++-----
mm/vmscan.c | 3 +--
2 files changed, 5 insertions(+), 7 deletions(-)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index 54168ad45f6e..b2ad83e5f25e 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -124,10 +124,9 @@ TRACE_EVENT(mm_vmscan_balance_pgdat_begin,
TRACE_EVENT(mm_vmscan_balance_pgdat_end,
- TP_PROTO(int nid, int order, int highest_zoneidx,
- unsigned long nr_reclaimed),
+ TP_PROTO(int nid, struct scan_control *sc, int highest_zoneidx),
- TP_ARGS(nid, order, highest_zoneidx, nr_reclaimed),
+ TP_ARGS(nid, sc, highest_zoneidx),
TP_STRUCT__entry(
__field(int, nid)
@@ -138,9 +137,9 @@ TRACE_EVENT(mm_vmscan_balance_pgdat_end,
TP_fast_assign(
__entry->nid = nid;
- __entry->order = order;
+ __entry->order = sc->order;
__entry->highest_zoneidx = highest_zoneidx;
- __entry->nr_reclaimed = nr_reclaimed;
+ __entry->nr_reclaimed = sc->nr_reclaimed;
),
TP_printk("nid=%d order=%d highest_zoneidx=%-8s nr_reclaimed=%lu",
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 4bb00371a67f..5d699decaa28 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -7402,8 +7402,7 @@ static int balance_pgdat(pg_data_t *pgdat, int order, int highest_zoneidx)
psi_memstall_leave(&pflags);
set_task_reclaim_state(current, NULL);
- trace_mm_vmscan_balance_pgdat_end(pgdat->node_id, sc.order,
- highest_zoneidx, sc.nr_reclaimed);
+ trace_mm_vmscan_balance_pgdat_end(pgdat->node_id, &sc, highest_zoneidx);
/*
* Return the order kswapd stopped reclaiming at as
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 8/9] mm/mglru: add tracepoint for scan_folios()
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (6 preceding siblings ...)
2026-10-19 4:23 ` [PATCH v4 7/9] mm/vmscan: pass scan_control to mm_vmscan_balance_pgdat_end Ridong Chen
@ 2026-10-19 4:23 ` Ridong Chen
2026-10-19 4:23 ` [PATCH v4 9/9] mm/mglru: add tracepoint for inc_max_seq() Ridong Chen
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 4:23 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
MGLRU's scan_folios() emits the classic-LRU tracepoint
trace_mm_vmscan_lru_isolate(), which predates MGLRU. It reports the
scan/isolate counts and the LRU type, but carries no generation or
memcg context, so a trace of an MGLRU run cannot tell which memcg a
given scan belongs to, nor how far reclaim has progressed through the
generations.
Add mm_mglru_scan_folios next to it, reporting the same counters plus
nr_sorted (folios moved to a younger generation by sort_folio()) and
the context the classic tracepoint lacks: the node id and memcg id of
the lruvec, and the max_seq, tier and min_seq of the type being
scanned.
Now that struct scan_control is visible to the trace header, pass sc,
lruvec, type and tier straight in and derive everything else in
TP_fast_assign(), so nothing is computed at the call site when the
event is disabled. The int fields are grouped at the end of the entry
to avoid padding on 64-bit.
scan_folios() is the MGLRU-specific layer where folios are actually
scanned, so it has no classic-LRU counterpart. The existing tracepoint
is left unchanged.
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 66 +++++++++++++++++++++++++++++++++++++++++++++++
mm/vmscan.c | 2 ++
2 files changed, 68 insertions(+)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index b2ad83e5f25e..8148b8224422 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -392,6 +392,72 @@ TRACE_EVENT(mm_vmscan_lru_isolate,
__print_symbolic(__entry->lru, LRU_NAMES))
);
+#ifdef CONFIG_LRU_GEN
+TRACE_EVENT(mm_mglru_scan_folios,
+
+ TP_PROTO(struct lruvec *lruvec,
+ struct scan_control *sc,
+ unsigned long nr_requested,
+ unsigned long nr_scanned,
+ unsigned long nr_sorted,
+ unsigned long nr_skipped,
+ unsigned long nr_taken,
+ int type,
+ int tier),
+
+ TP_ARGS(lruvec, sc, nr_requested, nr_scanned, nr_sorted, nr_skipped,
+ nr_taken, type, tier),
+
+ TP_STRUCT__entry(
+ __field(u64, memcg_id)
+ __field(unsigned long, nr_requested)
+ __field(unsigned long, nr_scanned)
+ __field(unsigned long, nr_sorted)
+ __field(unsigned long, nr_skipped)
+ __field(unsigned long, nr_taken)
+ __field(unsigned long, max_seq)
+ __field(unsigned long, min_seq)
+ __field(int, nid)
+ __field(int, highest_zoneidx)
+ __field(int, order)
+ __field(int, lru)
+ __field(int, tier)
+ ),
+
+ TP_fast_assign(
+ __entry->memcg_id = mem_cgroup_id(lruvec_memcg(lruvec));
+ __entry->nr_requested = nr_requested;
+ __entry->nr_scanned = nr_scanned;
+ __entry->nr_sorted = nr_sorted;
+ __entry->nr_skipped = nr_skipped;
+ __entry->nr_taken = nr_taken;
+ __entry->max_seq = lruvec->lrugen.max_seq;
+ __entry->min_seq = lruvec->lrugen.min_seq[type];
+ __entry->nid = lruvec_pgdat(lruvec)->node_id;
+ __entry->highest_zoneidx = sc->reclaim_idx;
+ __entry->order = sc->order;
+ __entry->lru = type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON;
+ __entry->tier = tier;
+ ),
+
+ TP_printk("nid=%d memcg_id=%llu classzone=%d order=%d nr_requested=%lu nr_scanned=%lu nr_sorted=%lu nr_skipped=%lu nr_taken=%lu lru=%s max_seq=%lu tier=%d min_seq=%lu",
+ __entry->nid,
+ __entry->memcg_id,
+ __entry->highest_zoneidx,
+ __entry->order,
+ __entry->nr_requested,
+ __entry->nr_scanned,
+ __entry->nr_sorted,
+ __entry->nr_skipped,
+ __entry->nr_taken,
+ __print_symbolic(__entry->lru, LRU_NAMES),
+ __entry->max_seq,
+ __entry->tier,
+ __entry->min_seq)
+);
+
+#endif /* CONFIG_LRU_GEN */
+
TRACE_EVENT(mm_vmscan_write_folio,
TP_PROTO(struct folio *folio),
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 5d699decaa28..d459678c5ee5 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4847,6 +4847,8 @@ static int scan_folios(unsigned long nr_to_scan, struct lruvec *lruvec,
trace_mm_vmscan_lru_isolate(sc, nr_to_scan,
scanned, skipped, isolated,
type ? LRU_INACTIVE_FILE : LRU_INACTIVE_ANON);
+ trace_mm_mglru_scan_folios(lruvec, sc, nr_to_scan, scanned, sorted,
+ skipped, isolated, type, tier);
*isolatedp = isolated;
return scanned;
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread* [PATCH v4 9/9] mm/mglru: add tracepoint for inc_max_seq()
2026-10-19 3:44 [PATCH v4 0/9] mm/vmscan: move tracepoints to mm/ and add MGLRU tracepoints Ridong Chen
` (7 preceding siblings ...)
2026-10-19 4:23 ` [PATCH v4 8/9] mm/mglru: add tracepoint for scan_folios() Ridong Chen
@ 2026-10-19 4:23 ` Ridong Chen
8 siblings, 0 replies; 10+ messages in thread
From: Ridong Chen @ 2026-10-19 4:23 UTC (permalink / raw)
To: Steven Rostedt, Masami Hiramatsu, Andrew Morton, Johannes Weiner,
Michal Hocko, Roman Gushchin, Shakeel Butt, Dave Chinner
Cc: Mathieu Desnoyers, Muchun Song, Qi Zheng, David Hildenbrand,
Lorenzo Stoakes, Kairui Song, Barry Song, Axel Rasmussen,
Yuanchu Xie, Wei Xu, Baoquan He, Baolin Wang, linux-kernel,
linux-trace-kernel, linux-mm, cgroups, bpf, Ridong Chen,
Ridong Chen
From: Ridong Chen <chenridong@xiaomi.com>
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.
Add mm_mglru_inc_max_seq, emitted right after max_seq is bumped while
the lruvec lock is still held, with the node id, memcg id, the new
max_seq, the anon and file min_seq, and the number of pages in each
generation for both types, summed over zones and clamped to >= 0 the
same way the debugfs lru_gen file reports them. The nr_anon/nr_file
arrays are indexed by generation slot, so the emitted max_seq/min_seq
say which slot holds which seq. They are printed with __print_array(),
so the output is hex and its length follows MAX_NR_GENS automatically.
Only the lruvec is passed in; all of the above is collected in
TP_fast_assign(), so inc_max_seq() does no extra work when the event is
disabled. Paired with mm_mglru_scan_folios it makes the full
aging-to-eviction window observable per memcg.
Assisted-by: LLM
Signed-off-by: Ridong Chen <chenridong@xiaomi.com>
---
mm/trace_vmscan.h | 47 +++++++++++++++++++++++++++++++++++++++++++++++
mm/vmscan.c | 2 ++
2 files changed, 49 insertions(+)
diff --git a/mm/trace_vmscan.h b/mm/trace_vmscan.h
index 8148b8224422..cddf42b5849a 100644
--- a/mm/trace_vmscan.h
+++ b/mm/trace_vmscan.h
@@ -456,6 +456,53 @@ TRACE_EVENT(mm_mglru_scan_folios,
__entry->min_seq)
);
+TRACE_EVENT(mm_mglru_inc_max_seq,
+
+ TP_PROTO(struct lruvec *lruvec),
+
+ TP_ARGS(lruvec),
+
+ TP_STRUCT__entry(
+ __field(u64, memcg_id)
+ __field(unsigned long, max_seq)
+ __field(unsigned long, anon_min_seq)
+ __field(unsigned long, file_min_seq)
+ __array(unsigned long, nr_anon, MAX_NR_GENS)
+ __array(unsigned long, nr_file, MAX_NR_GENS)
+ __field(int, nid)
+ ),
+
+ TP_fast_assign(
+ struct lru_gen_folio *lrugen = &lruvec->lrugen;
+ int gen, zone;
+
+ __entry->memcg_id = mem_cgroup_id(lruvec_memcg(lruvec));
+ __entry->max_seq = lrugen->max_seq;
+ __entry->anon_min_seq = lrugen->min_seq[LRU_GEN_ANON];
+ __entry->file_min_seq = lrugen->min_seq[LRU_GEN_FILE];
+ /* summed over zones and clamped to >= 0, as debugfs lru_gen does */
+ for (gen = 0; gen < MAX_NR_GENS; gen++) {
+ __entry->nr_anon[gen] = 0;
+ __entry->nr_file[gen] = 0;
+ for (zone = 0; zone < MAX_NR_ZONES; zone++) {
+ __entry->nr_anon[gen] +=
+ max(lrugen->nr_pages[gen][LRU_GEN_ANON][zone], 0L);
+ __entry->nr_file[gen] +=
+ max(lrugen->nr_pages[gen][LRU_GEN_FILE][zone], 0L);
+ }
+ }
+ __entry->nid = lruvec_pgdat(lruvec)->node_id;
+ ),
+
+ TP_printk("nid=%d memcg_id=%llu max_seq=%lu anon_min_seq=%lu file_min_seq=%lu nr_anon=%s nr_file=%s",
+ __entry->nid,
+ __entry->memcg_id,
+ __entry->max_seq,
+ __entry->anon_min_seq,
+ __entry->file_min_seq,
+ __print_array(__entry->nr_anon, MAX_NR_GENS, sizeof(unsigned long)),
+ __print_array(__entry->nr_file, MAX_NR_GENS, sizeof(unsigned long)))
+);
#endif /* CONFIG_LRU_GEN */
TRACE_EVENT(mm_vmscan_write_folio,
diff --git a/mm/vmscan.c b/mm/vmscan.c
index d459678c5ee5..7b9b1aca5c88 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -4129,6 +4129,8 @@ static bool inc_max_seq(struct lruvec *lruvec, unsigned long seq, int swappiness
WRITE_ONCE(lrugen->timestamps[next], jiffies);
/* make sure preceding modifications appear */
smp_store_release(&lrugen->max_seq, lrugen->max_seq + 1);
+
+ trace_mm_mglru_inc_max_seq(lruvec);
unlock:
lruvec_unlock_irq(lruvec);
--
2.34.1
^ permalink raw reply [flat|nested] 10+ messages in thread