aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/ftrace.c
diff options
context:
space:
mode:
authorSteven Rostedt (VMware) <rostedt@goodmis.org>2018-12-05 12:48:53 -0500
committerSteven Rostedt (VMware) <rostedt@goodmis.org>2018-12-10 12:22:45 -0500
commita0572f687fb3c46e15554f4789797a077cc393b4 (patch)
treeb30fd0ba692ed630e5b1afe9e31b9a7f8aac4701 /kernel/trace/ftrace.c
parentdbc3f042fbc8d75392b128af0eafbcf357733dd6 (diff)
ftrace: Allow ftrace_replace_code() to be schedulable
The function ftrace_replace_code() is the ftrace engine that does the work to modify all the nops into the calls to the function callback in all the functions being traced. The generic version which is normally called from stop machine, but an architecture can implement a non stop machine version and still use the generic ftrace_replace_code(). When an architecture does this, ftrace_replace_code() may be called from a schedulable context, where it can allow the code to be preemptible, and schedule out. In order to allow an architecture to make ftrace_replace_code() schedulable, a new command flag is added called: FTRACE_MAY_SLEEP Which can be or'd to the command that is passed to ftrace_modify_all_code() that calls ftrace_replace_code() and will have it call cond_resched() in the loop that modifies the nops into the calls to the ftrace trampolines. Link: http://lkml.kernel.org/r/20181204192903.8193-1-anders.roxell@linaro.org Link: http://lkml.kernel.org/r/20181205183303.828422192@goodmis.org Reported-by: Anders Roxell <anders.roxell@linaro.org> Tested-by: Anders Roxell <anders.roxell@linaro.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/ftrace.c')
-rw-r--r--kernel/trace/ftrace.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 8ef9fc226037..ab3e8b995e12 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -77,6 +77,11 @@
77#define ASSIGN_OPS_HASH(opsname, val) 77#define ASSIGN_OPS_HASH(opsname, val)
78#endif 78#endif
79 79
80enum {
81 FTRACE_MODIFY_ENABLE_FL = (1 << 0),
82 FTRACE_MODIFY_MAY_SLEEP_FL = (1 << 1),
83};
84
80struct ftrace_ops ftrace_list_end __read_mostly = { 85struct ftrace_ops ftrace_list_end __read_mostly = {
81 .func = ftrace_stub, 86 .func = ftrace_stub,
82 .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB, 87 .flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
@@ -2389,10 +2394,12 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
2389 return -1; /* unknow ftrace bug */ 2394 return -1; /* unknow ftrace bug */
2390} 2395}
2391 2396
2392void __weak ftrace_replace_code(int enable) 2397void __weak ftrace_replace_code(int mod_flags)
2393{ 2398{
2394 struct dyn_ftrace *rec; 2399 struct dyn_ftrace *rec;
2395 struct ftrace_page *pg; 2400 struct ftrace_page *pg;
2401 int enable = mod_flags & FTRACE_MODIFY_ENABLE_FL;
2402 int schedulable = mod_flags & FTRACE_MODIFY_MAY_SLEEP_FL;
2396 int failed; 2403 int failed;
2397 2404
2398 if (unlikely(ftrace_disabled)) 2405 if (unlikely(ftrace_disabled))
@@ -2409,6 +2416,8 @@ void __weak ftrace_replace_code(int enable)
2409 /* Stop processing */ 2416 /* Stop processing */
2410 return; 2417 return;
2411 } 2418 }
2419 if (schedulable)
2420 cond_resched();
2412 } while_for_each_ftrace_rec(); 2421 } while_for_each_ftrace_rec();
2413} 2422}
2414 2423
@@ -2522,8 +2531,12 @@ int __weak ftrace_arch_code_modify_post_process(void)
2522void ftrace_modify_all_code(int command) 2531void ftrace_modify_all_code(int command)
2523{ 2532{
2524 int update = command & FTRACE_UPDATE_TRACE_FUNC; 2533 int update = command & FTRACE_UPDATE_TRACE_FUNC;
2534 int mod_flags = 0;
2525 int err = 0; 2535 int err = 0;
2526 2536
2537 if (command & FTRACE_MAY_SLEEP)
2538 mod_flags = FTRACE_MODIFY_MAY_SLEEP_FL;
2539
2527 /* 2540 /*
2528 * If the ftrace_caller calls a ftrace_ops func directly, 2541 * If the ftrace_caller calls a ftrace_ops func directly,
2529 * we need to make sure that it only traces functions it 2542 * we need to make sure that it only traces functions it
@@ -2541,9 +2554,9 @@ void ftrace_modify_all_code(int command)
2541 } 2554 }
2542 2555
2543 if (command & FTRACE_UPDATE_CALLS) 2556 if (command & FTRACE_UPDATE_CALLS)
2544 ftrace_replace_code(1); 2557 ftrace_replace_code(mod_flags | FTRACE_MODIFY_ENABLE_FL);
2545 else if (command & FTRACE_DISABLE_CALLS) 2558 else if (command & FTRACE_DISABLE_CALLS)
2546 ftrace_replace_code(0); 2559 ftrace_replace_code(mod_flags);
2547 2560
2548 if (update && ftrace_trace_function != ftrace_ops_list_func) { 2561 if (update && ftrace_trace_function != ftrace_ops_list_func) {
2549 function_trace_op = set_function_trace_op; 2562 function_trace_op = set_function_trace_op;