mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/xiang/erofs.git
synced 2026-10-29 21:33:00 +01:00
ftrace: disable preemption when recursion locked
As the documentation explained, ftrace_test_recursion_trylock() and ftrace_test_recursion_unlock() were supposed to disable and enable preemption properly, however currently this work is done outside of the function, which could be missing by mistake. And since the internal using of trace_test_and_set_recursion() and trace_clear_recursion() also require preemption disabled, we can just merge the logical. This patch will make sure the preemption has been disabled when trace_test_and_set_recursion() return bit >= 0, and trace_clear_recursion() will enable the preemption if previously enabled. Link: https://lkml.kernel.org/r/[email protected] CC: Petr Mladek <[email protected]> Cc: Guo Ren <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: "James E.J. Bottomley" <[email protected]> Cc: Helge Deller <[email protected]> Cc: Michael Ellerman <[email protected]> Cc: Benjamin Herrenschmidt <[email protected]> Cc: Paul Mackerras <[email protected]> Cc: Paul Walmsley <[email protected]> Cc: Palmer Dabbelt <[email protected]> Cc: Albert Ou <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Borislav Petkov <[email protected]> Cc: "H. Peter Anvin" <[email protected]> Cc: Josh Poimboeuf <[email protected]> Cc: Jiri Kosina <[email protected]> Cc: Joe Lawrence <[email protected]> Cc: Masami Hiramatsu <[email protected]> Cc: Nicholas Piggin <[email protected]> Cc: Jisheng Zhang <[email protected]> CC: Steven Rostedt <[email protected]> CC: Miroslav Benes <[email protected]> Reported-by: Abaci <[email protected]> Suggested-by: Peter Zijlstra <[email protected]> Signed-off-by: Michael Wang <[email protected]> [ Removed extra line in comment - SDR ] Signed-off-by: Steven Rostedt (VMware) <[email protected]>
This commit is contained in:
1 parent
2d2f6d4b8c
commit
ce5e48036c
9 files changed
+21
-32
No files matched your search
@@ -17,7 +17,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
return;
|
||||
|
||||
regs = ftrace_get_regs(fregs);
|
||||
preempt_disable_notrace();
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (!p) {
|
||||
p = get_kprobe((kprobe_opcode_t *)(ip - MCOUNT_INSN_SIZE));
|
||||
@@ -57,7 +56,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
}
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
@@ -211,7 +211,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
return;
|
||||
|
||||
regs = ftrace_get_regs(fregs);
|
||||
preempt_disable_notrace();
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (unlikely(!p) || kprobe_disabled(p))
|
||||
goto out;
|
||||
@@ -240,7 +239,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
}
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
@@ -26,7 +26,6 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
|
||||
return;
|
||||
|
||||
regs = ftrace_get_regs(fregs);
|
||||
preempt_disable_notrace();
|
||||
p = get_kprobe((kprobe_opcode_t *)nip);
|
||||
if (unlikely(!p) || kprobe_disabled(p))
|
||||
goto out;
|
||||
@@ -61,7 +60,6 @@ void kprobe_ftrace_handler(unsigned long nip, unsigned long parent_nip,
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
}
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
@@ -15,7 +15,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
preempt_disable_notrace();
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (unlikely(!p) || kprobe_disabled(p))
|
||||
goto out;
|
||||
@@ -52,7 +51,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
}
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
@@ -25,7 +25,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
preempt_disable_notrace();
|
||||
p = get_kprobe((kprobe_opcode_t *)ip);
|
||||
if (unlikely(!p) || kprobe_disabled(p))
|
||||
goto out;
|
||||
@@ -59,7 +58,6 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
|
||||
__this_cpu_write(current_kprobe, NULL);
|
||||
}
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(kprobe_ftrace_handler);
|
||||
|
||||
@@ -155,6 +155,9 @@ extern void ftrace_record_recursion(unsigned long ip, unsigned long parent_ip);
|
||||
# define do_ftrace_record_recursion(ip, pip) do { } while (0)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Preemption is promised to be disabled when return bit >= 0.
|
||||
*/
|
||||
static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsigned long pip,
|
||||
int start, int max)
|
||||
{
|
||||
@@ -189,14 +192,20 @@ static __always_inline int trace_test_and_set_recursion(unsigned long ip, unsign
|
||||
current->trace_recursion = val;
|
||||
barrier();
|
||||
|
||||
preempt_disable_notrace();
|
||||
|
||||
return bit + 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Preemption will be enabled (if it was previously enabled).
|
||||
*/
|
||||
static __always_inline void trace_clear_recursion(int bit)
|
||||
{
|
||||
if (!bit)
|
||||
return;
|
||||
|
||||
preempt_enable_notrace();
|
||||
barrier();
|
||||
bit--;
|
||||
trace_recursion_clear(bit);
|
||||
@@ -209,7 +218,7 @@ static __always_inline void trace_clear_recursion(int bit)
|
||||
* tracing recursed in the same context (normal vs interrupt),
|
||||
*
|
||||
* Returns: -1 if a recursion happened.
|
||||
* >= 0 if no recursion
|
||||
* >= 0 if no recursion.
|
||||
*/
|
||||
static __always_inline int ftrace_test_recursion_trylock(unsigned long ip,
|
||||
unsigned long parent_ip)
|
||||
|
||||
@@ -49,14 +49,15 @@ static void notrace klp_ftrace_handler(unsigned long ip,
|
||||
|
||||
ops = container_of(fops, struct klp_ops, fops);
|
||||
|
||||
/*
|
||||
* The ftrace_test_recursion_trylock() will disable preemption,
|
||||
* which is required for the variant of synchronize_rcu() that is
|
||||
* used to allow patching functions where RCU is not watching.
|
||||
* See klp_synchronize_transition() for more details.
|
||||
*/
|
||||
bit = ftrace_test_recursion_trylock(ip, parent_ip);
|
||||
if (WARN_ON_ONCE(bit < 0))
|
||||
return;
|
||||
/*
|
||||
* A variant of synchronize_rcu() is used to allow patching functions
|
||||
* where RCU is not watching, see klp_synchronize_transition().
|
||||
*/
|
||||
preempt_disable_notrace();
|
||||
|
||||
func = list_first_or_null_rcu(&ops->func_stack, struct klp_func,
|
||||
stack_node);
|
||||
@@ -120,7 +121,6 @@ static void notrace klp_ftrace_handler(unsigned long ip,
|
||||
klp_arch_set_pc(fregs, (unsigned long)func->new_func);
|
||||
|
||||
unlock:
|
||||
preempt_enable_notrace();
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
}
|
||||
|
||||
|
||||
+5
-10
@@ -7198,16 +7198,15 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
|
||||
struct ftrace_ops *op;
|
||||
int bit;
|
||||
|
||||
/*
|
||||
* The ftrace_test_and_set_recursion() will disable preemption,
|
||||
* which is required since some of the ops may be dynamically
|
||||
* allocated, they must be freed after a synchronize_rcu().
|
||||
*/
|
||||
bit = trace_test_and_set_recursion(ip, parent_ip, TRACE_LIST_START, TRACE_LIST_MAX);
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* Some of the ops may be dynamically allocated,
|
||||
* they must be freed after a synchronize_rcu().
|
||||
*/
|
||||
preempt_disable_notrace();
|
||||
|
||||
do_for_each_ftrace_op(op, ftrace_ops_list) {
|
||||
/* Stub functions don't need to be called nor tested */
|
||||
if (op->flags & FTRACE_OPS_FL_STUB)
|
||||
@@ -7231,7 +7230,6 @@ __ftrace_ops_list_func(unsigned long ip, unsigned long parent_ip,
|
||||
}
|
||||
} while_for_each_ftrace_op(op);
|
||||
out:
|
||||
preempt_enable_notrace();
|
||||
trace_clear_recursion(bit);
|
||||
}
|
||||
|
||||
@@ -7279,12 +7277,9 @@ static void ftrace_ops_assist_func(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
preempt_disable_notrace();
|
||||
|
||||
if (!(op->flags & FTRACE_OPS_FL_RCU) || rcu_is_watching())
|
||||
op->func(ip, parent_ip, op, fregs);
|
||||
|
||||
preempt_enable_notrace();
|
||||
trace_clear_recursion(bit);
|
||||
}
|
||||
NOKPROBE_SYMBOL(ftrace_ops_assist_func);
|
||||
|
||||
@@ -186,7 +186,6 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
return;
|
||||
|
||||
trace_ctx = tracing_gen_ctx();
|
||||
preempt_disable_notrace();
|
||||
|
||||
cpu = smp_processor_id();
|
||||
data = per_cpu_ptr(tr->array_buffer.data, cpu);
|
||||
@@ -194,7 +193,6 @@ function_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
trace_function(tr, ip, parent_ip, trace_ctx);
|
||||
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
preempt_enable_notrace();
|
||||
}
|
||||
|
||||
#ifdef CONFIG_UNWINDER_ORC
|
||||
@@ -298,8 +296,6 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
if (bit < 0)
|
||||
return;
|
||||
|
||||
preempt_disable_notrace();
|
||||
|
||||
cpu = smp_processor_id();
|
||||
data = per_cpu_ptr(tr->array_buffer.data, cpu);
|
||||
if (atomic_read(&data->disabled))
|
||||
@@ -324,7 +320,6 @@ function_no_repeats_trace_call(unsigned long ip, unsigned long parent_ip,
|
||||
|
||||
out:
|
||||
ftrace_test_recursion_unlock(bit);
|
||||
preempt_enable_notrace();
|
||||
}
|
||||
|
||||
static void
|
||||
|
||||
Reference in new issue
Block a user