Skip to content

Commit da5b3eb

Browse files
joelagnelrostedt
authored andcommitted
tracing: irqsoff: Account for additional preempt_disable
Recently we tried to make the preemptirqsoff tracer to use irqsoff tracepoint probes. However this causes issues as reported by Masami: [2.271078] Testing tracer preemptirqsoff: .. no entries found ..FAILED! [2.381015] WARNING: CPU: 0 PID: 1 at /home/mhiramat/ksrc/linux/kernel/ trace/trace.c:1512 run_tracer_selftest+0xf3/0x154 This is due to the tracepoint code increasing the preempt nesting count by calling an additional preempt_disable before calling into the preemptoff tracer which messes up the preempt_count() check in tracer_hardirqs_off. To fix this, make the irqsoff tracer probes balance the additional outer preempt_disable with a preempt_enable_notrace. The other way to fix this is to just use SRCU for all tracepoints. However we can't do that because we can't use NMIs from RCU context. Link: http://lkml.kernel.org/r/[email protected] Fixes: c3bc8fd ("tracing: Centralize preemptirq tracepoints and unify their usage") Fixes: e6753f2 ("tracepoint: Make rcuidle tracepoint callers use SRCU") Reported-by: Masami Hiramatsu <[email protected]> Tested-by: Masami Hiramatsu <[email protected]> Signed-off-by: Joel Fernandes (Google) <[email protected]> Signed-off-by: Steven Rostedt (VMware) <[email protected]>
1 parent da25a67 commit da5b3eb

File tree

1 file changed

+26
-0
lines changed

1 file changed

+26
-0
lines changed

kernel/trace/trace_irqsoff.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,14 +603,40 @@ static void irqsoff_tracer_stop(struct trace_array *tr)
603603
*/
604604
static void tracer_hardirqs_on(void *none, unsigned long a0, unsigned long a1)
605605
{
606+
/*
607+
* Tracepoint probes are expected to be called with preempt disabled,
608+
* We don't care about being called with preempt disabled but we need
609+
* to know in the future if that changes so we can remove the next
610+
* preempt_enable.
611+
*/
612+
WARN_ON_ONCE(!preempt_count());
613+
614+
/* Tracepoint probes disable preemption atleast once, account for that */
615+
preempt_enable_notrace();
616+
606617
if (!preempt_trace() && irq_trace())
607618
stop_critical_timing(a0, a1);
619+
620+
preempt_disable_notrace();
608621
}
609622

610623
static void tracer_hardirqs_off(void *none, unsigned long a0, unsigned long a1)
611624
{
625+
/*
626+
* Tracepoint probes are expected to be called with preempt disabled,
627+
* We don't care about being called with preempt disabled but we need
628+
* to know in the future if that changes so we can remove the next
629+
* preempt_enable.
630+
*/
631+
WARN_ON_ONCE(!preempt_count());
632+
633+
/* Tracepoint probes disable preemption atleast once, account for that */
634+
preempt_enable_notrace();
635+
612636
if (!preempt_trace() && irq_trace())
613637
start_critical_timing(a0, a1);
638+
639+
preempt_disable_notrace();
614640
}
615641

616642
static int irqsoff_tracer_init(struct trace_array *tr)

0 commit comments

Comments
 (0)