fgraph: Add new fgraph_ops structure to enable function graph hooks

Currently the registering of function graph is to pass in a entry and return
function. We need to have a way to associate those functions together where
the entry can determine to run the return hook. Having a structure that
contains both functions will facilitate the process of converting the code
to be able to do such.

This is similar to the way function hooks are enabled (it passes in
ftrace_ops). Instead of passing in the functions to use, a single structure
is passed in to the registering function.

The unregister function is now passed in the fgraph_ops handle. When we
allow more than one callback to the function graph hooks, this will let the
system know which one to remove.
Reviewed-by: default avatarJoel Fernandes (Google) <joel@joelfernandes.org>
Signed-off-by: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 317e04ca
...@@ -749,6 +749,11 @@ typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */ ...@@ -749,6 +749,11 @@ typedef int (*trace_func_graph_ent_t)(struct ftrace_graph_ent *); /* entry */
#ifdef CONFIG_FUNCTION_GRAPH_TRACER #ifdef CONFIG_FUNCTION_GRAPH_TRACER
struct fgraph_ops {
trace_func_graph_ent_t entryfunc;
trace_func_graph_ret_t retfunc;
};
/* /*
* Stack of return addresses for functions * Stack of return addresses for functions
* of a thread. * of a thread.
...@@ -792,8 +797,9 @@ unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx, ...@@ -792,8 +797,9 @@ unsigned long ftrace_graph_ret_addr(struct task_struct *task, int *idx,
#define FTRACE_RETFUNC_DEPTH 50 #define FTRACE_RETFUNC_DEPTH 50
#define FTRACE_RETSTACK_ALLOC_SIZE 32 #define FTRACE_RETSTACK_ALLOC_SIZE 32
extern int register_ftrace_graph(trace_func_graph_ret_t retfunc,
trace_func_graph_ent_t entryfunc); extern int register_ftrace_graph(struct fgraph_ops *ops);
extern void unregister_ftrace_graph(struct fgraph_ops *ops);
extern bool ftrace_graph_is_dead(void); extern bool ftrace_graph_is_dead(void);
extern void ftrace_graph_stop(void); extern void ftrace_graph_stop(void);
...@@ -802,8 +808,6 @@ extern void ftrace_graph_stop(void); ...@@ -802,8 +808,6 @@ extern void ftrace_graph_stop(void);
extern trace_func_graph_ret_t ftrace_graph_return; extern trace_func_graph_ret_t ftrace_graph_return;
extern trace_func_graph_ent_t ftrace_graph_entry; extern trace_func_graph_ent_t ftrace_graph_entry;
extern void unregister_ftrace_graph(void);
extern void ftrace_graph_init_task(struct task_struct *t); extern void ftrace_graph_init_task(struct task_struct *t);
extern void ftrace_graph_exit_task(struct task_struct *t); extern void ftrace_graph_exit_task(struct task_struct *t);
extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu); extern void ftrace_graph_init_idle_task(struct task_struct *t, int cpu);
...@@ -825,12 +829,9 @@ static inline void ftrace_graph_init_task(struct task_struct *t) { } ...@@ -825,12 +829,9 @@ static inline void ftrace_graph_init_task(struct task_struct *t) { }
static inline void ftrace_graph_exit_task(struct task_struct *t) { } static inline void ftrace_graph_exit_task(struct task_struct *t) { }
static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { } static inline void ftrace_graph_init_idle_task(struct task_struct *t, int cpu) { }
static inline int register_ftrace_graph(trace_func_graph_ret_t retfunc, /* Define as macros as fgraph_ops may not be defined */
trace_func_graph_ent_t entryfunc) #define register_ftrace_graph(ops) ({ -1; })
{ #define unregister_ftrace_graph(ops) do { } while (0)
return -1;
}
static inline void unregister_ftrace_graph(void) { }
static inline unsigned long static inline unsigned long
ftrace_graph_ret_addr(struct task_struct *task, int *idx, unsigned long ret, ftrace_graph_ret_addr(struct task_struct *task, int *idx, unsigned long ret,
......
...@@ -490,8 +490,7 @@ static int start_graph_tracing(void) ...@@ -490,8 +490,7 @@ static int start_graph_tracing(void)
return ret; return ret;
} }
int register_ftrace_graph(trace_func_graph_ret_t retfunc, int register_ftrace_graph(struct fgraph_ops *gops)
trace_func_graph_ent_t entryfunc)
{ {
int ret = 0; int ret = 0;
...@@ -512,7 +511,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, ...@@ -512,7 +511,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
goto out; goto out;
} }
ftrace_graph_return = retfunc; ftrace_graph_return = gops->retfunc;
/* /*
* Update the indirect function to the entryfunc, and the * Update the indirect function to the entryfunc, and the
...@@ -520,7 +519,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, ...@@ -520,7 +519,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
* call the update fgraph entry function to determine if * call the update fgraph entry function to determine if
* the entryfunc should be called directly or not. * the entryfunc should be called directly or not.
*/ */
__ftrace_graph_entry = entryfunc; __ftrace_graph_entry = gops->entryfunc;
ftrace_graph_entry = ftrace_graph_entry_test; ftrace_graph_entry = ftrace_graph_entry_test;
update_function_graph_func(); update_function_graph_func();
...@@ -530,7 +529,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, ...@@ -530,7 +529,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc,
return ret; return ret;
} }
void unregister_ftrace_graph(void) void unregister_ftrace_graph(struct fgraph_ops *gops)
{ {
mutex_lock(&ftrace_lock); mutex_lock(&ftrace_lock);
......
...@@ -849,15 +849,19 @@ static void profile_graph_return(struct ftrace_graph_ret *trace) ...@@ -849,15 +849,19 @@ static void profile_graph_return(struct ftrace_graph_ret *trace)
local_irq_restore(flags); local_irq_restore(flags);
} }
static struct fgraph_ops fprofiler_ops = {
.entryfunc = &profile_graph_entry,
.retfunc = &profile_graph_return,
};
static int register_ftrace_profiler(void) static int register_ftrace_profiler(void)
{ {
return register_ftrace_graph(&profile_graph_return, return register_ftrace_graph(&fprofiler_ops);
&profile_graph_entry);
} }
static void unregister_ftrace_profiler(void) static void unregister_ftrace_profiler(void)
{ {
unregister_ftrace_graph(); unregister_ftrace_graph(&fprofiler_ops);
} }
#else #else
static struct ftrace_ops ftrace_profile_ops __read_mostly = { static struct ftrace_ops ftrace_profile_ops __read_mostly = {
......
...@@ -345,17 +345,25 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace) ...@@ -345,17 +345,25 @@ static void trace_graph_thresh_return(struct ftrace_graph_ret *trace)
trace_graph_return(trace); trace_graph_return(trace);
} }
static struct fgraph_ops funcgraph_thresh_ops = {
.entryfunc = &trace_graph_entry,
.retfunc = &trace_graph_thresh_return,
};
static struct fgraph_ops funcgraph_ops = {
.entryfunc = &trace_graph_entry,
.retfunc = &trace_graph_return,
};
static int graph_trace_init(struct trace_array *tr) static int graph_trace_init(struct trace_array *tr)
{ {
int ret; int ret;
set_graph_array(tr); set_graph_array(tr);
if (tracing_thresh) if (tracing_thresh)
ret = register_ftrace_graph(&trace_graph_thresh_return, ret = register_ftrace_graph(&funcgraph_thresh_ops);
&trace_graph_entry);
else else
ret = register_ftrace_graph(&trace_graph_return, ret = register_ftrace_graph(&funcgraph_ops);
&trace_graph_entry);
if (ret) if (ret)
return ret; return ret;
tracing_start_cmdline_record(); tracing_start_cmdline_record();
...@@ -366,7 +374,10 @@ static int graph_trace_init(struct trace_array *tr) ...@@ -366,7 +374,10 @@ static int graph_trace_init(struct trace_array *tr)
static void graph_trace_reset(struct trace_array *tr) static void graph_trace_reset(struct trace_array *tr)
{ {
tracing_stop_cmdline_record(); tracing_stop_cmdline_record();
unregister_ftrace_graph(); if (tracing_thresh)
unregister_ftrace_graph(&funcgraph_thresh_ops);
else
unregister_ftrace_graph(&funcgraph_ops);
} }
static int graph_trace_update_thresh(struct trace_array *tr) static int graph_trace_update_thresh(struct trace_array *tr)
......
...@@ -218,6 +218,11 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace) ...@@ -218,6 +218,11 @@ static void irqsoff_graph_return(struct ftrace_graph_ret *trace)
atomic_dec(&data->disabled); atomic_dec(&data->disabled);
} }
static struct fgraph_ops fgraph_ops = {
.entryfunc = &irqsoff_graph_entry,
.retfunc = &irqsoff_graph_return,
};
static void irqsoff_trace_open(struct trace_iterator *iter) static void irqsoff_trace_open(struct trace_iterator *iter)
{ {
if (is_graph(iter->tr)) if (is_graph(iter->tr))
...@@ -272,13 +277,6 @@ __trace_function(struct trace_array *tr, ...@@ -272,13 +277,6 @@ __trace_function(struct trace_array *tr,
#else #else
#define __trace_function trace_function #define __trace_function trace_function
#ifdef CONFIG_FUNCTION_TRACER
static int irqsoff_graph_entry(struct ftrace_graph_ent *trace)
{
return -1;
}
#endif
static enum print_line_t irqsoff_print_line(struct trace_iterator *iter) static enum print_line_t irqsoff_print_line(struct trace_iterator *iter)
{ {
return TRACE_TYPE_UNHANDLED; return TRACE_TYPE_UNHANDLED;
...@@ -288,7 +286,6 @@ static void irqsoff_trace_open(struct trace_iterator *iter) { } ...@@ -288,7 +286,6 @@ static void irqsoff_trace_open(struct trace_iterator *iter) { }
static void irqsoff_trace_close(struct trace_iterator *iter) { } static void irqsoff_trace_close(struct trace_iterator *iter) { }
#ifdef CONFIG_FUNCTION_TRACER #ifdef CONFIG_FUNCTION_TRACER
static void irqsoff_graph_return(struct ftrace_graph_ret *trace) { }
static void irqsoff_print_header(struct seq_file *s) static void irqsoff_print_header(struct seq_file *s)
{ {
trace_default_header(s); trace_default_header(s);
...@@ -468,8 +465,7 @@ static int register_irqsoff_function(struct trace_array *tr, int graph, int set) ...@@ -468,8 +465,7 @@ static int register_irqsoff_function(struct trace_array *tr, int graph, int set)
return 0; return 0;
if (graph) if (graph)
ret = register_ftrace_graph(&irqsoff_graph_return, ret = register_ftrace_graph(&fgraph_ops);
&irqsoff_graph_entry);
else else
ret = register_ftrace_function(tr->ops); ret = register_ftrace_function(tr->ops);
...@@ -485,7 +481,7 @@ static void unregister_irqsoff_function(struct trace_array *tr, int graph) ...@@ -485,7 +481,7 @@ static void unregister_irqsoff_function(struct trace_array *tr, int graph)
return; return;
if (graph) if (graph)
unregister_ftrace_graph(); unregister_ftrace_graph(&fgraph_ops);
else else
unregister_ftrace_function(tr->ops); unregister_ftrace_function(tr->ops);
......
...@@ -162,6 +162,11 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace) ...@@ -162,6 +162,11 @@ static void wakeup_graph_return(struct ftrace_graph_ret *trace)
return; return;
} }
static struct fgraph_ops fgraph_wakeup_ops = {
.entryfunc = &wakeup_graph_entry,
.retfunc = &wakeup_graph_return,
};
static void wakeup_trace_open(struct trace_iterator *iter) static void wakeup_trace_open(struct trace_iterator *iter)
{ {
if (is_graph(iter->tr)) if (is_graph(iter->tr))
...@@ -197,12 +202,6 @@ static void wakeup_print_header(struct seq_file *s) ...@@ -197,12 +202,6 @@ static void wakeup_print_header(struct seq_file *s)
else else
trace_default_header(s); trace_default_header(s);
} }
#else /* CONFIG_FUNCTION_GRAPH_TRACER */
static int wakeup_graph_entry(struct ftrace_graph_ent *trace)
{
return -1;
}
static void wakeup_graph_return(struct ftrace_graph_ret *trace) { }
#endif /* else CONFIG_FUNCTION_GRAPH_TRACER */ #endif /* else CONFIG_FUNCTION_GRAPH_TRACER */
/* /*
...@@ -237,8 +236,7 @@ static int register_wakeup_function(struct trace_array *tr, int graph, int set) ...@@ -237,8 +236,7 @@ static int register_wakeup_function(struct trace_array *tr, int graph, int set)
return 0; return 0;
if (graph) if (graph)
ret = register_ftrace_graph(&wakeup_graph_return, ret = register_ftrace_graph(&fgraph_wakeup_ops);
&wakeup_graph_entry);
else else
ret = register_ftrace_function(tr->ops); ret = register_ftrace_function(tr->ops);
...@@ -254,7 +252,7 @@ static void unregister_wakeup_function(struct trace_array *tr, int graph) ...@@ -254,7 +252,7 @@ static void unregister_wakeup_function(struct trace_array *tr, int graph)
return; return;
if (graph) if (graph)
unregister_ftrace_graph(); unregister_ftrace_graph(&fgraph_wakeup_ops);
else else
unregister_ftrace_function(tr->ops); unregister_ftrace_function(tr->ops);
......
...@@ -741,6 +741,11 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace) ...@@ -741,6 +741,11 @@ static int trace_graph_entry_watchdog(struct ftrace_graph_ent *trace)
return trace_graph_entry(trace); return trace_graph_entry(trace);
} }
static struct fgraph_ops fgraph_ops __initdata = {
.entryfunc = &trace_graph_entry_watchdog,
.retfunc = &trace_graph_return,
};
/* /*
* Pretty much the same than for the function tracer from which the selftest * Pretty much the same than for the function tracer from which the selftest
* has been borrowed. * has been borrowed.
...@@ -765,8 +770,7 @@ trace_selftest_startup_function_graph(struct tracer *trace, ...@@ -765,8 +770,7 @@ trace_selftest_startup_function_graph(struct tracer *trace,
*/ */
tracing_reset_online_cpus(&tr->trace_buffer); tracing_reset_online_cpus(&tr->trace_buffer);
set_graph_array(tr); set_graph_array(tr);
ret = register_ftrace_graph(&trace_graph_return, ret = register_ftrace_graph(&fgraph_ops);
&trace_graph_entry_watchdog);
if (ret) { if (ret) {
warn_failed_init_tracer(trace, ret); warn_failed_init_tracer(trace, ret);
goto out; goto out;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment