diff options
Diffstat (limited to 'kernel/trace/trace.c')
-rw-r--r-- | kernel/trace/trace.c | 119 |
1 files changed, 116 insertions, 3 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index a3f1bc5d2a00..ed7b5d1e12f4 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <linux/ctype.h> | 36 | #include <linux/ctype.h> |
37 | #include <linux/init.h> | 37 | #include <linux/init.h> |
38 | #include <linux/poll.h> | 38 | #include <linux/poll.h> |
39 | #include <linux/nmi.h> | ||
39 | #include <linux/fs.h> | 40 | #include <linux/fs.h> |
40 | 41 | ||
41 | #include "trace.h" | 42 | #include "trace.h" |
@@ -352,6 +353,59 @@ static void wakeup_work_handler(struct work_struct *work) | |||
352 | static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler); | 353 | static DECLARE_DELAYED_WORK(wakeup_work, wakeup_work_handler); |
353 | 354 | ||
354 | /** | 355 | /** |
356 | * tracing_on - enable tracing buffers | ||
357 | * | ||
358 | * This function enables tracing buffers that may have been | ||
359 | * disabled with tracing_off. | ||
360 | */ | ||
361 | void tracing_on(void) | ||
362 | { | ||
363 | if (global_trace.buffer) | ||
364 | ring_buffer_record_on(global_trace.buffer); | ||
365 | /* | ||
366 | * This flag is only looked at when buffers haven't been | ||
367 | * allocated yet. We don't really care about the race | ||
368 | * between setting this flag and actually turning | ||
369 | * on the buffer. | ||
370 | */ | ||
371 | global_trace.buffer_disabled = 0; | ||
372 | } | ||
373 | EXPORT_SYMBOL_GPL(tracing_on); | ||
374 | |||
375 | /** | ||
376 | * tracing_off - turn off tracing buffers | ||
377 | * | ||
378 | * This function stops the tracing buffers from recording data. | ||
379 | * It does not disable any overhead the tracers themselves may | ||
380 | * be causing. This function simply causes all recording to | ||
381 | * the ring buffers to fail. | ||
382 | */ | ||
383 | void tracing_off(void) | ||
384 | { | ||
385 | if (global_trace.buffer) | ||
386 | ring_buffer_record_on(global_trace.buffer); | ||
387 | /* | ||
388 | * This flag is only looked at when buffers haven't been | ||
389 | * allocated yet. We don't really care about the race | ||
390 | * between setting this flag and actually turning | ||
391 | * on the buffer. | ||
392 | */ | ||
393 | global_trace.buffer_disabled = 1; | ||
394 | } | ||
395 | EXPORT_SYMBOL_GPL(tracing_off); | ||
396 | |||
397 | /** | ||
398 | * tracing_is_on - show state of ring buffers enabled | ||
399 | */ | ||
400 | int tracing_is_on(void) | ||
401 | { | ||
402 | if (global_trace.buffer) | ||
403 | return ring_buffer_record_is_on(global_trace.buffer); | ||
404 | return !global_trace.buffer_disabled; | ||
405 | } | ||
406 | EXPORT_SYMBOL_GPL(tracing_is_on); | ||
407 | |||
408 | /** | ||
355 | * trace_wake_up - wake up tasks waiting for trace input | 409 | * trace_wake_up - wake up tasks waiting for trace input |
356 | * | 410 | * |
357 | * Schedules a delayed work to wake up any task that is blocked on the | 411 | * Schedules a delayed work to wake up any task that is blocked on the |
@@ -1644,6 +1698,7 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, | |||
1644 | int cpu_file = iter->cpu_file; | 1698 | int cpu_file = iter->cpu_file; |
1645 | u64 next_ts = 0, ts; | 1699 | u64 next_ts = 0, ts; |
1646 | int next_cpu = -1; | 1700 | int next_cpu = -1; |
1701 | int next_size = 0; | ||
1647 | int cpu; | 1702 | int cpu; |
1648 | 1703 | ||
1649 | /* | 1704 | /* |
@@ -1675,9 +1730,12 @@ __find_next_entry(struct trace_iterator *iter, int *ent_cpu, | |||
1675 | next_cpu = cpu; | 1730 | next_cpu = cpu; |
1676 | next_ts = ts; | 1731 | next_ts = ts; |
1677 | next_lost = lost_events; | 1732 | next_lost = lost_events; |
1733 | next_size = iter->ent_size; | ||
1678 | } | 1734 | } |
1679 | } | 1735 | } |
1680 | 1736 | ||
1737 | iter->ent_size = next_size; | ||
1738 | |||
1681 | if (ent_cpu) | 1739 | if (ent_cpu) |
1682 | *ent_cpu = next_cpu; | 1740 | *ent_cpu = next_cpu; |
1683 | 1741 | ||
@@ -2764,12 +2822,12 @@ static const char readme_msg[] = | |||
2764 | "tracing mini-HOWTO:\n\n" | 2822 | "tracing mini-HOWTO:\n\n" |
2765 | "# mount -t debugfs nodev /sys/kernel/debug\n\n" | 2823 | "# mount -t debugfs nodev /sys/kernel/debug\n\n" |
2766 | "# cat /sys/kernel/debug/tracing/available_tracers\n" | 2824 | "# cat /sys/kernel/debug/tracing/available_tracers\n" |
2767 | "wakeup preemptirqsoff preemptoff irqsoff function sched_switch nop\n\n" | 2825 | "wakeup wakeup_rt preemptirqsoff preemptoff irqsoff function nop\n\n" |
2768 | "# cat /sys/kernel/debug/tracing/current_tracer\n" | 2826 | "# cat /sys/kernel/debug/tracing/current_tracer\n" |
2769 | "nop\n" | 2827 | "nop\n" |
2770 | "# echo sched_switch > /sys/kernel/debug/tracing/current_tracer\n" | 2828 | "# echo wakeup > /sys/kernel/debug/tracing/current_tracer\n" |
2771 | "# cat /sys/kernel/debug/tracing/current_tracer\n" | 2829 | "# cat /sys/kernel/debug/tracing/current_tracer\n" |
2772 | "sched_switch\n" | 2830 | "wakeup\n" |
2773 | "# cat /sys/kernel/debug/tracing/trace_options\n" | 2831 | "# cat /sys/kernel/debug/tracing/trace_options\n" |
2774 | "noprint-parent nosym-offset nosym-addr noverbose\n" | 2832 | "noprint-parent nosym-offset nosym-addr noverbose\n" |
2775 | "# echo print-parent > /sys/kernel/debug/tracing/trace_options\n" | 2833 | "# echo print-parent > /sys/kernel/debug/tracing/trace_options\n" |
@@ -4567,6 +4625,55 @@ static __init void create_trace_options_dir(void) | |||
4567 | create_trace_option_core_file(trace_options[i], i); | 4625 | create_trace_option_core_file(trace_options[i], i); |
4568 | } | 4626 | } |
4569 | 4627 | ||
4628 | static ssize_t | ||
4629 | rb_simple_read(struct file *filp, char __user *ubuf, | ||
4630 | size_t cnt, loff_t *ppos) | ||
4631 | { | ||
4632 | struct ring_buffer *buffer = filp->private_data; | ||
4633 | char buf[64]; | ||
4634 | int r; | ||
4635 | |||
4636 | if (buffer) | ||
4637 | r = ring_buffer_record_is_on(buffer); | ||
4638 | else | ||
4639 | r = 0; | ||
4640 | |||
4641 | r = sprintf(buf, "%d\n", r); | ||
4642 | |||
4643 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | ||
4644 | } | ||
4645 | |||
4646 | static ssize_t | ||
4647 | rb_simple_write(struct file *filp, const char __user *ubuf, | ||
4648 | size_t cnt, loff_t *ppos) | ||
4649 | { | ||
4650 | struct ring_buffer *buffer = filp->private_data; | ||
4651 | unsigned long val; | ||
4652 | int ret; | ||
4653 | |||
4654 | ret = kstrtoul_from_user(ubuf, cnt, 10, &val); | ||
4655 | if (ret) | ||
4656 | return ret; | ||
4657 | |||
4658 | if (buffer) { | ||
4659 | if (val) | ||
4660 | ring_buffer_record_on(buffer); | ||
4661 | else | ||
4662 | ring_buffer_record_off(buffer); | ||
4663 | } | ||
4664 | |||
4665 | (*ppos)++; | ||
4666 | |||
4667 | return cnt; | ||
4668 | } | ||
4669 | |||
4670 | static const struct file_operations rb_simple_fops = { | ||
4671 | .open = tracing_open_generic, | ||
4672 | .read = rb_simple_read, | ||
4673 | .write = rb_simple_write, | ||
4674 | .llseek = default_llseek, | ||
4675 | }; | ||
4676 | |||
4570 | static __init int tracer_init_debugfs(void) | 4677 | static __init int tracer_init_debugfs(void) |
4571 | { | 4678 | { |
4572 | struct dentry *d_tracer; | 4679 | struct dentry *d_tracer; |
@@ -4626,6 +4733,9 @@ static __init int tracer_init_debugfs(void) | |||
4626 | trace_create_file("trace_clock", 0644, d_tracer, NULL, | 4733 | trace_create_file("trace_clock", 0644, d_tracer, NULL, |
4627 | &trace_clock_fops); | 4734 | &trace_clock_fops); |
4628 | 4735 | ||
4736 | trace_create_file("tracing_on", 0644, d_tracer, | ||
4737 | global_trace.buffer, &rb_simple_fops); | ||
4738 | |||
4629 | #ifdef CONFIG_DYNAMIC_FTRACE | 4739 | #ifdef CONFIG_DYNAMIC_FTRACE |
4630 | trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, | 4740 | trace_create_file("dyn_ftrace_total_info", 0444, d_tracer, |
4631 | &ftrace_update_tot_cnt, &tracing_dyn_info_fops); | 4741 | &ftrace_update_tot_cnt, &tracing_dyn_info_fops); |
@@ -4798,6 +4908,7 @@ __ftrace_dump(bool disable_tracing, enum ftrace_dump_mode oops_dump_mode) | |||
4798 | if (ret != TRACE_TYPE_NO_CONSUME) | 4908 | if (ret != TRACE_TYPE_NO_CONSUME) |
4799 | trace_consume(&iter); | 4909 | trace_consume(&iter); |
4800 | } | 4910 | } |
4911 | touch_nmi_watchdog(); | ||
4801 | 4912 | ||
4802 | trace_printk_seq(&iter.seq); | 4913 | trace_printk_seq(&iter.seq); |
4803 | } | 4914 | } |
@@ -4863,6 +4974,8 @@ __init static int tracer_alloc_buffers(void) | |||
4863 | goto out_free_cpumask; | 4974 | goto out_free_cpumask; |
4864 | } | 4975 | } |
4865 | global_trace.entries = ring_buffer_size(global_trace.buffer); | 4976 | global_trace.entries = ring_buffer_size(global_trace.buffer); |
4977 | if (global_trace.buffer_disabled) | ||
4978 | tracing_off(); | ||
4866 | 4979 | ||
4867 | 4980 | ||
4868 | #ifdef CONFIG_TRACER_MAX_TRACE | 4981 | #ifdef CONFIG_TRACER_MAX_TRACE |