diff options
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r-- | kernel/trace/ftrace.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 17b95a492948..4b93b8412252 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -297,6 +297,12 @@ static void ftrace_sync_ipi(void *data) | |||
297 | smp_rmb(); | 297 | smp_rmb(); |
298 | } | 298 | } |
299 | 299 | ||
300 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
301 | static void update_function_graph_func(void); | ||
302 | #else | ||
303 | static inline void update_function_graph_func(void) { } | ||
304 | #endif | ||
305 | |||
300 | static void update_ftrace_function(void) | 306 | static void update_ftrace_function(void) |
301 | { | 307 | { |
302 | ftrace_func_t func; | 308 | ftrace_func_t func; |
@@ -329,6 +335,8 @@ static void update_ftrace_function(void) | |||
329 | if (ftrace_trace_function == func) | 335 | if (ftrace_trace_function == func) |
330 | return; | 336 | return; |
331 | 337 | ||
338 | update_function_graph_func(); | ||
339 | |||
332 | /* | 340 | /* |
333 | * If we are using the list function, it doesn't care | 341 | * If we are using the list function, it doesn't care |
334 | * about the function_trace_ops. | 342 | * about the function_trace_ops. |
@@ -4810,6 +4818,7 @@ int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) | |||
4810 | trace_func_graph_ret_t ftrace_graph_return = | 4818 | trace_func_graph_ret_t ftrace_graph_return = |
4811 | (trace_func_graph_ret_t)ftrace_stub; | 4819 | (trace_func_graph_ret_t)ftrace_stub; |
4812 | trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub; | 4820 | trace_func_graph_ent_t ftrace_graph_entry = ftrace_graph_entry_stub; |
4821 | static trace_func_graph_ent_t __ftrace_graph_entry = ftrace_graph_entry_stub; | ||
4813 | 4822 | ||
4814 | /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */ | 4823 | /* Try to assign a return stack array on FTRACE_RETSTACK_ALLOC_SIZE tasks. */ |
4815 | static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) | 4824 | static int alloc_retstack_tasklist(struct ftrace_ret_stack **ret_stack_list) |
@@ -4951,6 +4960,30 @@ static struct ftrace_ops fgraph_ops __read_mostly = { | |||
4951 | FTRACE_OPS_FL_RECURSION_SAFE, | 4960 | FTRACE_OPS_FL_RECURSION_SAFE, |
4952 | }; | 4961 | }; |
4953 | 4962 | ||
4963 | static int ftrace_graph_entry_test(struct ftrace_graph_ent *trace) | ||
4964 | { | ||
4965 | if (!ftrace_ops_test(&global_ops, trace->func, NULL)) | ||
4966 | return 0; | ||
4967 | return __ftrace_graph_entry(trace); | ||
4968 | } | ||
4969 | |||
4970 | /* | ||
4971 | * The function graph tracer should only trace the functions defined | ||
4972 | * by set_ftrace_filter and set_ftrace_notrace. If another function | ||
4973 | * tracer ops is registered, the graph tracer requires testing the | ||
4974 | * function against the global ops, and not just trace any function | ||
4975 | * that any ftrace_ops registered. | ||
4976 | */ | ||
4977 | static void update_function_graph_func(void) | ||
4978 | { | ||
4979 | if (ftrace_ops_list == &ftrace_list_end || | ||
4980 | (ftrace_ops_list == &global_ops && | ||
4981 | global_ops.next == &ftrace_list_end)) | ||
4982 | ftrace_graph_entry = __ftrace_graph_entry; | ||
4983 | else | ||
4984 | ftrace_graph_entry = ftrace_graph_entry_test; | ||
4985 | } | ||
4986 | |||
4954 | int register_ftrace_graph(trace_func_graph_ret_t retfunc, | 4987 | int register_ftrace_graph(trace_func_graph_ret_t retfunc, |
4955 | trace_func_graph_ent_t entryfunc) | 4988 | trace_func_graph_ent_t entryfunc) |
4956 | { | 4989 | { |
@@ -4975,7 +5008,16 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, | |||
4975 | } | 5008 | } |
4976 | 5009 | ||
4977 | ftrace_graph_return = retfunc; | 5010 | ftrace_graph_return = retfunc; |
4978 | ftrace_graph_entry = entryfunc; | 5011 | |
5012 | /* | ||
5013 | * Update the indirect function to the entryfunc, and the | ||
5014 | * function that gets called to the entry_test first. Then | ||
5015 | * call the update fgraph entry function to determine if | ||
5016 | * the entryfunc should be called directly or not. | ||
5017 | */ | ||
5018 | __ftrace_graph_entry = entryfunc; | ||
5019 | ftrace_graph_entry = ftrace_graph_entry_test; | ||
5020 | update_function_graph_func(); | ||
4979 | 5021 | ||
4980 | ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET); | 5022 | ret = ftrace_startup(&fgraph_ops, FTRACE_START_FUNC_RET); |
4981 | 5023 | ||
@@ -4994,6 +5036,7 @@ void unregister_ftrace_graph(void) | |||
4994 | ftrace_graph_active--; | 5036 | ftrace_graph_active--; |
4995 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; | 5037 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; |
4996 | ftrace_graph_entry = ftrace_graph_entry_stub; | 5038 | ftrace_graph_entry = ftrace_graph_entry_stub; |
5039 | __ftrace_graph_entry = ftrace_graph_entry_stub; | ||
4997 | ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET); | 5040 | ftrace_shutdown(&fgraph_ops, FTRACE_STOP_FUNC_RET); |
4998 | unregister_pm_notifier(&ftrace_suspend_notifier); | 5041 | unregister_pm_notifier(&ftrace_suspend_notifier); |
4999 | unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); | 5042 | unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); |