| From 60295b944ff6805e677c48ae4178532b207d43be Mon Sep 17 00:00:00 2001 |
| From: Steven Rostedt <rostedt@goodmis.org> |
| Date: Thu, 16 Jan 2025 16:41:24 -0500 |
| Subject: tracing: gfp: Fix the GFP enum values shown for user space tracing tools |
| |
| From: Steven Rostedt <rostedt@goodmis.org> |
| |
| commit 60295b944ff6805e677c48ae4178532b207d43be upstream. |
| |
| Tracing tools like perf and trace-cmd read the /sys/kernel/tracing/events/*/*/format |
| files to know how to parse the data and also how to print it. For the |
| "print fmt" portion of that file, if anything uses an enum that is not |
| exported to the tracing system, user space will not be able to parse it. |
| |
| The GFP flags use to be defines, and defines get translated in the print |
| fmt sections. But now they are converted to use enums, which is not. |
| |
| The mm_page_alloc trace event format use to have: |
| |
| print fmt: "page=%p pfn=0x%lx order=%d migratetype=%d gfp_flags=%s", |
| REC->pfn != -1UL ? (((struct page *)vmemmap_base) + (REC->pfn)) : ((void |
| *)0), REC->pfn != -1UL ? REC->pfn : 0, REC->order, REC->migratetype, |
| (REC->gfp_flags) ? __print_flags(REC->gfp_flags, "|", {( unsigned |
| long)(((((((( gfp_t)(0x400u|0x800u)) | (( gfp_t)0x40u) | (( gfp_t)0x80u) | |
| (( gfp_t)0x100000u)) | (( gfp_t)0x02u)) | (( gfp_t)0x08u) | (( gfp_t)0)) | |
| (( gfp_t)0x40000u) | (( gfp_t)0x80000u) | (( gfp_t)0x2000u)) & ~(( |
| gfp_t)(0x400u|0x800u))) | (( gfp_t)0x400u)), "GFP_TRANSHUGE"}, {( unsigned |
| long)((((((( gfp_t)(0x400u|0x800u)) | (( gfp_t)0x40u) | (( gfp_t)0x80u) | |
| (( gfp_t)0x100000u)) | (( gfp_t)0x02u)) | (( gfp_t)0x08u) | (( gfp_t)0)) ... |
| |
| Where the GFP values are shown and not their names. But after the GFP |
| flags were converted to use enums, it has: |
| |
| print fmt: "page=%p pfn=0x%lx order=%d migratetype=%d gfp_flags=%s", |
| REC->pfn != -1UL ? (vmemmap + (REC->pfn)) : ((void *)0), REC->pfn != -1UL |
| ? REC->pfn : 0, REC->order, REC->migratetype, (REC->gfp_flags) ? |
| __print_flags(REC->gfp_flags, "|", {( unsigned long)(((((((( |
| gfp_t)(((((1UL))) << (___GFP_DIRECT_RECLAIM_BIT))|((((1UL))) << |
| (___GFP_KSWAPD_RECLAIM_BIT)))) | (( gfp_t)((((1UL))) << (___GFP_IO_BIT))) |
| | (( gfp_t)((((1UL))) << (___GFP_FS_BIT))) | (( gfp_t)((((1UL))) << |
| (___GFP_HARDWALL_BIT)))) | (( gfp_t)((((1UL))) << (___GFP_HIGHMEM_BIT)))) |
| | (( gfp_t)((((1UL))) << (___GFP_MOVABLE_BIT))) | (( gfp_t)0)) | (( |
| gfp_t)((((1UL))) << (___GFP_COMP_BIT))) ... |
| |
| Where the enums names like ___GFP_KSWAPD_RECLAIM_BIT are shown and not their |
| values. User space has no way to convert these names to their values and |
| the output will fail to parse. What is shown is now: |
| |
| mm_page_alloc: page=0xffffffff981685f3 pfn=0x1d1ac1 order=0 migratetype=1 gfp_flags=0x140cca |
| |
| The TRACE_DEFINE_ENUM() macro was created to handle enums in the print fmt |
| files. This causes them to be replaced at boot up with the numbers, so |
| that user space tooling can parse it. By using this macro, the output is |
| back to the human readable: |
| |
| mm_page_alloc: page=0xffffffff981685f3 pfn=0x122233 order=0 migratetype=1 gfp_flags=GFP_HIGHUSER_MOVABLE|__GFP_COMP |
| |
| Cc: stable@vger.kernel.org |
| Cc: Masami Hiramatsu <mhiramat@kernel.org> |
| Cc: Mark Rutland <mark.rutland@arm.com> |
| Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> |
| Cc: Andrew Morton <akpm@linux-foundation.org> |
| Cc: Veronika Molnarova <vmolnaro@redhat.com> |
| Cc: Suren Baghdasaryan <surenb@google.com> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Link: https://lore.kernel.org/20250116214438.749504792@goodmis.org |
| Reported-by: Michael Petlan <mpetlan@redhat.com> |
| Closes: https://lore.kernel.org/all/87be5f7c-1a0-dad-daa0-54e342efaea7@redhat.com/ |
| Fixes: 772dd0342727c ("mm: enumerate all gfp flags") |
| Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| include/trace/events/mmflags.h | 63 ++++++++++++++++++++++++++++++++++ |
| 1 file changed, 63 insertions(+) |
| |
| diff --git a/include/trace/events/mmflags.h b/include/trace/events/mmflags.h |
| index bb8a59c6caa2..d36c857dd249 100644 |
| --- a/include/trace/events/mmflags.h |
| +++ b/include/trace/events/mmflags.h |
| @@ -13,6 +13,69 @@ |
| * Thus most bits set go first. |
| */ |
| |
| +/* These define the values that are enums (the bits) */ |
| +#define TRACE_GFP_FLAGS_GENERAL \ |
| + TRACE_GFP_EM(DMA) \ |
| + TRACE_GFP_EM(HIGHMEM) \ |
| + TRACE_GFP_EM(DMA32) \ |
| + TRACE_GFP_EM(MOVABLE) \ |
| + TRACE_GFP_EM(RECLAIMABLE) \ |
| + TRACE_GFP_EM(HIGH) \ |
| + TRACE_GFP_EM(IO) \ |
| + TRACE_GFP_EM(FS) \ |
| + TRACE_GFP_EM(ZERO) \ |
| + TRACE_GFP_EM(DIRECT_RECLAIM) \ |
| + TRACE_GFP_EM(KSWAPD_RECLAIM) \ |
| + TRACE_GFP_EM(WRITE) \ |
| + TRACE_GFP_EM(NOWARN) \ |
| + TRACE_GFP_EM(RETRY_MAYFAIL) \ |
| + TRACE_GFP_EM(NOFAIL) \ |
| + TRACE_GFP_EM(NORETRY) \ |
| + TRACE_GFP_EM(MEMALLOC) \ |
| + TRACE_GFP_EM(COMP) \ |
| + TRACE_GFP_EM(NOMEMALLOC) \ |
| + TRACE_GFP_EM(HARDWALL) \ |
| + TRACE_GFP_EM(THISNODE) \ |
| + TRACE_GFP_EM(ACCOUNT) \ |
| + TRACE_GFP_EM(ZEROTAGS) |
| + |
| +#ifdef CONFIG_KASAN_HW_TAGS |
| +# define TRACE_GFP_FLAGS_KASAN \ |
| + TRACE_GFP_EM(SKIP_ZERO) \ |
| + TRACE_GFP_EM(SKIP_KASAN) |
| +#else |
| +# define TRACE_GFP_FLAGS_KASAN |
| +#endif |
| + |
| +#ifdef CONFIG_LOCKDEP |
| +# define TRACE_GFP_FLAGS_LOCKDEP \ |
| + TRACE_GFP_EM(NOLOCKDEP) |
| +#else |
| +# define TRACE_GFP_FLAGS_LOCKDEP |
| +#endif |
| + |
| +#ifdef CONFIG_SLAB_OBJ_EXT |
| +# define TRACE_GFP_FLAGS_SLAB \ |
| + TRACE_GFP_EM(NO_OBJ_EXT) |
| +#else |
| +# define TRACE_GFP_FLAGS_SLAB |
| +#endif |
| + |
| +#define TRACE_GFP_FLAGS \ |
| + TRACE_GFP_FLAGS_GENERAL \ |
| + TRACE_GFP_FLAGS_KASAN \ |
| + TRACE_GFP_FLAGS_LOCKDEP \ |
| + TRACE_GFP_FLAGS_SLAB |
| + |
| +#undef TRACE_GFP_EM |
| +#define TRACE_GFP_EM(a) TRACE_DEFINE_ENUM(___GFP_##a##_BIT); |
| + |
| +TRACE_GFP_FLAGS |
| + |
| +/* Just in case these are ever used */ |
| +TRACE_DEFINE_ENUM(___GFP_UNUSED_BIT); |
| +TRACE_DEFINE_ENUM(___GFP_LAST_BIT); |
| + |
| #define gfpflag_string(flag) {(__force unsigned long)flag, #flag} |
| |
| #define __def_gfpflag_names \ |
| -- |
| 2.48.1 |
| |