diff options
author | Steven Rostedt (Red Hat) <rostedt@goodmis.org> | 2014-03-25 23:39:41 -0400 |
---|---|---|
committer | Steven Rostedt <rostedt@goodmis.org> | 2014-03-25 23:39:41 -0400 |
commit | 2c4a33aba5f9ea3a28f2e40351f078d95f00786b (patch) | |
tree | 657da8f44eaa6331bd8bfa4789f10b152bc8104c /kernel | |
parent | 87291347c49dc40aa339f587b209618201c2e527 (diff) |
tracing: Fix traceon trigger condition to actually turn tracing on
While working on my tutorial for 2014 Linux Collaboration Summit
I found that the traceon trigger did not work when conditions were
used. The other triggers worked fine though. Looking into it, it
is because of the way the triggers use the ring buffer to store
the fields it will use for the condition. But if tracing is off, nothing
is stored in the buffer, and the tracepoint exits before calling the
trigger to test the condition. This is fine for all the triggers that
only work when tracing is on, but for traceon trigger that is to
work when tracing is off, nothing happens.
The fix is simple, just use a temp ring buffer to record the event
if tracing is off and the event has a trace event conditional trigger
enabled. The rest of the tracepoint code will work just fine, but
the tracepoint wont be recorded in the other buffers.
Cc: Tom Zanussi <tom.zanussi@linux.intel.com>
Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/trace/trace.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index 815c878f409b..24c1f2382557 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -1600,15 +1600,31 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer, | |||
1600 | } | 1600 | } |
1601 | EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit); | 1601 | EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit); |
1602 | 1602 | ||
1603 | static struct ring_buffer *temp_buffer; | ||
1604 | |||
1603 | struct ring_buffer_event * | 1605 | struct ring_buffer_event * |
1604 | trace_event_buffer_lock_reserve(struct ring_buffer **current_rb, | 1606 | trace_event_buffer_lock_reserve(struct ring_buffer **current_rb, |
1605 | struct ftrace_event_file *ftrace_file, | 1607 | struct ftrace_event_file *ftrace_file, |
1606 | int type, unsigned long len, | 1608 | int type, unsigned long len, |
1607 | unsigned long flags, int pc) | 1609 | unsigned long flags, int pc) |
1608 | { | 1610 | { |
1611 | struct ring_buffer_event *entry; | ||
1612 | |||
1609 | *current_rb = ftrace_file->tr->trace_buffer.buffer; | 1613 | *current_rb = ftrace_file->tr->trace_buffer.buffer; |
1610 | return trace_buffer_lock_reserve(*current_rb, | 1614 | entry = trace_buffer_lock_reserve(*current_rb, |
1611 | type, len, flags, pc); | 1615 | type, len, flags, pc); |
1616 | /* | ||
1617 | * If tracing is off, but we have triggers enabled | ||
1618 | * we still need to look at the event data. Use the temp_buffer | ||
1619 | * to store the trace event for the tigger to use. It's recusive | ||
1620 | * safe and will not be recorded anywhere. | ||
1621 | */ | ||
1622 | if (!entry && ftrace_file->flags & FTRACE_EVENT_FL_TRIGGER_COND) { | ||
1623 | *current_rb = temp_buffer; | ||
1624 | entry = trace_buffer_lock_reserve(*current_rb, | ||
1625 | type, len, flags, pc); | ||
1626 | } | ||
1627 | return entry; | ||
1612 | } | 1628 | } |
1613 | EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve); | 1629 | EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve); |
1614 | 1630 | ||
@@ -6494,11 +6510,16 @@ __init static int tracer_alloc_buffers(void) | |||
6494 | 6510 | ||
6495 | raw_spin_lock_init(&global_trace.start_lock); | 6511 | raw_spin_lock_init(&global_trace.start_lock); |
6496 | 6512 | ||
6513 | /* Used for event triggers */ | ||
6514 | temp_buffer = ring_buffer_alloc(PAGE_SIZE, RB_FL_OVERWRITE); | ||
6515 | if (!temp_buffer) | ||
6516 | goto out_free_cpumask; | ||
6517 | |||
6497 | /* TODO: make the number of buffers hot pluggable with CPUS */ | 6518 | /* TODO: make the number of buffers hot pluggable with CPUS */ |
6498 | if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) { | 6519 | if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) { |
6499 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); | 6520 | printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); |
6500 | WARN_ON(1); | 6521 | WARN_ON(1); |
6501 | goto out_free_cpumask; | 6522 | goto out_free_temp_buffer; |
6502 | } | 6523 | } |
6503 | 6524 | ||
6504 | if (global_trace.buffer_disabled) | 6525 | if (global_trace.buffer_disabled) |
@@ -6540,6 +6561,8 @@ __init static int tracer_alloc_buffers(void) | |||
6540 | 6561 | ||
6541 | return 0; | 6562 | return 0; |
6542 | 6563 | ||
6564 | out_free_temp_buffer: | ||
6565 | ring_buffer_free(temp_buffer); | ||
6543 | out_free_cpumask: | 6566 | out_free_cpumask: |
6544 | free_percpu(global_trace.trace_buffer.data); | 6567 | free_percpu(global_trace.trace_buffer.data); |
6545 | #ifdef CONFIG_TRACER_MAX_TRACE | 6568 | #ifdef CONFIG_TRACER_MAX_TRACE |