ftrace: Add ftrace_test_recursion_trylock() helper function
To make it easier for ftrace callbacks to have recursion protection, provide a ftrace_test_recursion_trylock() and ftrace_test_recursion_unlock() helper that tests for recursion. Link: https://lkml.kernel.org/r/20201028115612.634927593@goodmis.org Link: https://lkml.kernel.org/r/20201106023546.378584067@goodmis.org Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
parent
0264c8c9e1
commit
6e4eb9cb22
|
@ -183,5 +183,30 @@ static __always_inline void trace_clear_recursion(int bit)
|
||||||
current->trace_recursion = val;
|
current->trace_recursion = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ftrace_test_recursion_trylock - tests for recursion in same context
|
||||||
|
*
|
||||||
|
* Use this for ftrace callbacks. This will detect if the function
|
||||||
|
* tracing recursed in the same context (normal vs interrupt),
|
||||||
|
*
|
||||||
|
* Returns: -1 if a recursion happened.
|
||||||
|
* >= 0 if no recursion
|
||||||
|
*/
|
||||||
|
static __always_inline int ftrace_test_recursion_trylock(void)
|
||||||
|
{
|
||||||
|
return trace_test_and_set_recursion(TRACE_FTRACE_START, TRACE_FTRACE_MAX);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ftrace_test_recursion_unlock - called when function callback is complete
|
||||||
|
* @bit: The return of a successful ftrace_test_recursion_trylock()
|
||||||
|
*
|
||||||
|
* This is used at the end of a ftrace callback.
|
||||||
|
*/
|
||||||
|
static __always_inline void ftrace_test_recursion_unlock(int bit)
|
||||||
|
{
|
||||||
|
trace_clear_recursion(bit);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* CONFIG_TRACING */
|
#endif /* CONFIG_TRACING */
|
||||||
#endif /* _LINUX_TRACE_RECURSION_H */
|
#endif /* _LINUX_TRACE_RECURSION_H */
|
||||||
|
|
|
@ -141,22 +141,20 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||||
if (unlikely(!tr->function_enabled))
|
if (unlikely(!tr->function_enabled))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
bit = ftrace_test_recursion_trylock();
|
||||||
|
if (bit < 0)
|
||||||
|
return;
|
||||||
|
|
||||||
pc = preempt_count();
|
pc = preempt_count();
|
||||||
preempt_disable_notrace();
|
preempt_disable_notrace();
|
||||||
|
|
||||||
bit = trace_test_and_set_recursion(TRACE_FTRACE_START, TRACE_FTRACE_MAX);
|
|
||||||
if (bit < 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
cpu = smp_processor_id();
|
cpu = smp_processor_id();
|
||||||
data = per_cpu_ptr(tr->array_buffer.data, cpu);
|
data = per_cpu_ptr(tr->array_buffer.data, cpu);
|
||||||
if (!atomic_read(&data->disabled)) {
|
if (!atomic_read(&data->disabled)) {
|
||||||
local_save_flags(flags);
|
local_save_flags(flags);
|
||||||
trace_function(tr, ip, parent_ip, flags, pc);
|
trace_function(tr, ip, parent_ip, flags, pc);
|
||||||
}
|
}
|
||||||
trace_clear_recursion(bit);
|
ftrace_test_recursion_unlock(bit);
|
||||||
|
|
||||||
out:
|
|
||||||
preempt_enable_notrace();
|
preempt_enable_notrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue