History

tracing: Add a no-rcu-check version of trace_##event##_enabled()

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.

Steven Rostedt committed 4 months ago

Commit 1e67bb61 parent 0a607082 files · +12 −2Browse files

Unified · Split

2 files
  1. include/linux/tracepoint.h +11 −1
  2. kernel/trace/trace_preemptirq.c +1 −1
include/linux/tracepoint.h+11−1
@@ -292,13 +292,18 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · 291 unmodified lines
292 { \292 { \
293 } \293 } \
294 static inline bool \294 static inline bool \
295 __trace_##name##_enabled(void) \
296 { \
297 return static_branch_unlikely(&__tracepoint_##name.key);\
298 } \
299 static inline bool \
295 trace_##name##_enabled(void) \300 trace_##name##_enabled(void) \
296 { \301 { \
297 if (IS_ENABLED(CONFIG_LOCKDEP)) { \302 if (IS_ENABLED(CONFIG_LOCKDEP)) { \
298 WARN_ONCE(!rcu_is_watching(), \303 WARN_ONCE(!rcu_is_watching(), \
299 "RCU not watching for tracepoint"); \304 "RCU not watching for tracepoint"); \
300 } \305 } \
301 return static_branch_unlikely(&__tracepoint_##name.key);\306 return __trace_##name##_enabled(); \
302 }307 }
303 308
304#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \309#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
@@ -457,6 +462,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p) · 152 unmodified lines
457 { \462 { \
458 } \463 } \
459 static inline bool \464 static inline bool \
465 __trace_##name##_enabled(void) \
466 { \
467 return false; \
468 } \
469 static inline bool \
460 trace_##name##_enabled(void) \470 trace_##name##_enabled(void) \
461 { \471 { \
462 return false; \472 return false; \
kernel/trace/trace_preemptirq.c+1−1
@@ -30,7 +30,7 @@ · 29 unmodified lines
30#else30#else
31#define trace(point, args) \31#define trace(point, args) \
32 do { \32 do { \
33 if (trace_##point##_enabled()) { \33 if (__trace_##point##_enabled()) { \
34 bool exit_rcu = false; \34 bool exit_rcu = false; \
35 if (in_nmi()) \35 if (in_nmi()) \
36 break; \36 break; \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t