Commit f217c44e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'trace-fixes-v3.14-rc7-v2' of...

Merge tag 'trace-fixes-v3.14-rc7-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace

Pull tracing fix from Steven Rostedt:
 "While on my flight to Linux Collaboration Summit, I was working on my
  slides for the event trigger tutorial.  I booted a 3.14-rc7 kernel to
  perform what I wanted to teach and cut and paste it into my slides.
  When I tried the traceon event trigger with a condition attached to it
  (turns tracing on only if a field of the trigger event matches a
  condition set by the user), nothing happened.  Tracing would not turn
  on.  I stopped working on my presentation in order to find what was
  wrong.

  It ended up being the way trace event triggers work when they have
  conditions.  Instead of copying the fields, the condition code just
  looks at the fields that were copied into the ring buffer.  This works
  great, unless tracing is off.  That's because when the event is
  reserved on the ring buffer, the ring buffer returns a NULL pointer,
  this tells the tracing code that the ring buffer is disabled.  This
  ends up being a problem for the traceon trigger if it is using this
  information to check its condition.

  Luckily the code that checks if tracing is on returns the ring buffer
  to use (because the ring buffer is determined by the event file also
  passed to that field).  I was able to easily solve this bug by
  checking in that helper function if the returned ring buffer entry is
  NULL, and if so, also check the file flag if it has a trace event
  trigger condition, and if so, to pass back a temp ring buffer to use.
  This will allow the trace event trigger condition to still test the
  event fields, but nothing will be recorded"

* tag 'trace-fixes-v3.14-rc7-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace:
  tracing: Fix traceon trigger condition to actually turn tracing on
parents fce7fc79 2c4a33ab
...@@ -1600,15 +1600,31 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer, ...@@ -1600,15 +1600,31 @@ void trace_buffer_unlock_commit(struct ring_buffer *buffer,
} }
EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit); EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit);
static struct ring_buffer *temp_buffer;
struct ring_buffer_event * struct ring_buffer_event *
trace_event_buffer_lock_reserve(struct ring_buffer **current_rb, trace_event_buffer_lock_reserve(struct ring_buffer **current_rb,
struct ftrace_event_file *ftrace_file, struct ftrace_event_file *ftrace_file,
int type, unsigned long len, int type, unsigned long len,
unsigned long flags, int pc) unsigned long flags, int pc)
{ {
struct ring_buffer_event *entry;
*current_rb = ftrace_file->tr->trace_buffer.buffer; *current_rb = ftrace_file->tr->trace_buffer.buffer;
return trace_buffer_lock_reserve(*current_rb, entry = trace_buffer_lock_reserve(*current_rb,
type, len, flags, pc); type, len, flags, pc);
/*
* If tracing is off, but we have triggers enabled
* we still need to look at the event data. Use the temp_buffer
* to store the trace event for the tigger to use. It's recusive
* safe and will not be recorded anywhere.
*/
if (!entry && ftrace_file->flags & FTRACE_EVENT_FL_TRIGGER_COND) {
*current_rb = temp_buffer;
entry = trace_buffer_lock_reserve(*current_rb,
type, len, flags, pc);
}
return entry;
} }
EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve); EXPORT_SYMBOL_GPL(trace_event_buffer_lock_reserve);
...@@ -6494,11 +6510,16 @@ __init static int tracer_alloc_buffers(void) ...@@ -6494,11 +6510,16 @@ __init static int tracer_alloc_buffers(void)
raw_spin_lock_init(&global_trace.start_lock); raw_spin_lock_init(&global_trace.start_lock);
/* Used for event triggers */
temp_buffer = ring_buffer_alloc(PAGE_SIZE, RB_FL_OVERWRITE);
if (!temp_buffer)
goto out_free_cpumask;
/* TODO: make the number of buffers hot pluggable with CPUS */ /* TODO: make the number of buffers hot pluggable with CPUS */
if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) { if (allocate_trace_buffers(&global_trace, ring_buf_size) < 0) {
printk(KERN_ERR "tracer: failed to allocate ring buffer!\n"); printk(KERN_ERR "tracer: failed to allocate ring buffer!\n");
WARN_ON(1); WARN_ON(1);
goto out_free_cpumask; goto out_free_temp_buffer;
} }
if (global_trace.buffer_disabled) if (global_trace.buffer_disabled)
...@@ -6540,6 +6561,8 @@ __init static int tracer_alloc_buffers(void) ...@@ -6540,6 +6561,8 @@ __init static int tracer_alloc_buffers(void)
return 0; return 0;
out_free_temp_buffer:
ring_buffer_free(temp_buffer);
out_free_cpumask: out_free_cpumask:
free_percpu(global_trace.trace_buffer.data); free_percpu(global_trace.trace_buffer.data);
#ifdef CONFIG_TRACER_MAX_TRACE #ifdef CONFIG_TRACER_MAX_TRACE
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment