[PATCH] ftrace: Show subops in enabled_functions

Steven Rostedt posted 1 patch 4 weeks ago
There is a newer version of this series
include/linux/ftrace.h |  2 ++
kernel/trace/fgraph.c  |  2 ++
kernel/trace/ftrace.c  | 36 ++++++++++++++++++++++++++++++++++++
3 files changed, 40 insertions(+)
[PATCH] ftrace: Show subops in enabled_functions
Posted by Steven Rostedt 4 weeks ago
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
Re: [PATCH] ftrace: Show subops in enabled_functions
Posted by kernel test robot 3 weeks, 6 days ago
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
Re: [PATCH] ftrace: Show subops in enabled_functions
Posted by Steven Rostedt 3 weeks, 6 days ago
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