From: xu xin Add trace_rmap_walk_start() and trace_rmap_walk_end() to bracket reverse mapping walks. Unlike manual clock sampling, these tracepoints record no timestamp; latency can be computed offline by tools (e.g., perf, trace-cmd) using the event timestamps. When tracepoints are disabled, the only cost is a static branch check (no clock read, no duration calculation), making them suitable for production use. The information (folio type, locked state) helps diagnose performance issues in KSM, anonymous, and file-backed rmap walks. Signed-off-by: xu xin --- include/trace/events/rmap.h | 67 +++++++++++++++++++++++++++++++++++++ mm/rmap.c | 9 +++++ 2 files changed, 76 insertions(+) create mode 100644 include/trace/events/rmap.h diff --git a/include/trace/events/rmap.h b/include/trace/events/rmap.h new file mode 100644 index 000000000000..55a319ba6235 --- /dev/null +++ b/include/trace/events/rmap.h @@ -0,0 +1,67 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#undef TRACE_SYSTEM +#define TRACE_SYSTEM rmap + +#if !defined(_TRACE_RMAP_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_RMAP_H + +#include +#include + +#define GET_RMAP_PAGE_TYPE(folio) (folio_test_ksm(folio) ? "ksm" : \ + (folio_test_anon(folio) ? "anon" : "file")) + +/** + * rmap_walk_template - called for start / stop of rmap_walk. + */ +DECLARE_EVENT_CLASS(rmap_walk_template, + + TP_PROTO(struct folio *folio, struct rmap_walk_control *rwc, bool locked), + + TP_ARGS(folio, rwc, locked), + + TP_STRUCT__entry( + __field(unsigned long, folio_addr) + __field(unsigned long, rwc_addr) + __string(page_type, GET_RMAP_PAGE_TYPE(folio)) + __field(bool, locked) + ), + + TP_fast_assign( + __entry->folio_addr = (unsigned long)folio; + __entry->rwc_addr = (unsigned long)rwc; + __assign_str(page_type); + __entry->locked = locked; + ), + + TP_printk("folio=%p rwc=%p page_type=%s locked=%s", + (void *)(unsigned long)__entry->folio_addr, + (void *)(unsigned long)__entry->rwc_addr, + __get_str(page_type), + __entry->locked ? "true" : "false") + +); + +/** + * rmap_walk_start - called before a folio is rmapped. + */ +DEFINE_EVENT(rmap_walk_template, rmap_walk_start, + + TP_PROTO(struct folio *folio, struct rmap_walk_control *rwc, bool locked), + + TP_ARGS(folio, rwc, locked) +); + +DEFINE_EVENT(rmap_walk_template, rmap_walk_end, + + TP_PROTO(struct folio *folio, struct rmap_walk_control *rwc, bool locked), + + TP_ARGS(folio, rwc, locked) +); + + +#endif /* _TRACE_RMAP_H */ + +/* This part must be outside protection */ +#include + diff --git a/mm/rmap.c b/mm/rmap.c index 78b7fb5f367c..52f795f768e1 100644 --- a/mm/rmap.c +++ b/mm/rmap.c @@ -80,6 +80,7 @@ #define CREATE_TRACE_POINTS #include +#include #include "internal.h" #include "swap.h" @@ -3098,23 +3099,31 @@ static void rmap_walk_file(struct folio *folio, void rmap_walk(struct folio *folio, struct rmap_walk_control *rwc) { + trace_rmap_walk_start(folio, rwc, false); + if (unlikely(folio_test_ksm(folio))) rmap_walk_ksm(folio, rwc); else if (folio_test_anon(folio)) rmap_walk_anon(folio, rwc, false); else rmap_walk_file(folio, rwc, false); + + trace_rmap_walk_end(folio, rwc, false); } /* Like rmap_walk, but caller holds relevant rmap lock */ void rmap_walk_locked(struct folio *folio, struct rmap_walk_control *rwc) { + trace_rmap_walk_start(folio, rwc, true); + /* no ksm support for now */ VM_BUG_ON_FOLIO(folio_test_ksm(folio), folio); if (folio_test_anon(folio)) rmap_walk_anon(folio, rwc, true); else rmap_walk_file(folio, rwc, true); + + trace_rmap_walk_end(folio, rwc, true); } #ifdef CONFIG_HUGETLB_PAGE -- 2.25.1