aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.c
diff options
context:
space:
mode:
authorSteven Rostedt (Red Hat) <rostedt@goodmis.org>2013-07-01 15:58:24 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-07-01 20:34:28 -0400
commit10246fa35d4ffdfe472185d4cbf9c2dfd9a9f023 (patch)
tree277cb4041486bfe87730fd767b2a8072330211b9 /kernel/trace/trace.c
parentb04d52e368e2cf526abb2bab61f304eaea126af2 (diff)
tracing: Use flag buffer_disabled for irqsoff tracer
If the ring buffer is disabled and the irqsoff tracer records a trace it will clear out its buffer and lose the data it had previously recorded. Currently there's a callback when writing to the tracing_of file, but if tracing is disabled via the function tracer trigger, it will not inform the irqsoff tracer to stop recording. By using the "mirror" flag (buffer_disabled) in the trace_array, that keeps track of the status of the trace_array's buffer, it gives the irqsoff tracer a fast way to know if it should record a new trace or not. The flag may be a little behind the real state of the buffer, but it should not affect the trace too much. It's more important for the irqsoff tracer to be fast. Reported-by: Dave Jones <davej@redhat.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r--kernel/trace/trace.c101
1 files changed, 70 insertions, 31 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index c4c9296b1916..0dc50711d656 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -226,9 +226,24 @@ cycle_t ftrace_now(int cpu)
226 return ts; 226 return ts;
227} 227}
228 228
229/**
230 * tracing_is_enabled - Show if global_trace has been disabled
231 *
232 * Shows if the global trace has been enabled or not. It uses the
233 * mirror flag "buffer_disabled" to be used in fast paths such as for
234 * the irqsoff tracer. But it may be inaccurate due to races. If you
235 * need to know the accurate state, use tracing_is_on() which is a little
236 * slower, but accurate.
237 */
229int tracing_is_enabled(void) 238int tracing_is_enabled(void)
230{ 239{
231 return tracing_is_on(); 240 /*
241 * For quick access (irqsoff uses this in fast path), just
242 * return the mirror variable of the state of the ring buffer.
243 * It's a little racy, but we don't really care.
244 */
245 smp_rmb();
246 return !global_trace.buffer_disabled;
232} 247}
233 248
234/* 249/*
@@ -341,6 +356,23 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
341 TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE | 356 TRACE_ITER_GRAPH_TIME | TRACE_ITER_RECORD_CMD | TRACE_ITER_OVERWRITE |
342 TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION; 357 TRACE_ITER_IRQ_INFO | TRACE_ITER_MARKERS | TRACE_ITER_FUNCTION;
343 358
359void tracer_tracing_on(struct trace_array *tr)
360{
361 if (tr->trace_buffer.buffer)
362 ring_buffer_record_on(tr->trace_buffer.buffer);
363 /*
364 * This flag is looked at when buffers haven't been allocated
365 * yet, or by some tracers (like irqsoff), that just want to
366 * know if the ring buffer has been disabled, but it can handle
367 * races of where it gets disabled but we still do a record.
368 * As the check is in the fast path of the tracers, it is more
369 * important to be fast than accurate.
370 */
371 tr->buffer_disabled = 0;
372 /* Make the flag seen by readers */
373 smp_wmb();
374}
375
344/** 376/**
345 * tracing_on - enable tracing buffers 377 * tracing_on - enable tracing buffers
346 * 378 *
@@ -349,15 +381,7 @@ unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK |
349 */ 381 */
350void tracing_on(void) 382void tracing_on(void)
351{ 383{
352 if (global_trace.trace_buffer.buffer) 384 tracer_tracing_on(&global_trace);
353 ring_buffer_record_on(global_trace.trace_buffer.buffer);
354 /*
355 * This flag is only looked at when buffers haven't been
356 * allocated yet. We don't really care about the race
357 * between setting this flag and actually turning
358 * on the buffer.
359 */
360 global_trace.buffer_disabled = 0;
361} 385}
362EXPORT_SYMBOL_GPL(tracing_on); 386EXPORT_SYMBOL_GPL(tracing_on);
363 387
@@ -551,6 +575,23 @@ void tracing_snapshot_alloc(void)
551EXPORT_SYMBOL_GPL(tracing_snapshot_alloc); 575EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
552#endif /* CONFIG_TRACER_SNAPSHOT */ 576#endif /* CONFIG_TRACER_SNAPSHOT */
553 577
578void tracer_tracing_off(struct trace_array *tr)
579{
580 if (tr->trace_buffer.buffer)
581 ring_buffer_record_off(tr->trace_buffer.buffer);
582 /*
583 * This flag is looked at when buffers haven't been allocated
584 * yet, or by some tracers (like irqsoff), that just want to
585 * know if the ring buffer has been disabled, but it can handle
586 * races of where it gets disabled but we still do a record.
587 * As the check is in the fast path of the tracers, it is more
588 * important to be fast than accurate.
589 */
590 tr->buffer_disabled = 1;
591 /* Make the flag seen by readers */
592 smp_wmb();
593}
594
554/** 595/**
555 * tracing_off - turn off tracing buffers 596 * tracing_off - turn off tracing buffers
556 * 597 *
@@ -561,15 +602,7 @@ EXPORT_SYMBOL_GPL(tracing_snapshot_alloc);
561 */ 602 */
562void tracing_off(void) 603void tracing_off(void)
563{ 604{
564 if (global_trace.trace_buffer.buffer) 605 tracer_tracing_off(&global_trace);
565 ring_buffer_record_off(global_trace.trace_buffer.buffer);
566 /*
567 * This flag is only looked at when buffers haven't been
568 * allocated yet. We don't really care about the race
569 * between setting this flag and actually turning
570 * on the buffer.
571 */
572 global_trace.buffer_disabled = 1;
573} 606}
574EXPORT_SYMBOL_GPL(tracing_off); 607EXPORT_SYMBOL_GPL(tracing_off);
575 608
@@ -580,13 +613,24 @@ void disable_trace_on_warning(void)
580} 613}
581 614
582/** 615/**
616 * tracer_tracing_is_on - show real state of ring buffer enabled
617 * @tr : the trace array to know if ring buffer is enabled
618 *
619 * Shows real state of the ring buffer if it is enabled or not.
620 */
621int tracer_tracing_is_on(struct trace_array *tr)
622{
623 if (tr->trace_buffer.buffer)
624 return ring_buffer_record_is_on(tr->trace_buffer.buffer);
625 return !tr->buffer_disabled;
626}
627
628/**
583 * tracing_is_on - show state of ring buffers enabled 629 * tracing_is_on - show state of ring buffers enabled
584 */ 630 */
585int tracing_is_on(void) 631int tracing_is_on(void)
586{ 632{
587 if (global_trace.trace_buffer.buffer) 633 return tracer_tracing_is_on(&global_trace);
588 return ring_buffer_record_is_on(global_trace.trace_buffer.buffer);
589 return !global_trace.buffer_disabled;
590} 634}
591EXPORT_SYMBOL_GPL(tracing_is_on); 635EXPORT_SYMBOL_GPL(tracing_is_on);
592 636
@@ -3958,7 +4002,7 @@ static int tracing_wait_pipe(struct file *filp)
3958 * 4002 *
3959 * iter->pos will be 0 if we haven't read anything. 4003 * iter->pos will be 0 if we haven't read anything.
3960 */ 4004 */
3961 if (!tracing_is_enabled() && iter->pos) 4005 if (!tracing_is_on() && iter->pos)
3962 break; 4006 break;
3963 } 4007 }
3964 4008
@@ -5631,15 +5675,10 @@ rb_simple_read(struct file *filp, char __user *ubuf,
5631 size_t cnt, loff_t *ppos) 5675 size_t cnt, loff_t *ppos)
5632{ 5676{
5633 struct trace_array *tr = filp->private_data; 5677 struct trace_array *tr = filp->private_data;
5634 struct ring_buffer *buffer = tr->trace_buffer.buffer;
5635 char buf[64]; 5678 char buf[64];
5636 int r; 5679 int r;
5637 5680
5638 if (buffer) 5681 r = tracer_tracing_is_on(tr);
5639 r = ring_buffer_record_is_on(buffer);
5640 else
5641 r = 0;
5642
5643 r = sprintf(buf, "%d\n", r); 5682 r = sprintf(buf, "%d\n", r);
5644 5683
5645 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); 5684 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
@@ -5661,11 +5700,11 @@ rb_simple_write(struct file *filp, const char __user *ubuf,
5661 if (buffer) { 5700 if (buffer) {
5662 mutex_lock(&trace_types_lock); 5701 mutex_lock(&trace_types_lock);
5663 if (val) { 5702 if (val) {
5664 ring_buffer_record_on(buffer); 5703 tracer_tracing_on(tr);
5665 if (tr->current_trace->start) 5704 if (tr->current_trace->start)
5666 tr->current_trace->start(tr); 5705 tr->current_trace->start(tr);
5667 } else { 5706 } else {
5668 ring_buffer_record_off(buffer); 5707 tracer_tracing_off(tr);
5669 if (tr->current_trace->stop) 5708 if (tr->current_trace->stop)
5670 tr->current_trace->stop(tr); 5709 tr->current_trace->stop(tr);
5671 } 5710 }