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>
This commit is contained in:
parent
dbc3f042fb
commit
a0572f687f
|
@ -389,6 +389,7 @@ enum {
|
||||||
FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
|
FTRACE_UPDATE_TRACE_FUNC = (1 << 2),
|
||||||
FTRACE_START_FUNC_RET = (1 << 3),
|
FTRACE_START_FUNC_RET = (1 << 3),
|
||||||
FTRACE_STOP_FUNC_RET = (1 << 4),
|
FTRACE_STOP_FUNC_RET = (1 << 4),
|
||||||
|
FTRACE_MAY_SLEEP = (1 << 5),
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -77,6 +77,11 @@
|
||||||
#define ASSIGN_OPS_HASH(opsname, val)
|
#define ASSIGN_OPS_HASH(opsname, val)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
enum {
|
||||||
|
FTRACE_MODIFY_ENABLE_FL = (1 << 0),
|
||||||
|
FTRACE_MODIFY_MAY_SLEEP_FL = (1 << 1),
|
||||||
|
};
|
||||||
|
|
||||||
struct ftrace_ops ftrace_list_end __read_mostly = {
|
struct ftrace_ops ftrace_list_end __read_mostly = {
|
||||||
.func = ftrace_stub,
|
.func = ftrace_stub,
|
||||||
.flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
|
.flags = FTRACE_OPS_FL_RECURSION_SAFE | FTRACE_OPS_FL_STUB,
|
||||||
|
@ -2389,10 +2394,12 @@ __ftrace_replace_code(struct dyn_ftrace *rec, int enable)
|
||||||
return -1; /* unknow ftrace bug */
|
return -1; /* unknow ftrace bug */
|
||||||
}
|
}
|
||||||
|
|
||||||
void __weak ftrace_replace_code(int enable)
|
void __weak ftrace_replace_code(int mod_flags)
|
||||||
{
|
{
|
||||||
struct dyn_ftrace *rec;
|
struct dyn_ftrace *rec;
|
||||||
struct ftrace_page *pg;
|
struct ftrace_page *pg;
|
||||||
|
int enable = mod_flags & FTRACE_MODIFY_ENABLE_FL;
|
||||||
|
int schedulable = mod_flags & FTRACE_MODIFY_MAY_SLEEP_FL;
|
||||||
int failed;
|
int failed;
|
||||||
|
|
||||||
if (unlikely(ftrace_disabled))
|
if (unlikely(ftrace_disabled))
|
||||||
|
@ -2409,6 +2416,8 @@ void __weak ftrace_replace_code(int enable)
|
||||||
/* Stop processing */
|
/* Stop processing */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (schedulable)
|
||||||
|
cond_resched();
|
||||||
} while_for_each_ftrace_rec();
|
} while_for_each_ftrace_rec();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2522,8 +2531,12 @@ int __weak ftrace_arch_code_modify_post_process(void)
|
||||||
void ftrace_modify_all_code(int command)
|
void ftrace_modify_all_code(int command)
|
||||||
{
|
{
|
||||||
int update = command & FTRACE_UPDATE_TRACE_FUNC;
|
int update = command & FTRACE_UPDATE_TRACE_FUNC;
|
||||||
|
int mod_flags = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
|
if (command & FTRACE_MAY_SLEEP)
|
||||||
|
mod_flags = FTRACE_MODIFY_MAY_SLEEP_FL;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the ftrace_caller calls a ftrace_ops func directly,
|
* If the ftrace_caller calls a ftrace_ops func directly,
|
||||||
* we need to make sure that it only traces functions it
|
* we need to make sure that it only traces functions it
|
||||||
|
@ -2541,9 +2554,9 @@ void ftrace_modify_all_code(int command)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (command & FTRACE_UPDATE_CALLS)
|
if (command & FTRACE_UPDATE_CALLS)
|
||||||
ftrace_replace_code(1);
|
ftrace_replace_code(mod_flags | FTRACE_MODIFY_ENABLE_FL);
|
||||||
else if (command & FTRACE_DISABLE_CALLS)
|
else if (command & FTRACE_DISABLE_CALLS)
|
||||||
ftrace_replace_code(0);
|
ftrace_replace_code(mod_flags);
|
||||||
|
|
||||||
if (update && ftrace_trace_function != ftrace_ops_list_func) {
|
if (update && ftrace_trace_function != ftrace_ops_list_func) {
|
||||||
function_trace_op = set_function_trace_op;
|
function_trace_op = set_function_trace_op;
|
||||||
|
|
Loading…
Reference in New Issue