Commit 6e4eb9cb authored by Steven Rostedt (VMware)'s avatar Steven Rostedt (VMware)
Browse files

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: default avatarSteven Rostedt (VMware) <rostedt@goodmis.org>
parent 0264c8c9
Loading
Loading
Loading
Loading
+25 −0
Original line number Diff line number Diff line
@@ -183,5 +183,30 @@ static __always_inline void trace_clear_recursion(int bit)
	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 /* _LINUX_TRACE_RECURSION_H */
+5 −7
Original line number Diff line number Diff line
@@ -141,22 +141,20 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
	if (unlikely(!tr->function_enabled))
		return;

	bit = ftrace_test_recursion_trylock();
	if (bit < 0)
		return;

	pc = preempt_count();
	preempt_disable_notrace();

	bit = trace_test_and_set_recursion(TRACE_FTRACE_START, TRACE_FTRACE_MAX);
	if (bit < 0)
		goto out;

	cpu = smp_processor_id();
	data = per_cpu_ptr(tr->array_buffer.data, cpu);
	if (!atomic_read(&data->disabled)) {
		local_save_flags(flags);
		trace_function(tr, ip, parent_ip, flags, pc);
	}
	trace_clear_recursion(bit);

 out:
	ftrace_test_recursion_unlock(bit);
	preempt_enable_notrace();
}