include/linux/ftrace.h | 2 ++ kernel/trace/fgraph.c | 2 ++ kernel/trace/ftrace.c | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+)
From: Steven Rostedt <rostedt@goodmis.org>
The function graph infrastructure uses subops of the function tracer.
These are not shown in enabled_functions. Add a "subops:" section to the
enabled_functions line to show what functions are attached via subops. If
the subops is from the function_graph infrastructure, then show the entry
and return callbacks that are attached.
Here's an example of the output:
schedule_on_each_cpu (1) tramp: 0xffffffffc03ef000 (ftrace_graph_func+0x0/0x60) ->ftrace_graph_func+0x0/0x60 subops: {ent:trace_graph_entry+0x0/0x20 ret:trace_graph_return+0x0/0x150}
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
---
include/linux/ftrace.h | 2 ++
kernel/trace/fgraph.c | 2 ++
kernel/trace/ftrace.c | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
diff --git a/include/linux/ftrace.h b/include/linux/ftrace.h
index fbabc3d848b3..fc939ca2ff66 100644
--- a/include/linux/ftrace.h
+++ b/include/linux/ftrace.h
@@ -328,6 +328,7 @@ ftrace_func_t ftrace_ops_get_func(struct ftrace_ops *ops);
* DIRECT - Used by the direct ftrace_ops helper for direct functions
* (internal ftrace only, should not be used by others)
* SUBOP - Is controlled by another op in field managed.
+ * GRAPH - Is a component of the fgraph_ops structure
*/
enum {
FTRACE_OPS_FL_ENABLED = BIT(0),
@@ -349,6 +350,7 @@ enum {
FTRACE_OPS_FL_PERMANENT = BIT(16),
FTRACE_OPS_FL_DIRECT = BIT(17),
FTRACE_OPS_FL_SUBOP = BIT(18),
+ FTRACE_OPS_FL_GRAPH = BIT(19),
};
#ifndef CONFIG_DYNAMIC_FTRACE_WITH_ARGS
diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index 8d925cbdce3a..c5b207992fb4 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -1382,6 +1382,8 @@ int register_ftrace_graph(struct fgraph_ops *gops)
/* Always save the function, and reset at unregistering */
gops->saved_func = gops->entryfunc;
+ gops->ops.flags |= FTRACE_OPS_FL_GRAPH;
+
ret = ftrace_startup_subops(&graph_ops, &gops->ops, command);
if (!ret)
fgraph_array[i] = gops;
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 1a48aedb5255..cd62f5ab3dfe 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -4323,6 +4323,40 @@ static inline int print_rec(struct seq_file *m, unsigned long ip)
}
#endif
+static void print_subops(struct seq_file *m, struct ftrace_ops *ops, struct dyn_ftrace *rec)
+{
+ struct ftrace_ops *subops;
+ bool first = true;
+
+ list_for_each_entry(subops, &ops->subop_list, list) {
+ if (!((subops->flags & FTRACE_OPS_FL_ENABLED) &&
+ hash_contains_ip(rec->ip, subops->func_hash)))
+ continue;
+ if (first) {
+ seq_printf(m, "\tsubops:");
+ first = false;
+ }
+ if (subops->flags & FTRACE_OPS_FL_GRAPH) {
+ struct fgraph_ops *gops;
+
+ gops = container_of(subops, struct fgraph_ops, ops);
+ seq_printf(m, " {ent:%pS ret:%pS}",
+ (void *)gops->entryfunc,
+ (void *)gops->retfunc);
+ continue;
+ }
+ if (subops->trampoline) {
+ seq_printf(m, " {%pS (%pS)}",
+ (void *)subops->trampoline,
+ (void *)subops->func);
+ add_trampoline_func(m, subops, rec);
+ } else {
+ seq_printf(m, " {%pS}",
+ (void *)subops->func);
+ }
+ }
+}
+
static int t_show(struct seq_file *m, void *v)
{
struct ftrace_iterator *iter = m->private;
@@ -4375,6 +4409,7 @@ static int t_show(struct seq_file *m, void *v)
(void *)ops->trampoline,
(void *)ops->func);
add_trampoline_func(m, ops, rec);
+ print_subops(m, ops, rec);
ops = ftrace_find_tramp_ops_next(rec, ops);
} while (ops);
} else
@@ -4387,6 +4422,7 @@ static int t_show(struct seq_file *m, void *v)
if (ops) {
seq_printf(m, "\tops: %pS (%pS)",
ops, ops->func);
+ print_subops(m, ops, rec);
} else {
seq_puts(m, "\tops: ERROR!");
}
--
2.47.2
Hi Steven, kernel test robot noticed the following build errors: [auto build test ERROR on trace/for-next] [also build test ERROR on linus/master v6.15-rc1 next-20250410] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/Steven-Rostedt/ftrace-Show-subops-in-enabled_functions/20250409-214345 base: https://git.kernel.org/pub/scm/linux/kernel/git/trace/linux-trace for-next patch link: https://lore.kernel.org/r/20250409094226.23f75293%40gandalf.local.home patch subject: [PATCH] ftrace: Show subops in enabled_functions config: i386-buildonly-randconfig-001-20250410 (https://download.01.org/0day-ci/archive/20250410/202504102339.KxLwdUFJ-lkp@intel.com/config) compiler: clang version 20.1.2 (https://github.com/llvm/llvm-project 58df0ef89dd64126512e4ee27b4ac3fd8ddf6247) reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250410/202504102339.KxLwdUFJ-lkp@intel.com/reproduce) If you fix the issue in a separate patch/commit (i.e. not just a new version of the same patch/commit), kindly add following tags | Reported-by: kernel test robot <lkp@intel.com> | Closes: https://lore.kernel.org/oe-kbuild-all/202504102339.KxLwdUFJ-lkp@intel.com/ All errors (new ones prefixed by >>): >> kernel/trace/ftrace.c:4342:11: error: incomplete definition of type 'struct fgraph_ops' 4342 | gops = container_of(subops, struct fgraph_ops, ops); | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/container_of.h:20:47: note: expanded from macro 'container_of' 20 | static_assert(__same_type(*(ptr), ((type *)0)->member) || \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~ 21 | __same_type(*(ptr), void), \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 22 | "pointer type mismatch in container_of()"); \ | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/compiler_types.h:483:74: note: expanded from macro '__same_type' 483 | #define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b)) | ^ include/linux/build_bug.h:77:50: note: expanded from macro 'static_assert' 77 | #define static_assert(expr, ...) __static_assert(expr, ##__VA_ARGS__, #expr) | ~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~ include/linux/build_bug.h:78:56: note: expanded from macro '__static_assert' 78 | #define __static_assert(expr, msg, ...) _Static_assert(expr, msg) | ^~~~ include/linux/ftrace.h:1158:8: note: forward declaration of 'struct fgraph_ops' 1158 | struct fgraph_ops; | ^ >> kernel/trace/ftrace.c:4342:11: error: offsetof of incomplete type 'struct fgraph_ops' 4342 | gops = container_of(subops, struct fgraph_ops, ops); | ^ ~~~~~~ include/linux/container_of.h:23:21: note: expanded from macro 'container_of' 23 | ((type *)(__mptr - offsetof(type, member))); }) | ^ ~~~~ include/linux/stddef.h:16:32: note: expanded from macro 'offsetof' 16 | #define offsetof(TYPE, MEMBER) __builtin_offsetof(TYPE, MEMBER) | ^ ~~~~ include/linux/ftrace.h:1158:8: note: forward declaration of 'struct fgraph_ops' 1158 | struct fgraph_ops; | ^ kernel/trace/ftrace.c:4344:20: error: incomplete definition of type 'struct fgraph_ops' 4344 | (void *)gops->entryfunc, | ~~~~^ include/linux/ftrace.h:1158:8: note: forward declaration of 'struct fgraph_ops' 1158 | struct fgraph_ops; | ^ kernel/trace/ftrace.c:4345:20: error: incomplete definition of type 'struct fgraph_ops' 4345 | (void *)gops->retfunc); | ~~~~^ include/linux/ftrace.h:1158:8: note: forward declaration of 'struct fgraph_ops' 1158 | struct fgraph_ops; | ^ 4 errors generated. vim +4342 kernel/trace/ftrace.c 4325 4326 static void print_subops(struct seq_file *m, struct ftrace_ops *ops, struct dyn_ftrace *rec) 4327 { 4328 struct ftrace_ops *subops; 4329 bool first = true; 4330 4331 list_for_each_entry(subops, &ops->subop_list, list) { 4332 if (!((subops->flags & FTRACE_OPS_FL_ENABLED) && 4333 hash_contains_ip(rec->ip, subops->func_hash))) 4334 continue; 4335 if (first) { 4336 seq_printf(m, "\tsubops:"); 4337 first = false; 4338 } 4339 if (subops->flags & FTRACE_OPS_FL_GRAPH) { 4340 struct fgraph_ops *gops; 4341 > 4342 gops = container_of(subops, struct fgraph_ops, ops); 4343 seq_printf(m, " {ent:%pS ret:%pS}", 4344 (void *)gops->entryfunc, 4345 (void *)gops->retfunc); 4346 continue; 4347 } 4348 if (subops->trampoline) { 4349 seq_printf(m, " {%pS (%pS)}", 4350 (void *)subops->trampoline, 4351 (void *)subops->func); 4352 add_trampoline_func(m, subops, rec); 4353 } else { 4354 seq_printf(m, " {%pS}", 4355 (void *)subops->func); 4356 } 4357 } 4358 } 4359 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests/wiki
On Thu, 10 Apr 2025 23:45:45 +0800 kernel test robot <lkp@intel.com> wrote: > >> kernel/trace/ftrace.c:4342:11: error: incomplete definition of type 'struct fgraph_ops' > 4342 | gops = container_of(subops, struct fgraph_ops, ops); > | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Thanks, This code needs a "#ifdef CONFIG_FUNCTION_GRAPH_TRACER" wrapper. -- Steve
© 2016 - 2025 Red Hat, Inc.