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 |
