]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
tracing: Add a no-rcu-check version of trace_##event##_enabled()
authorSteven Rostedt <rostedt@goodmis.org>
Wed, 1 Jul 2026 17:27:44 +0000 (13:27 -0400)
committerSteven Rostedt <rostedt@goodmis.org>
Tue, 7 Jul 2026 14:42:29 +0000 (10:42 -0400)
Tracepoints require that RCU is watching. To prevent them from being used
in places that RCU is not watching, the trace_##event() macro always
calls rcu_is_watching() even when the event is not enabled and warns if
RCU is not watching. This is to make sure a warning is triggered even if
the tracepoint is never enabled (as it is only a bug when it is).

It was noticed that tracepoints could be hidden within
trace_#event#_enabled() calls, which are used to do extra work for the
tracepoint only if the tracepoint is enabled. But this also can hide the
fact that a tracepoint is placed in a location that can be called when RCU
is not watching.

Commit 9764e731ef6ab ("tracepoint: Add lockdep rcu_is_watching() check to
trace_##name##_enabled()") added a check to the trace_##event##_enabled()
macro to make sure RCU is watching when it is called to make sure not to
hide the bug of a tracepoint being called when RCU is not watching.

There is one case in the irq_disable tracepoint where it is within a
trace_irq_disable_enabled() block, but it checks if RCU is watching, and
if it isn't, it makes a call to ct_irq_enter() that makes RCU watch again.
But because trace_irq_disable_enabled() now checks if RCU is watching and
will trigger if it isn't. This is a false warning as the code within
the block handles this case.

Add a new internal macro __trace_##event##_enabled() that doesn't check if
RCU is watching, and convert the irq_enable/disable tracepoints over to
it.

Link: https://patch.msgid.link/20260701132744.6a7fc68b@robin
Reported-by: Geert Uytterhoeven <geert@linux-m68k.org>
Closes: https://lore.kernel.org/all/CAMuHMdXud_RpWag_hFqa2ByBGRxg6KnxGL1ObCWZrpTsk3TfAw@mail.gmail.com/
Fixes: 9764e731ef6ab ("tracepoint: Add lockdep rcu_is_watching() check to trace_##name##_enabled()")
Tested-by: Geert Uytterhoeven <geert+renesas@glider.be>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
include/linux/tracepoint.h
kernel/trace/trace_preemptirq.c

index 4a0c36f40fe2c25ff6533e13df015c35a3eb722b..e0d838c9ce9382802d9a86b8581b175854dad8b9 100644 (file)
@@ -292,13 +292,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
        {                                                               \
        }                                                               \
        static inline bool                                              \
+       __trace_##name##_enabled(void)                                  \
+       {                                                               \
+               return static_branch_unlikely(&__tracepoint_##name.key);\
+       }                                                               \
+       static inline bool                                              \
        trace_##name##_enabled(void)                                    \
        {                                                               \
                if (IS_ENABLED(CONFIG_LOCKDEP)) {                       \
                        WARN_ONCE(!rcu_is_watching(),                   \
                                  "RCU not watching for tracepoint");   \
                }                                                       \
-               return static_branch_unlikely(&__tracepoint_##name.key);\
+               return __trace_##name##_enabled();                      \
        }
 
 #define __DECLARE_TRACE(name, proto, args, cond, data_proto)                   \
@@ -457,6 +462,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
        {                                                               \
        }                                                               \
        static inline bool                                              \
+       __trace_##name##_enabled(void)                                  \
+       {                                                               \
+               return false;                                           \
+       }                                                               \
+       static inline bool                                              \
        trace_##name##_enabled(void)                                    \
        {                                                               \
                return false;                                           \
index 0c42b15c380047b44efdd4b2c6395d6b77b9ccf7..b63e3558948f7a8d764e95d1f4468a55cda62d6f 100644 (file)
@@ -30,7 +30,7 @@
 #else
 #define trace(point, args)                                     \
        do {                                                    \
-               if (trace_##point##_enabled()) {                \
+               if (__trace_##point##_enabled()) {              \
                        bool exit_rcu = false;                  \
                        if (in_nmi())                           \
                                break;                          \