diff options
-rw-r--r-- | kernel/trace/ftrace.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 92376aeac4a7..08aca65d709a 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c | |||
@@ -68,8 +68,12 @@ | |||
68 | #define INIT_OPS_HASH(opsname) \ | 68 | #define INIT_OPS_HASH(opsname) \ |
69 | .func_hash = &opsname.local_hash, \ | 69 | .func_hash = &opsname.local_hash, \ |
70 | .local_hash.regex_lock = __MUTEX_INITIALIZER(opsname.local_hash.regex_lock), | 70 | .local_hash.regex_lock = __MUTEX_INITIALIZER(opsname.local_hash.regex_lock), |
71 | #define ASSIGN_OPS_HASH(opsname, val) \ | ||
72 | .func_hash = val, \ | ||
73 | .local_hash.regex_lock = __MUTEX_INITIALIZER(opsname.local_hash.regex_lock), | ||
71 | #else | 74 | #else |
72 | #define INIT_OPS_HASH(opsname) | 75 | #define INIT_OPS_HASH(opsname) |
76 | #define ASSIGN_OPS_HASH(opsname, val) | ||
73 | #endif | 77 | #endif |
74 | 78 | ||
75 | static struct ftrace_ops ftrace_list_end __read_mostly = { | 79 | static struct ftrace_ops ftrace_list_end __read_mostly = { |
@@ -4663,7 +4667,6 @@ void __init ftrace_init(void) | |||
4663 | static struct ftrace_ops global_ops = { | 4667 | static struct ftrace_ops global_ops = { |
4664 | .func = ftrace_stub, | 4668 | .func = ftrace_stub, |
4665 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, | 4669 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_INITIALIZED, |
4666 | INIT_OPS_HASH(global_ops) | ||
4667 | }; | 4670 | }; |
4668 | 4671 | ||
4669 | static int __init ftrace_nodyn_init(void) | 4672 | static int __init ftrace_nodyn_init(void) |
@@ -5197,6 +5200,17 @@ ftrace_enable_sysctl(struct ctl_table *table, int write, | |||
5197 | 5200 | ||
5198 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | 5201 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER |
5199 | 5202 | ||
5203 | static struct ftrace_ops graph_ops = { | ||
5204 | .func = ftrace_stub, | ||
5205 | .flags = FTRACE_OPS_FL_RECURSION_SAFE | | ||
5206 | FTRACE_OPS_FL_INITIALIZED | | ||
5207 | FTRACE_OPS_FL_STUB, | ||
5208 | #ifdef FTRACE_GRAPH_TRAMP_ADDR | ||
5209 | .trampoline = FTRACE_GRAPH_TRAMP_ADDR, | ||
5210 | #endif | ||
5211 | ASSIGN_OPS_HASH(graph_ops, &global_ops.local_hash) | ||
5212 | }; | ||
5213 | |||
5200 | static int ftrace_graph_active; | 5214 | static int ftrace_graph_active; |
5201 | 5215 | ||
5202 | int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) | 5216 | int ftrace_graph_entry_stub(struct ftrace_graph_ent *trace) |
@@ -5359,12 +5373,28 @@ static int ftrace_graph_entry_test(struct ftrace_graph_ent *trace) | |||
5359 | */ | 5373 | */ |
5360 | static void update_function_graph_func(void) | 5374 | static void update_function_graph_func(void) |
5361 | { | 5375 | { |
5362 | if (ftrace_ops_list == &ftrace_list_end || | 5376 | struct ftrace_ops *op; |
5363 | (ftrace_ops_list == &global_ops && | 5377 | bool do_test = false; |
5364 | global_ops.next == &ftrace_list_end)) | 5378 | |
5365 | ftrace_graph_entry = __ftrace_graph_entry; | 5379 | /* |
5366 | else | 5380 | * The graph and global ops share the same set of functions |
5381 | * to test. If any other ops is on the list, then | ||
5382 | * the graph tracing needs to test if its the function | ||
5383 | * it should call. | ||
5384 | */ | ||
5385 | do_for_each_ftrace_op(op, ftrace_ops_list) { | ||
5386 | if (op != &global_ops && op != &graph_ops && | ||
5387 | op != &ftrace_list_end) { | ||
5388 | do_test = true; | ||
5389 | /* in double loop, break out with goto */ | ||
5390 | goto out; | ||
5391 | } | ||
5392 | } while_for_each_ftrace_op(op); | ||
5393 | out: | ||
5394 | if (do_test) | ||
5367 | ftrace_graph_entry = ftrace_graph_entry_test; | 5395 | ftrace_graph_entry = ftrace_graph_entry_test; |
5396 | else | ||
5397 | ftrace_graph_entry = __ftrace_graph_entry; | ||
5368 | } | 5398 | } |
5369 | 5399 | ||
5370 | static struct notifier_block ftrace_suspend_notifier = { | 5400 | static struct notifier_block ftrace_suspend_notifier = { |
@@ -5405,16 +5435,7 @@ int register_ftrace_graph(trace_func_graph_ret_t retfunc, | |||
5405 | ftrace_graph_entry = ftrace_graph_entry_test; | 5435 | ftrace_graph_entry = ftrace_graph_entry_test; |
5406 | update_function_graph_func(); | 5436 | update_function_graph_func(); |
5407 | 5437 | ||
5408 | /* Function graph doesn't use the .func field of global_ops */ | 5438 | ret = ftrace_startup(&graph_ops, FTRACE_START_FUNC_RET); |
5409 | global_ops.flags |= FTRACE_OPS_FL_STUB; | ||
5410 | |||
5411 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
5412 | /* Optimize function graph calling (if implemented by arch) */ | ||
5413 | if (FTRACE_GRAPH_TRAMP_ADDR != 0) | ||
5414 | global_ops.trampoline = FTRACE_GRAPH_TRAMP_ADDR; | ||
5415 | #endif | ||
5416 | |||
5417 | ret = ftrace_startup(&global_ops, FTRACE_START_FUNC_RET); | ||
5418 | 5439 | ||
5419 | out: | 5440 | out: |
5420 | mutex_unlock(&ftrace_lock); | 5441 | mutex_unlock(&ftrace_lock); |
@@ -5432,12 +5453,7 @@ void unregister_ftrace_graph(void) | |||
5432 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; | 5453 | ftrace_graph_return = (trace_func_graph_ret_t)ftrace_stub; |
5433 | ftrace_graph_entry = ftrace_graph_entry_stub; | 5454 | ftrace_graph_entry = ftrace_graph_entry_stub; |
5434 | __ftrace_graph_entry = ftrace_graph_entry_stub; | 5455 | __ftrace_graph_entry = ftrace_graph_entry_stub; |
5435 | ftrace_shutdown(&global_ops, FTRACE_STOP_FUNC_RET); | 5456 | ftrace_shutdown(&graph_ops, FTRACE_STOP_FUNC_RET); |
5436 | global_ops.flags &= ~FTRACE_OPS_FL_STUB; | ||
5437 | #ifdef CONFIG_DYNAMIC_FTRACE | ||
5438 | if (FTRACE_GRAPH_TRAMP_ADDR != 0) | ||
5439 | global_ops.trampoline = 0; | ||
5440 | #endif | ||
5441 | unregister_pm_notifier(&ftrace_suspend_notifier); | 5457 | unregister_pm_notifier(&ftrace_suspend_notifier); |
5442 | unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); | 5458 | unregister_trace_sched_switch(ftrace_graph_probe_sched_switch, NULL); |
5443 | 5459 | ||