diff options
Diffstat (limited to 'kernel/trace/trace.c')
| -rw-r--r-- | kernel/trace/trace.c | 976 |
1 files changed, 811 insertions, 165 deletions
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index d86e3252f300..79db26e8216e 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/gfp.h> | 30 | #include <linux/gfp.h> |
| 31 | #include <linux/fs.h> | 31 | #include <linux/fs.h> |
| 32 | #include <linux/kprobes.h> | 32 | #include <linux/kprobes.h> |
| 33 | #include <linux/seq_file.h> | ||
| 33 | #include <linux/writeback.h> | 34 | #include <linux/writeback.h> |
| 34 | 35 | ||
| 35 | #include <linux/stacktrace.h> | 36 | #include <linux/stacktrace.h> |
| @@ -43,6 +44,38 @@ | |||
| 43 | unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX; | 44 | unsigned long __read_mostly tracing_max_latency = (cycle_t)ULONG_MAX; |
| 44 | unsigned long __read_mostly tracing_thresh; | 45 | unsigned long __read_mostly tracing_thresh; |
| 45 | 46 | ||
| 47 | /* | ||
| 48 | * We need to change this state when a selftest is running. | ||
| 49 | * A selftest will lurk into the ring-buffer to count the | ||
| 50 | * entries inserted during the selftest although some concurrent | ||
| 51 | * insertions into the ring-buffer such as ftrace_printk could occurred | ||
| 52 | * at the same time, giving false positive or negative results. | ||
| 53 | */ | ||
| 54 | static bool __read_mostly tracing_selftest_running; | ||
| 55 | |||
| 56 | /* For tracers that don't implement custom flags */ | ||
| 57 | static struct tracer_opt dummy_tracer_opt[] = { | ||
| 58 | { } | ||
| 59 | }; | ||
| 60 | |||
| 61 | static struct tracer_flags dummy_tracer_flags = { | ||
| 62 | .val = 0, | ||
| 63 | .opts = dummy_tracer_opt | ||
| 64 | }; | ||
| 65 | |||
| 66 | static int dummy_set_flag(u32 old_flags, u32 bit, int set) | ||
| 67 | { | ||
| 68 | return 0; | ||
| 69 | } | ||
| 70 | |||
| 71 | /* | ||
| 72 | * Kill all tracing for good (never come back). | ||
| 73 | * It is initialized to 1 but will turn to zero if the initialization | ||
| 74 | * of the tracer is successful. But that is the only place that sets | ||
| 75 | * this back to zero. | ||
| 76 | */ | ||
| 77 | int tracing_disabled = 1; | ||
| 78 | |||
| 46 | static DEFINE_PER_CPU(local_t, ftrace_cpu_disabled); | 79 | static DEFINE_PER_CPU(local_t, ftrace_cpu_disabled); |
| 47 | 80 | ||
| 48 | static inline void ftrace_disable_cpu(void) | 81 | static inline void ftrace_disable_cpu(void) |
| @@ -62,7 +95,36 @@ static cpumask_t __read_mostly tracing_buffer_mask; | |||
| 62 | #define for_each_tracing_cpu(cpu) \ | 95 | #define for_each_tracing_cpu(cpu) \ |
| 63 | for_each_cpu_mask(cpu, tracing_buffer_mask) | 96 | for_each_cpu_mask(cpu, tracing_buffer_mask) |
| 64 | 97 | ||
| 65 | static int tracing_disabled = 1; | 98 | /* |
| 99 | * ftrace_dump_on_oops - variable to dump ftrace buffer on oops | ||
| 100 | * | ||
| 101 | * If there is an oops (or kernel panic) and the ftrace_dump_on_oops | ||
| 102 | * is set, then ftrace_dump is called. This will output the contents | ||
| 103 | * of the ftrace buffers to the console. This is very useful for | ||
| 104 | * capturing traces that lead to crashes and outputing it to a | ||
| 105 | * serial console. | ||
| 106 | * | ||
| 107 | * It is default off, but you can enable it with either specifying | ||
| 108 | * "ftrace_dump_on_oops" in the kernel command line, or setting | ||
| 109 | * /proc/sys/kernel/ftrace_dump_on_oops to true. | ||
| 110 | */ | ||
| 111 | int ftrace_dump_on_oops; | ||
| 112 | |||
| 113 | static int tracing_set_tracer(char *buf); | ||
| 114 | |||
| 115 | static int __init set_ftrace(char *str) | ||
| 116 | { | ||
| 117 | tracing_set_tracer(str); | ||
| 118 | return 1; | ||
| 119 | } | ||
| 120 | __setup("ftrace", set_ftrace); | ||
| 121 | |||
| 122 | static int __init set_ftrace_dump_on_oops(char *str) | ||
| 123 | { | ||
| 124 | ftrace_dump_on_oops = 1; | ||
| 125 | return 1; | ||
| 126 | } | ||
| 127 | __setup("ftrace_dump_on_oops", set_ftrace_dump_on_oops); | ||
| 66 | 128 | ||
| 67 | long | 129 | long |
| 68 | ns2usecs(cycle_t nsec) | 130 | ns2usecs(cycle_t nsec) |
| @@ -112,6 +174,19 @@ static DEFINE_PER_CPU(struct trace_array_cpu, max_data); | |||
| 112 | /* tracer_enabled is used to toggle activation of a tracer */ | 174 | /* tracer_enabled is used to toggle activation of a tracer */ |
| 113 | static int tracer_enabled = 1; | 175 | static int tracer_enabled = 1; |
| 114 | 176 | ||
| 177 | /** | ||
| 178 | * tracing_is_enabled - return tracer_enabled status | ||
| 179 | * | ||
| 180 | * This function is used by other tracers to know the status | ||
| 181 | * of the tracer_enabled flag. Tracers may use this function | ||
| 182 | * to know if it should enable their features when starting | ||
| 183 | * up. See irqsoff tracer for an example (start_irqsoff_tracer). | ||
| 184 | */ | ||
| 185 | int tracing_is_enabled(void) | ||
| 186 | { | ||
| 187 | return tracer_enabled; | ||
| 188 | } | ||
| 189 | |||
| 115 | /* function tracing enabled */ | 190 | /* function tracing enabled */ |
| 116 | int ftrace_function_enabled; | 191 | int ftrace_function_enabled; |
| 117 | 192 | ||
| @@ -153,8 +228,9 @@ static DEFINE_MUTEX(trace_types_lock); | |||
| 153 | /* trace_wait is a waitqueue for tasks blocked on trace_poll */ | 228 | /* trace_wait is a waitqueue for tasks blocked on trace_poll */ |
| 154 | static DECLARE_WAIT_QUEUE_HEAD(trace_wait); | 229 | static DECLARE_WAIT_QUEUE_HEAD(trace_wait); |
| 155 | 230 | ||
| 156 | /* trace_flags holds iter_ctrl options */ | 231 | /* trace_flags holds trace_options default values */ |
| 157 | unsigned long trace_flags = TRACE_ITER_PRINT_PARENT; | 232 | unsigned long trace_flags = TRACE_ITER_PRINT_PARENT | TRACE_ITER_PRINTK | |
| 233 | TRACE_ITER_ANNOTATE; | ||
| 158 | 234 | ||
| 159 | /** | 235 | /** |
| 160 | * trace_wake_up - wake up tasks waiting for trace input | 236 | * trace_wake_up - wake up tasks waiting for trace input |
| @@ -193,13 +269,6 @@ unsigned long nsecs_to_usecs(unsigned long nsecs) | |||
| 193 | return nsecs / 1000; | 269 | return nsecs / 1000; |
| 194 | } | 270 | } |
| 195 | 271 | ||
| 196 | /* | ||
| 197 | * TRACE_ITER_SYM_MASK masks the options in trace_flags that | ||
| 198 | * control the output of kernel symbols. | ||
| 199 | */ | ||
| 200 | #define TRACE_ITER_SYM_MASK \ | ||
| 201 | (TRACE_ITER_PRINT_PARENT|TRACE_ITER_SYM_OFFSET|TRACE_ITER_SYM_ADDR) | ||
| 202 | |||
| 203 | /* These must match the bit postions in trace_iterator_flags */ | 272 | /* These must match the bit postions in trace_iterator_flags */ |
| 204 | static const char *trace_options[] = { | 273 | static const char *trace_options[] = { |
| 205 | "print-parent", | 274 | "print-parent", |
| @@ -213,6 +282,12 @@ static const char *trace_options[] = { | |||
| 213 | "stacktrace", | 282 | "stacktrace", |
| 214 | "sched-tree", | 283 | "sched-tree", |
| 215 | "ftrace_printk", | 284 | "ftrace_printk", |
| 285 | "ftrace_preempt", | ||
| 286 | "branch", | ||
| 287 | "annotate", | ||
| 288 | "userstacktrace", | ||
| 289 | "sym-userobj", | ||
| 290 | "printk-msg-only", | ||
| 216 | NULL | 291 | NULL |
| 217 | }; | 292 | }; |
| 218 | 293 | ||
| @@ -359,6 +434,28 @@ trace_seq_putmem_hex(struct trace_seq *s, void *mem, size_t len) | |||
| 359 | return trace_seq_putmem(s, hex, j); | 434 | return trace_seq_putmem(s, hex, j); |
| 360 | } | 435 | } |
| 361 | 436 | ||
| 437 | static int | ||
| 438 | trace_seq_path(struct trace_seq *s, struct path *path) | ||
| 439 | { | ||
| 440 | unsigned char *p; | ||
| 441 | |||
| 442 | if (s->len >= (PAGE_SIZE - 1)) | ||
| 443 | return 0; | ||
| 444 | p = d_path(path, s->buffer + s->len, PAGE_SIZE - s->len); | ||
| 445 | if (!IS_ERR(p)) { | ||
| 446 | p = mangle_path(s->buffer + s->len, p, "\n"); | ||
| 447 | if (p) { | ||
| 448 | s->len = p - s->buffer; | ||
| 449 | return 1; | ||
| 450 | } | ||
| 451 | } else { | ||
| 452 | s->buffer[s->len++] = '?'; | ||
| 453 | return 1; | ||
| 454 | } | ||
| 455 | |||
| 456 | return 0; | ||
| 457 | } | ||
| 458 | |||
| 362 | static void | 459 | static void |
| 363 | trace_seq_reset(struct trace_seq *s) | 460 | trace_seq_reset(struct trace_seq *s) |
| 364 | { | 461 | { |
| @@ -470,7 +567,17 @@ int register_tracer(struct tracer *type) | |||
| 470 | return -1; | 567 | return -1; |
| 471 | } | 568 | } |
| 472 | 569 | ||
| 570 | /* | ||
| 571 | * When this gets called we hold the BKL which means that | ||
| 572 | * preemption is disabled. Various trace selftests however | ||
| 573 | * need to disable and enable preemption for successful tests. | ||
| 574 | * So we drop the BKL here and grab it after the tests again. | ||
| 575 | */ | ||
| 576 | unlock_kernel(); | ||
| 473 | mutex_lock(&trace_types_lock); | 577 | mutex_lock(&trace_types_lock); |
| 578 | |||
| 579 | tracing_selftest_running = true; | ||
| 580 | |||
| 474 | for (t = trace_types; t; t = t->next) { | 581 | for (t = trace_types; t; t = t->next) { |
| 475 | if (strcmp(type->name, t->name) == 0) { | 582 | if (strcmp(type->name, t->name) == 0) { |
| 476 | /* already found */ | 583 | /* already found */ |
| @@ -481,12 +588,20 @@ int register_tracer(struct tracer *type) | |||
| 481 | } | 588 | } |
| 482 | } | 589 | } |
| 483 | 590 | ||
| 591 | if (!type->set_flag) | ||
| 592 | type->set_flag = &dummy_set_flag; | ||
| 593 | if (!type->flags) | ||
| 594 | type->flags = &dummy_tracer_flags; | ||
| 595 | else | ||
| 596 | if (!type->flags->opts) | ||
| 597 | type->flags->opts = dummy_tracer_opt; | ||
| 598 | |||
| 484 | #ifdef CONFIG_FTRACE_STARTUP_TEST | 599 | #ifdef CONFIG_FTRACE_STARTUP_TEST |
| 485 | if (type->selftest) { | 600 | if (type->selftest) { |
| 486 | struct tracer *saved_tracer = current_trace; | 601 | struct tracer *saved_tracer = current_trace; |
| 487 | struct trace_array *tr = &global_trace; | 602 | struct trace_array *tr = &global_trace; |
| 488 | int saved_ctrl = tr->ctrl; | ||
| 489 | int i; | 603 | int i; |
| 604 | |||
| 490 | /* | 605 | /* |
| 491 | * Run a selftest on this tracer. | 606 | * Run a selftest on this tracer. |
| 492 | * Here we reset the trace buffer, and set the current | 607 | * Here we reset the trace buffer, and set the current |
| @@ -494,25 +609,23 @@ int register_tracer(struct tracer *type) | |||
| 494 | * internal tracing to verify that everything is in order. | 609 | * internal tracing to verify that everything is in order. |
| 495 | * If we fail, we do not register this tracer. | 610 | * If we fail, we do not register this tracer. |
| 496 | */ | 611 | */ |
| 497 | for_each_tracing_cpu(i) { | 612 | for_each_tracing_cpu(i) |
| 498 | tracing_reset(tr, i); | 613 | tracing_reset(tr, i); |
| 499 | } | 614 | |
| 500 | current_trace = type; | 615 | current_trace = type; |
| 501 | tr->ctrl = 0; | ||
| 502 | /* the test is responsible for initializing and enabling */ | 616 | /* the test is responsible for initializing and enabling */ |
| 503 | pr_info("Testing tracer %s: ", type->name); | 617 | pr_info("Testing tracer %s: ", type->name); |
| 504 | ret = type->selftest(type, tr); | 618 | ret = type->selftest(type, tr); |
| 505 | /* the test is responsible for resetting too */ | 619 | /* the test is responsible for resetting too */ |
| 506 | current_trace = saved_tracer; | 620 | current_trace = saved_tracer; |
| 507 | tr->ctrl = saved_ctrl; | ||
| 508 | if (ret) { | 621 | if (ret) { |
| 509 | printk(KERN_CONT "FAILED!\n"); | 622 | printk(KERN_CONT "FAILED!\n"); |
| 510 | goto out; | 623 | goto out; |
| 511 | } | 624 | } |
| 512 | /* Only reset on passing, to avoid touching corrupted buffers */ | 625 | /* Only reset on passing, to avoid touching corrupted buffers */ |
| 513 | for_each_tracing_cpu(i) { | 626 | for_each_tracing_cpu(i) |
| 514 | tracing_reset(tr, i); | 627 | tracing_reset(tr, i); |
| 515 | } | 628 | |
| 516 | printk(KERN_CONT "PASSED\n"); | 629 | printk(KERN_CONT "PASSED\n"); |
| 517 | } | 630 | } |
| 518 | #endif | 631 | #endif |
| @@ -524,7 +637,9 @@ int register_tracer(struct tracer *type) | |||
| 524 | max_tracer_type_len = len; | 637 | max_tracer_type_len = len; |
| 525 | 638 | ||
| 526 | out: | 639 | out: |
| 640 | tracing_selftest_running = false; | ||
| 527 | mutex_unlock(&trace_types_lock); | 641 | mutex_unlock(&trace_types_lock); |
| 642 | lock_kernel(); | ||
| 528 | 643 | ||
| 529 | return ret; | 644 | return ret; |
| 530 | } | 645 | } |
| @@ -564,6 +679,16 @@ void tracing_reset(struct trace_array *tr, int cpu) | |||
| 564 | ftrace_enable_cpu(); | 679 | ftrace_enable_cpu(); |
| 565 | } | 680 | } |
| 566 | 681 | ||
| 682 | void tracing_reset_online_cpus(struct trace_array *tr) | ||
| 683 | { | ||
| 684 | int cpu; | ||
| 685 | |||
| 686 | tr->time_start = ftrace_now(tr->cpu); | ||
| 687 | |||
| 688 | for_each_online_cpu(cpu) | ||
| 689 | tracing_reset(tr, cpu); | ||
| 690 | } | ||
| 691 | |||
| 567 | #define SAVED_CMDLINES 128 | 692 | #define SAVED_CMDLINES 128 |
| 568 | static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; | 693 | static unsigned map_pid_to_cmdline[PID_MAX_DEFAULT+1]; |
| 569 | static unsigned map_cmdline_to_pid[SAVED_CMDLINES]; | 694 | static unsigned map_cmdline_to_pid[SAVED_CMDLINES]; |
| @@ -581,6 +706,91 @@ static void trace_init_cmdlines(void) | |||
| 581 | cmdline_idx = 0; | 706 | cmdline_idx = 0; |
| 582 | } | 707 | } |
| 583 | 708 | ||
| 709 | static int trace_stop_count; | ||
| 710 | static DEFINE_SPINLOCK(tracing_start_lock); | ||
| 711 | |||
| 712 | /** | ||
| 713 | * ftrace_off_permanent - disable all ftrace code permanently | ||
| 714 | * | ||
| 715 | * This should only be called when a serious anomally has | ||
| 716 | * been detected. This will turn off the function tracing, | ||
| 717 | * ring buffers, and other tracing utilites. It takes no | ||
| 718 | * locks and can be called from any context. | ||
| 719 | */ | ||
| 720 | void ftrace_off_permanent(void) | ||
| 721 | { | ||
| 722 | tracing_disabled = 1; | ||
| 723 | ftrace_stop(); | ||
| 724 | tracing_off_permanent(); | ||
| 725 | } | ||
| 726 | |||
| 727 | /** | ||
| 728 | * tracing_start - quick start of the tracer | ||
| 729 | * | ||
| 730 | * If tracing is enabled but was stopped by tracing_stop, | ||
| 731 | * this will start the tracer back up. | ||
| 732 | */ | ||
| 733 | void tracing_start(void) | ||
| 734 | { | ||
| 735 | struct ring_buffer *buffer; | ||
| 736 | unsigned long flags; | ||
| 737 | |||
| 738 | if (tracing_disabled) | ||
| 739 | return; | ||
| 740 | |||
| 741 | spin_lock_irqsave(&tracing_start_lock, flags); | ||
| 742 | if (--trace_stop_count) | ||
| 743 | goto out; | ||
| 744 | |||
| 745 | if (trace_stop_count < 0) { | ||
| 746 | /* Someone screwed up their debugging */ | ||
| 747 | WARN_ON_ONCE(1); | ||
| 748 | trace_stop_count = 0; | ||
| 749 | goto out; | ||
| 750 | } | ||
| 751 | |||
| 752 | |||
| 753 | buffer = global_trace.buffer; | ||
| 754 | if (buffer) | ||
| 755 | ring_buffer_record_enable(buffer); | ||
| 756 | |||
| 757 | buffer = max_tr.buffer; | ||
| 758 | if (buffer) | ||
| 759 | ring_buffer_record_enable(buffer); | ||
| 760 | |||
| 761 | ftrace_start(); | ||
| 762 | out: | ||
| 763 | spin_unlock_irqrestore(&tracing_start_lock, flags); | ||
| 764 | } | ||
| 765 | |||
| 766 | /** | ||
| 767 | * tracing_stop - quick stop of the tracer | ||
| 768 | * | ||
| 769 | * Light weight way to stop tracing. Use in conjunction with | ||
| 770 | * tracing_start. | ||
| 771 | */ | ||
| 772 | void tracing_stop(void) | ||
| 773 | { | ||
| 774 | struct ring_buffer *buffer; | ||
| 775 | unsigned long flags; | ||
| 776 | |||
| 777 | ftrace_stop(); | ||
| 778 | spin_lock_irqsave(&tracing_start_lock, flags); | ||
| 779 | if (trace_stop_count++) | ||
| 780 | goto out; | ||
| 781 | |||
| 782 | buffer = global_trace.buffer; | ||
| 783 | if (buffer) | ||
| 784 | ring_buffer_record_disable(buffer); | ||
| 785 | |||
| 786 | buffer = max_tr.buffer; | ||
| 787 | if (buffer) | ||
| 788 | ring_buffer_record_disable(buffer); | ||
| 789 | |||
| 790 | out: | ||
| 791 | spin_unlock_irqrestore(&tracing_start_lock, flags); | ||
| 792 | } | ||
| 793 | |||
| 584 | void trace_stop_cmdline_recording(void); | 794 | void trace_stop_cmdline_recording(void); |
| 585 | 795 | ||
| 586 | static void trace_save_cmdline(struct task_struct *tsk) | 796 | static void trace_save_cmdline(struct task_struct *tsk) |
| @@ -618,7 +828,7 @@ static void trace_save_cmdline(struct task_struct *tsk) | |||
| 618 | spin_unlock(&trace_cmdline_lock); | 828 | spin_unlock(&trace_cmdline_lock); |
| 619 | } | 829 | } |
| 620 | 830 | ||
| 621 | static char *trace_find_cmdline(int pid) | 831 | char *trace_find_cmdline(int pid) |
| 622 | { | 832 | { |
| 623 | char *cmdline = "<...>"; | 833 | char *cmdline = "<...>"; |
| 624 | unsigned map; | 834 | unsigned map; |
| @@ -655,6 +865,7 @@ tracing_generic_entry_update(struct trace_entry *entry, unsigned long flags, | |||
| 655 | 865 | ||
| 656 | entry->preempt_count = pc & 0xff; | 866 | entry->preempt_count = pc & 0xff; |
| 657 | entry->pid = (tsk) ? tsk->pid : 0; | 867 | entry->pid = (tsk) ? tsk->pid : 0; |
| 868 | entry->tgid = (tsk) ? tsk->tgid : 0; | ||
| 658 | entry->flags = | 869 | entry->flags = |
| 659 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT | 870 | #ifdef CONFIG_TRACE_IRQFLAGS_SUPPORT |
| 660 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | | 871 | (irqs_disabled_flags(flags) ? TRACE_FLAG_IRQS_OFF : 0) | |
| @@ -691,6 +902,56 @@ trace_function(struct trace_array *tr, struct trace_array_cpu *data, | |||
| 691 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 902 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 692 | } | 903 | } |
| 693 | 904 | ||
| 905 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 906 | static void __trace_graph_entry(struct trace_array *tr, | ||
| 907 | struct trace_array_cpu *data, | ||
| 908 | struct ftrace_graph_ent *trace, | ||
| 909 | unsigned long flags, | ||
| 910 | int pc) | ||
| 911 | { | ||
| 912 | struct ring_buffer_event *event; | ||
| 913 | struct ftrace_graph_ent_entry *entry; | ||
| 914 | unsigned long irq_flags; | ||
| 915 | |||
| 916 | if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) | ||
| 917 | return; | ||
| 918 | |||
| 919 | event = ring_buffer_lock_reserve(global_trace.buffer, sizeof(*entry), | ||
| 920 | &irq_flags); | ||
| 921 | if (!event) | ||
| 922 | return; | ||
| 923 | entry = ring_buffer_event_data(event); | ||
| 924 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
| 925 | entry->ent.type = TRACE_GRAPH_ENT; | ||
| 926 | entry->graph_ent = *trace; | ||
| 927 | ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags); | ||
| 928 | } | ||
| 929 | |||
| 930 | static void __trace_graph_return(struct trace_array *tr, | ||
| 931 | struct trace_array_cpu *data, | ||
| 932 | struct ftrace_graph_ret *trace, | ||
| 933 | unsigned long flags, | ||
| 934 | int pc) | ||
| 935 | { | ||
| 936 | struct ring_buffer_event *event; | ||
| 937 | struct ftrace_graph_ret_entry *entry; | ||
| 938 | unsigned long irq_flags; | ||
| 939 | |||
| 940 | if (unlikely(local_read(&__get_cpu_var(ftrace_cpu_disabled)))) | ||
| 941 | return; | ||
| 942 | |||
| 943 | event = ring_buffer_lock_reserve(global_trace.buffer, sizeof(*entry), | ||
| 944 | &irq_flags); | ||
| 945 | if (!event) | ||
| 946 | return; | ||
| 947 | entry = ring_buffer_event_data(event); | ||
| 948 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
| 949 | entry->ent.type = TRACE_GRAPH_RET; | ||
| 950 | entry->ret = *trace; | ||
| 951 | ring_buffer_unlock_commit(global_trace.buffer, event, irq_flags); | ||
| 952 | } | ||
| 953 | #endif | ||
| 954 | |||
| 694 | void | 955 | void |
| 695 | ftrace(struct trace_array *tr, struct trace_array_cpu *data, | 956 | ftrace(struct trace_array *tr, struct trace_array_cpu *data, |
| 696 | unsigned long ip, unsigned long parent_ip, unsigned long flags, | 957 | unsigned long ip, unsigned long parent_ip, unsigned long flags, |
| @@ -742,6 +1003,46 @@ void __trace_stack(struct trace_array *tr, | |||
| 742 | ftrace_trace_stack(tr, data, flags, skip, preempt_count()); | 1003 | ftrace_trace_stack(tr, data, flags, skip, preempt_count()); |
| 743 | } | 1004 | } |
| 744 | 1005 | ||
| 1006 | static void ftrace_trace_userstack(struct trace_array *tr, | ||
| 1007 | struct trace_array_cpu *data, | ||
| 1008 | unsigned long flags, int pc) | ||
| 1009 | { | ||
| 1010 | #ifdef CONFIG_STACKTRACE | ||
| 1011 | struct ring_buffer_event *event; | ||
| 1012 | struct userstack_entry *entry; | ||
| 1013 | struct stack_trace trace; | ||
| 1014 | unsigned long irq_flags; | ||
| 1015 | |||
| 1016 | if (!(trace_flags & TRACE_ITER_USERSTACKTRACE)) | ||
| 1017 | return; | ||
| 1018 | |||
| 1019 | event = ring_buffer_lock_reserve(tr->buffer, sizeof(*entry), | ||
| 1020 | &irq_flags); | ||
| 1021 | if (!event) | ||
| 1022 | return; | ||
| 1023 | entry = ring_buffer_event_data(event); | ||
| 1024 | tracing_generic_entry_update(&entry->ent, flags, pc); | ||
| 1025 | entry->ent.type = TRACE_USER_STACK; | ||
| 1026 | |||
| 1027 | memset(&entry->caller, 0, sizeof(entry->caller)); | ||
| 1028 | |||
| 1029 | trace.nr_entries = 0; | ||
| 1030 | trace.max_entries = FTRACE_STACK_ENTRIES; | ||
| 1031 | trace.skip = 0; | ||
| 1032 | trace.entries = entry->caller; | ||
| 1033 | |||
| 1034 | save_stack_trace_user(&trace); | ||
| 1035 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | ||
| 1036 | #endif | ||
| 1037 | } | ||
| 1038 | |||
| 1039 | void __trace_userstack(struct trace_array *tr, | ||
| 1040 | struct trace_array_cpu *data, | ||
| 1041 | unsigned long flags) | ||
| 1042 | { | ||
| 1043 | ftrace_trace_userstack(tr, data, flags, preempt_count()); | ||
| 1044 | } | ||
| 1045 | |||
| 745 | static void | 1046 | static void |
| 746 | ftrace_trace_special(void *__tr, void *__data, | 1047 | ftrace_trace_special(void *__tr, void *__data, |
| 747 | unsigned long arg1, unsigned long arg2, unsigned long arg3, | 1048 | unsigned long arg1, unsigned long arg2, unsigned long arg3, |
| @@ -765,6 +1066,7 @@ ftrace_trace_special(void *__tr, void *__data, | |||
| 765 | entry->arg3 = arg3; | 1066 | entry->arg3 = arg3; |
| 766 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 1067 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 767 | ftrace_trace_stack(tr, data, irq_flags, 4, pc); | 1068 | ftrace_trace_stack(tr, data, irq_flags, 4, pc); |
| 1069 | ftrace_trace_userstack(tr, data, irq_flags, pc); | ||
| 768 | 1070 | ||
| 769 | trace_wake_up(); | 1071 | trace_wake_up(); |
| 770 | } | 1072 | } |
| @@ -803,6 +1105,7 @@ tracing_sched_switch_trace(struct trace_array *tr, | |||
| 803 | entry->next_cpu = task_cpu(next); | 1105 | entry->next_cpu = task_cpu(next); |
| 804 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 1106 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 805 | ftrace_trace_stack(tr, data, flags, 5, pc); | 1107 | ftrace_trace_stack(tr, data, flags, 5, pc); |
| 1108 | ftrace_trace_userstack(tr, data, flags, pc); | ||
| 806 | } | 1109 | } |
| 807 | 1110 | ||
| 808 | void | 1111 | void |
| @@ -832,6 +1135,7 @@ tracing_sched_wakeup_trace(struct trace_array *tr, | |||
| 832 | entry->next_cpu = task_cpu(wakee); | 1135 | entry->next_cpu = task_cpu(wakee); |
| 833 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 1136 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 834 | ftrace_trace_stack(tr, data, flags, 6, pc); | 1137 | ftrace_trace_stack(tr, data, flags, 6, pc); |
| 1138 | ftrace_trace_userstack(tr, data, flags, pc); | ||
| 835 | 1139 | ||
| 836 | trace_wake_up(); | 1140 | trace_wake_up(); |
| 837 | } | 1141 | } |
| @@ -841,26 +1145,28 @@ ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) | |||
| 841 | { | 1145 | { |
| 842 | struct trace_array *tr = &global_trace; | 1146 | struct trace_array *tr = &global_trace; |
| 843 | struct trace_array_cpu *data; | 1147 | struct trace_array_cpu *data; |
| 1148 | unsigned long flags; | ||
| 844 | int cpu; | 1149 | int cpu; |
| 845 | int pc; | 1150 | int pc; |
| 846 | 1151 | ||
| 847 | if (tracing_disabled || !tr->ctrl) | 1152 | if (tracing_disabled) |
| 848 | return; | 1153 | return; |
| 849 | 1154 | ||
| 850 | pc = preempt_count(); | 1155 | pc = preempt_count(); |
| 851 | preempt_disable_notrace(); | 1156 | local_irq_save(flags); |
| 852 | cpu = raw_smp_processor_id(); | 1157 | cpu = raw_smp_processor_id(); |
| 853 | data = tr->data[cpu]; | 1158 | data = tr->data[cpu]; |
| 854 | 1159 | ||
| 855 | if (likely(!atomic_read(&data->disabled))) | 1160 | if (likely(atomic_inc_return(&data->disabled) == 1)) |
| 856 | ftrace_trace_special(tr, data, arg1, arg2, arg3, pc); | 1161 | ftrace_trace_special(tr, data, arg1, arg2, arg3, pc); |
| 857 | 1162 | ||
| 858 | preempt_enable_notrace(); | 1163 | atomic_dec(&data->disabled); |
| 1164 | local_irq_restore(flags); | ||
| 859 | } | 1165 | } |
| 860 | 1166 | ||
| 861 | #ifdef CONFIG_FUNCTION_TRACER | 1167 | #ifdef CONFIG_FUNCTION_TRACER |
| 862 | static void | 1168 | static void |
| 863 | function_trace_call(unsigned long ip, unsigned long parent_ip) | 1169 | function_trace_call_preempt_only(unsigned long ip, unsigned long parent_ip) |
| 864 | { | 1170 | { |
| 865 | struct trace_array *tr = &global_trace; | 1171 | struct trace_array *tr = &global_trace; |
| 866 | struct trace_array_cpu *data; | 1172 | struct trace_array_cpu *data; |
| @@ -873,8 +1179,7 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) | |||
| 873 | return; | 1179 | return; |
| 874 | 1180 | ||
| 875 | pc = preempt_count(); | 1181 | pc = preempt_count(); |
| 876 | resched = need_resched(); | 1182 | resched = ftrace_preempt_disable(); |
| 877 | preempt_disable_notrace(); | ||
| 878 | local_save_flags(flags); | 1183 | local_save_flags(flags); |
| 879 | cpu = raw_smp_processor_id(); | 1184 | cpu = raw_smp_processor_id(); |
| 880 | data = tr->data[cpu]; | 1185 | data = tr->data[cpu]; |
| @@ -884,12 +1189,97 @@ function_trace_call(unsigned long ip, unsigned long parent_ip) | |||
| 884 | trace_function(tr, data, ip, parent_ip, flags, pc); | 1189 | trace_function(tr, data, ip, parent_ip, flags, pc); |
| 885 | 1190 | ||
| 886 | atomic_dec(&data->disabled); | 1191 | atomic_dec(&data->disabled); |
| 887 | if (resched) | 1192 | ftrace_preempt_enable(resched); |
| 888 | preempt_enable_no_resched_notrace(); | ||
| 889 | else | ||
| 890 | preempt_enable_notrace(); | ||
| 891 | } | 1193 | } |
| 892 | 1194 | ||
| 1195 | static void | ||
| 1196 | function_trace_call(unsigned long ip, unsigned long parent_ip) | ||
| 1197 | { | ||
| 1198 | struct trace_array *tr = &global_trace; | ||
| 1199 | struct trace_array_cpu *data; | ||
| 1200 | unsigned long flags; | ||
| 1201 | long disabled; | ||
| 1202 | int cpu; | ||
| 1203 | int pc; | ||
| 1204 | |||
| 1205 | if (unlikely(!ftrace_function_enabled)) | ||
| 1206 | return; | ||
| 1207 | |||
| 1208 | /* | ||
| 1209 | * Need to use raw, since this must be called before the | ||
| 1210 | * recursive protection is performed. | ||
| 1211 | */ | ||
| 1212 | local_irq_save(flags); | ||
| 1213 | cpu = raw_smp_processor_id(); | ||
| 1214 | data = tr->data[cpu]; | ||
| 1215 | disabled = atomic_inc_return(&data->disabled); | ||
| 1216 | |||
| 1217 | if (likely(disabled == 1)) { | ||
| 1218 | pc = preempt_count(); | ||
| 1219 | trace_function(tr, data, ip, parent_ip, flags, pc); | ||
| 1220 | } | ||
| 1221 | |||
| 1222 | atomic_dec(&data->disabled); | ||
| 1223 | local_irq_restore(flags); | ||
| 1224 | } | ||
| 1225 | |||
| 1226 | #ifdef CONFIG_FUNCTION_GRAPH_TRACER | ||
| 1227 | int trace_graph_entry(struct ftrace_graph_ent *trace) | ||
| 1228 | { | ||
| 1229 | struct trace_array *tr = &global_trace; | ||
| 1230 | struct trace_array_cpu *data; | ||
| 1231 | unsigned long flags; | ||
| 1232 | long disabled; | ||
| 1233 | int cpu; | ||
| 1234 | int pc; | ||
| 1235 | |||
| 1236 | if (!ftrace_trace_task(current)) | ||
| 1237 | return 0; | ||
| 1238 | |||
| 1239 | if (!ftrace_graph_addr(trace->func)) | ||
| 1240 | return 0; | ||
| 1241 | |||
| 1242 | local_irq_save(flags); | ||
| 1243 | cpu = raw_smp_processor_id(); | ||
| 1244 | data = tr->data[cpu]; | ||
| 1245 | disabled = atomic_inc_return(&data->disabled); | ||
| 1246 | if (likely(disabled == 1)) { | ||
| 1247 | pc = preempt_count(); | ||
| 1248 | __trace_graph_entry(tr, data, trace, flags, pc); | ||
| 1249 | } | ||
| 1250 | /* Only do the atomic if it is not already set */ | ||
| 1251 | if (!test_tsk_trace_graph(current)) | ||
| 1252 | set_tsk_trace_graph(current); | ||
| 1253 | atomic_dec(&data->disabled); | ||
| 1254 | local_irq_restore(flags); | ||
| 1255 | |||
| 1256 | return 1; | ||
| 1257 | } | ||
| 1258 | |||
| 1259 | void trace_graph_return(struct ftrace_graph_ret *trace) | ||
| 1260 | { | ||
| 1261 | struct trace_array *tr = &global_trace; | ||
| 1262 | struct trace_array_cpu *data; | ||
| 1263 | unsigned long flags; | ||
| 1264 | long disabled; | ||
| 1265 | int cpu; | ||
| 1266 | int pc; | ||
| 1267 | |||
| 1268 | local_irq_save(flags); | ||
| 1269 | cpu = raw_smp_processor_id(); | ||
| 1270 | data = tr->data[cpu]; | ||
| 1271 | disabled = atomic_inc_return(&data->disabled); | ||
| 1272 | if (likely(disabled == 1)) { | ||
| 1273 | pc = preempt_count(); | ||
| 1274 | __trace_graph_return(tr, data, trace, flags, pc); | ||
| 1275 | } | ||
| 1276 | if (!trace->depth) | ||
| 1277 | clear_tsk_trace_graph(current); | ||
| 1278 | atomic_dec(&data->disabled); | ||
| 1279 | local_irq_restore(flags); | ||
| 1280 | } | ||
| 1281 | #endif /* CONFIG_FUNCTION_GRAPH_TRACER */ | ||
| 1282 | |||
| 893 | static struct ftrace_ops trace_ops __read_mostly = | 1283 | static struct ftrace_ops trace_ops __read_mostly = |
| 894 | { | 1284 | { |
| 895 | .func = function_trace_call, | 1285 | .func = function_trace_call, |
| @@ -898,9 +1288,14 @@ static struct ftrace_ops trace_ops __read_mostly = | |||
| 898 | void tracing_start_function_trace(void) | 1288 | void tracing_start_function_trace(void) |
| 899 | { | 1289 | { |
| 900 | ftrace_function_enabled = 0; | 1290 | ftrace_function_enabled = 0; |
| 1291 | |||
| 1292 | if (trace_flags & TRACE_ITER_PREEMPTONLY) | ||
| 1293 | trace_ops.func = function_trace_call_preempt_only; | ||
| 1294 | else | ||
| 1295 | trace_ops.func = function_trace_call; | ||
| 1296 | |||
| 901 | register_ftrace_function(&trace_ops); | 1297 | register_ftrace_function(&trace_ops); |
| 902 | if (tracer_enabled) | 1298 | ftrace_function_enabled = 1; |
| 903 | ftrace_function_enabled = 1; | ||
| 904 | } | 1299 | } |
| 905 | 1300 | ||
| 906 | void tracing_stop_function_trace(void) | 1301 | void tracing_stop_function_trace(void) |
| @@ -912,6 +1307,7 @@ void tracing_stop_function_trace(void) | |||
| 912 | 1307 | ||
| 913 | enum trace_file_type { | 1308 | enum trace_file_type { |
| 914 | TRACE_FILE_LAT_FMT = 1, | 1309 | TRACE_FILE_LAT_FMT = 1, |
| 1310 | TRACE_FILE_ANNOTATE = 2, | ||
| 915 | }; | 1311 | }; |
| 916 | 1312 | ||
| 917 | static void trace_iterator_increment(struct trace_iterator *iter, int cpu) | 1313 | static void trace_iterator_increment(struct trace_iterator *iter, int cpu) |
| @@ -1047,10 +1443,6 @@ static void *s_start(struct seq_file *m, loff_t *pos) | |||
| 1047 | 1443 | ||
| 1048 | atomic_inc(&trace_record_cmdline_disabled); | 1444 | atomic_inc(&trace_record_cmdline_disabled); |
| 1049 | 1445 | ||
| 1050 | /* let the tracer grab locks here if needed */ | ||
| 1051 | if (current_trace->start) | ||
| 1052 | current_trace->start(iter); | ||
| 1053 | |||
| 1054 | if (*pos != iter->pos) { | 1446 | if (*pos != iter->pos) { |
| 1055 | iter->ent = NULL; | 1447 | iter->ent = NULL; |
| 1056 | iter->cpu = 0; | 1448 | iter->cpu = 0; |
| @@ -1077,14 +1469,7 @@ static void *s_start(struct seq_file *m, loff_t *pos) | |||
| 1077 | 1469 | ||
| 1078 | static void s_stop(struct seq_file *m, void *p) | 1470 | static void s_stop(struct seq_file *m, void *p) |
| 1079 | { | 1471 | { |
| 1080 | struct trace_iterator *iter = m->private; | ||
| 1081 | |||
| 1082 | atomic_dec(&trace_record_cmdline_disabled); | 1472 | atomic_dec(&trace_record_cmdline_disabled); |
| 1083 | |||
| 1084 | /* let the tracer release locks here if needed */ | ||
| 1085 | if (current_trace && current_trace == iter->trace && iter->trace->stop) | ||
| 1086 | iter->trace->stop(iter); | ||
| 1087 | |||
| 1088 | mutex_unlock(&trace_types_lock); | 1473 | mutex_unlock(&trace_types_lock); |
| 1089 | } | 1474 | } |
| 1090 | 1475 | ||
| @@ -1143,7 +1528,7 @@ seq_print_sym_offset(struct trace_seq *s, const char *fmt, | |||
| 1143 | # define IP_FMT "%016lx" | 1528 | # define IP_FMT "%016lx" |
| 1144 | #endif | 1529 | #endif |
| 1145 | 1530 | ||
| 1146 | static int | 1531 | int |
| 1147 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) | 1532 | seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) |
| 1148 | { | 1533 | { |
| 1149 | int ret; | 1534 | int ret; |
| @@ -1164,6 +1549,78 @@ seq_print_ip_sym(struct trace_seq *s, unsigned long ip, unsigned long sym_flags) | |||
| 1164 | return ret; | 1549 | return ret; |
| 1165 | } | 1550 | } |
| 1166 | 1551 | ||
| 1552 | static inline int seq_print_user_ip(struct trace_seq *s, struct mm_struct *mm, | ||
| 1553 | unsigned long ip, unsigned long sym_flags) | ||
| 1554 | { | ||
| 1555 | struct file *file = NULL; | ||
| 1556 | unsigned long vmstart = 0; | ||
| 1557 | int ret = 1; | ||
| 1558 | |||
| 1559 | if (mm) { | ||
| 1560 | const struct vm_area_struct *vma; | ||
| 1561 | |||
| 1562 | down_read(&mm->mmap_sem); | ||
| 1563 | vma = find_vma(mm, ip); | ||
| 1564 | if (vma) { | ||
| 1565 | file = vma->vm_file; | ||
| 1566 | vmstart = vma->vm_start; | ||
| 1567 | } | ||
| 1568 | if (file) { | ||
| 1569 | ret = trace_seq_path(s, &file->f_path); | ||
| 1570 | if (ret) | ||
| 1571 | ret = trace_seq_printf(s, "[+0x%lx]", ip - vmstart); | ||
| 1572 | } | ||
| 1573 | up_read(&mm->mmap_sem); | ||
| 1574 | } | ||
| 1575 | if (ret && ((sym_flags & TRACE_ITER_SYM_ADDR) || !file)) | ||
| 1576 | ret = trace_seq_printf(s, " <" IP_FMT ">", ip); | ||
| 1577 | return ret; | ||
| 1578 | } | ||
| 1579 | |||
| 1580 | static int | ||
| 1581 | seq_print_userip_objs(const struct userstack_entry *entry, struct trace_seq *s, | ||
| 1582 | unsigned long sym_flags) | ||
| 1583 | { | ||
| 1584 | struct mm_struct *mm = NULL; | ||
| 1585 | int ret = 1; | ||
| 1586 | unsigned int i; | ||
| 1587 | |||
| 1588 | if (trace_flags & TRACE_ITER_SYM_USEROBJ) { | ||
| 1589 | struct task_struct *task; | ||
| 1590 | /* | ||
| 1591 | * we do the lookup on the thread group leader, | ||
| 1592 | * since individual threads might have already quit! | ||
| 1593 | */ | ||
| 1594 | rcu_read_lock(); | ||
| 1595 | task = find_task_by_vpid(entry->ent.tgid); | ||
| 1596 | if (task) | ||
| 1597 | mm = get_task_mm(task); | ||
| 1598 | rcu_read_unlock(); | ||
| 1599 | } | ||
| 1600 | |||
| 1601 | for (i = 0; i < FTRACE_STACK_ENTRIES; i++) { | ||
| 1602 | unsigned long ip = entry->caller[i]; | ||
| 1603 | |||
| 1604 | if (ip == ULONG_MAX || !ret) | ||
| 1605 | break; | ||
| 1606 | if (i && ret) | ||
| 1607 | ret = trace_seq_puts(s, " <- "); | ||
| 1608 | if (!ip) { | ||
| 1609 | if (ret) | ||
| 1610 | ret = trace_seq_puts(s, "??"); | ||
| 1611 | continue; | ||
| 1612 | } | ||
| 1613 | if (!ret) | ||
| 1614 | break; | ||
| 1615 | if (ret) | ||
| 1616 | ret = seq_print_user_ip(s, mm, ip, sym_flags); | ||
| 1617 | } | ||
| 1618 | |||
| 1619 | if (mm) | ||
| 1620 | mmput(mm); | ||
| 1621 | return ret; | ||
| 1622 | } | ||
| 1623 | |||
| 1167 | static void print_lat_help_header(struct seq_file *m) | 1624 | static void print_lat_help_header(struct seq_file *m) |
| 1168 | { | 1625 | { |
| 1169 | seq_puts(m, "# _------=> CPU# \n"); | 1626 | seq_puts(m, "# _------=> CPU# \n"); |
| @@ -1301,6 +1758,13 @@ lat_print_timestamp(struct trace_seq *s, u64 abs_usecs, | |||
| 1301 | 1758 | ||
| 1302 | static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; | 1759 | static const char state_to_char[] = TASK_STATE_TO_CHAR_STR; |
| 1303 | 1760 | ||
| 1761 | static int task_state_char(unsigned long state) | ||
| 1762 | { | ||
| 1763 | int bit = state ? __ffs(state) + 1 : 0; | ||
| 1764 | |||
| 1765 | return bit < sizeof(state_to_char) - 1 ? state_to_char[bit] : '?'; | ||
| 1766 | } | ||
| 1767 | |||
| 1304 | /* | 1768 | /* |
| 1305 | * The message is supposed to contain an ending newline. | 1769 | * The message is supposed to contain an ending newline. |
| 1306 | * If the printing stops prematurely, try to add a newline of our own. | 1770 | * If the printing stops prematurely, try to add a newline of our own. |
| @@ -1338,6 +1802,23 @@ void trace_seq_print_cont(struct trace_seq *s, struct trace_iterator *iter) | |||
| 1338 | trace_seq_putc(s, '\n'); | 1802 | trace_seq_putc(s, '\n'); |
| 1339 | } | 1803 | } |
| 1340 | 1804 | ||
| 1805 | static void test_cpu_buff_start(struct trace_iterator *iter) | ||
| 1806 | { | ||
| 1807 | struct trace_seq *s = &iter->seq; | ||
| 1808 | |||
| 1809 | if (!(trace_flags & TRACE_ITER_ANNOTATE)) | ||
| 1810 | return; | ||
| 1811 | |||
| 1812 | if (!(iter->iter_flags & TRACE_FILE_ANNOTATE)) | ||
| 1813 | return; | ||
| 1814 | |||
| 1815 | if (cpu_isset(iter->cpu, iter->started)) | ||
| 1816 | return; | ||
| 1817 | |||
| 1818 | cpu_set(iter->cpu, iter->started); | ||
| 1819 | trace_seq_printf(s, "##### CPU %u buffer started ####\n", iter->cpu); | ||
| 1820 | } | ||
| 1821 | |||
| 1341 | static enum print_line_t | 1822 | static enum print_line_t |
| 1342 | print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | 1823 | print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) |
| 1343 | { | 1824 | { |
| @@ -1352,11 +1833,12 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
| 1352 | char *comm; | 1833 | char *comm; |
| 1353 | int S, T; | 1834 | int S, T; |
| 1354 | int i; | 1835 | int i; |
| 1355 | unsigned state; | ||
| 1356 | 1836 | ||
| 1357 | if (entry->type == TRACE_CONT) | 1837 | if (entry->type == TRACE_CONT) |
| 1358 | return TRACE_TYPE_HANDLED; | 1838 | return TRACE_TYPE_HANDLED; |
| 1359 | 1839 | ||
| 1840 | test_cpu_buff_start(iter); | ||
| 1841 | |||
| 1360 | next_entry = find_next_entry(iter, NULL, &next_ts); | 1842 | next_entry = find_next_entry(iter, NULL, &next_ts); |
| 1361 | if (!next_entry) | 1843 | if (!next_entry) |
| 1362 | next_ts = iter->ts; | 1844 | next_ts = iter->ts; |
| @@ -1396,12 +1878,8 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
| 1396 | 1878 | ||
| 1397 | trace_assign_type(field, entry); | 1879 | trace_assign_type(field, entry); |
| 1398 | 1880 | ||
| 1399 | T = field->next_state < sizeof(state_to_char) ? | 1881 | T = task_state_char(field->next_state); |
| 1400 | state_to_char[field->next_state] : 'X'; | 1882 | S = task_state_char(field->prev_state); |
| 1401 | |||
| 1402 | state = field->prev_state ? | ||
| 1403 | __ffs(field->prev_state) + 1 : 0; | ||
| 1404 | S = state < sizeof(state_to_char) - 1 ? state_to_char[state] : 'X'; | ||
| 1405 | comm = trace_find_cmdline(field->next_pid); | 1883 | comm = trace_find_cmdline(field->next_pid); |
| 1406 | trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", | 1884 | trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c %s\n", |
| 1407 | field->prev_pid, | 1885 | field->prev_pid, |
| @@ -1448,6 +1926,27 @@ print_lat_fmt(struct trace_iterator *iter, unsigned int trace_idx, int cpu) | |||
| 1448 | trace_seq_print_cont(s, iter); | 1926 | trace_seq_print_cont(s, iter); |
| 1449 | break; | 1927 | break; |
| 1450 | } | 1928 | } |
| 1929 | case TRACE_BRANCH: { | ||
| 1930 | struct trace_branch *field; | ||
| 1931 | |||
| 1932 | trace_assign_type(field, entry); | ||
| 1933 | |||
| 1934 | trace_seq_printf(s, "[%s] %s:%s:%d\n", | ||
| 1935 | field->correct ? " ok " : " MISS ", | ||
| 1936 | field->func, | ||
| 1937 | field->file, | ||
| 1938 | field->line); | ||
| 1939 | break; | ||
| 1940 | } | ||
| 1941 | case TRACE_USER_STACK: { | ||
| 1942 | struct userstack_entry *field; | ||
| 1943 | |||
| 1944 | trace_assign_type(field, entry); | ||
| 1945 | |||
| 1946 | seq_print_userip_objs(field, s, sym_flags); | ||
| 1947 | trace_seq_putc(s, '\n'); | ||
| 1948 | break; | ||
| 1949 | } | ||
| 1451 | default: | 1950 | default: |
| 1452 | trace_seq_printf(s, "Unknown type %d\n", entry->type); | 1951 | trace_seq_printf(s, "Unknown type %d\n", entry->type); |
| 1453 | } | 1952 | } |
| @@ -1472,6 +1971,8 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
| 1472 | if (entry->type == TRACE_CONT) | 1971 | if (entry->type == TRACE_CONT) |
| 1473 | return TRACE_TYPE_HANDLED; | 1972 | return TRACE_TYPE_HANDLED; |
| 1474 | 1973 | ||
| 1974 | test_cpu_buff_start(iter); | ||
| 1975 | |||
| 1475 | comm = trace_find_cmdline(iter->ent->pid); | 1976 | comm = trace_find_cmdline(iter->ent->pid); |
| 1476 | 1977 | ||
| 1477 | t = ns2usecs(iter->ts); | 1978 | t = ns2usecs(iter->ts); |
| @@ -1519,10 +2020,8 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
| 1519 | 2020 | ||
| 1520 | trace_assign_type(field, entry); | 2021 | trace_assign_type(field, entry); |
| 1521 | 2022 | ||
| 1522 | S = field->prev_state < sizeof(state_to_char) ? | 2023 | T = task_state_char(field->next_state); |
| 1523 | state_to_char[field->prev_state] : 'X'; | 2024 | S = task_state_char(field->prev_state); |
| 1524 | T = field->next_state < sizeof(state_to_char) ? | ||
| 1525 | state_to_char[field->next_state] : 'X'; | ||
| 1526 | ret = trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c\n", | 2025 | ret = trace_seq_printf(s, " %5d:%3d:%c %s [%03d] %5d:%3d:%c\n", |
| 1527 | field->prev_pid, | 2026 | field->prev_pid, |
| 1528 | field->prev_prio, | 2027 | field->prev_prio, |
| @@ -1581,6 +2080,37 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter) | |||
| 1581 | trace_seq_print_cont(s, iter); | 2080 | trace_seq_print_cont(s, iter); |
| 1582 | break; | 2081 | break; |
| 1583 | } | 2082 | } |
| 2083 | case TRACE_GRAPH_RET: { | ||
| 2084 | return print_graph_function(iter); | ||
| 2085 | } | ||
| 2086 | case TRACE_GRAPH_ENT: { | ||
| 2087 | return print_graph_function(iter); | ||
| 2088 | } | ||
| 2089 | case TRACE_BRANCH: { | ||
| 2090 | struct trace_branch *field; | ||
| 2091 | |||
| 2092 | trace_assign_type(field, entry); | ||
| 2093 | |||
| 2094 | trace_seq_printf(s, "[%s] %s:%s:%d\n", | ||
| 2095 | field->correct ? " ok " : " MISS ", | ||
| 2096 | field->func, | ||
| 2097 | field->file, | ||
| 2098 | field->line); | ||
| 2099 | break; | ||
| 2100 | } | ||
| 2101 | case TRACE_USER_STACK: { | ||
| 2102 | struct userstack_entry *field; | ||
| 2103 | |||
| 2104 | trace_assign_type(field, entry); | ||
| 2105 | |||
| 2106 | ret = seq_print_userip_objs(field, s, sym_flags); | ||
| 2107 | if (!ret) | ||
| 2108 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 2109 | ret = trace_seq_putc(s, '\n'); | ||
| 2110 | if (!ret) | ||
| 2111 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 2112 | break; | ||
| 2113 | } | ||
| 1584 | } | 2114 | } |
| 1585 | return TRACE_TYPE_HANDLED; | 2115 | return TRACE_TYPE_HANDLED; |
| 1586 | } | 2116 | } |
| @@ -1621,12 +2151,9 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
| 1621 | 2151 | ||
| 1622 | trace_assign_type(field, entry); | 2152 | trace_assign_type(field, entry); |
| 1623 | 2153 | ||
| 1624 | S = field->prev_state < sizeof(state_to_char) ? | 2154 | T = task_state_char(field->next_state); |
| 1625 | state_to_char[field->prev_state] : 'X'; | 2155 | S = entry->type == TRACE_WAKE ? '+' : |
| 1626 | T = field->next_state < sizeof(state_to_char) ? | 2156 | task_state_char(field->prev_state); |
| 1627 | state_to_char[field->next_state] : 'X'; | ||
| 1628 | if (entry->type == TRACE_WAKE) | ||
| 1629 | S = '+'; | ||
| 1630 | ret = trace_seq_printf(s, "%d %d %c %d %d %d %c\n", | 2157 | ret = trace_seq_printf(s, "%d %d %c %d %d %d %c\n", |
| 1631 | field->prev_pid, | 2158 | field->prev_pid, |
| 1632 | field->prev_prio, | 2159 | field->prev_prio, |
| @@ -1640,6 +2167,7 @@ static enum print_line_t print_raw_fmt(struct trace_iterator *iter) | |||
| 1640 | break; | 2167 | break; |
| 1641 | } | 2168 | } |
| 1642 | case TRACE_SPECIAL: | 2169 | case TRACE_SPECIAL: |
| 2170 | case TRACE_USER_STACK: | ||
| 1643 | case TRACE_STACK: { | 2171 | case TRACE_STACK: { |
| 1644 | struct special_entry *field; | 2172 | struct special_entry *field; |
| 1645 | 2173 | ||
| @@ -1712,12 +2240,9 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
| 1712 | 2240 | ||
| 1713 | trace_assign_type(field, entry); | 2241 | trace_assign_type(field, entry); |
| 1714 | 2242 | ||
| 1715 | S = field->prev_state < sizeof(state_to_char) ? | 2243 | T = task_state_char(field->next_state); |
| 1716 | state_to_char[field->prev_state] : 'X'; | 2244 | S = entry->type == TRACE_WAKE ? '+' : |
| 1717 | T = field->next_state < sizeof(state_to_char) ? | 2245 | task_state_char(field->prev_state); |
| 1718 | state_to_char[field->next_state] : 'X'; | ||
| 1719 | if (entry->type == TRACE_WAKE) | ||
| 1720 | S = '+'; | ||
| 1721 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid); | 2246 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_pid); |
| 1722 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio); | 2247 | SEQ_PUT_HEX_FIELD_RET(s, field->prev_prio); |
| 1723 | SEQ_PUT_HEX_FIELD_RET(s, S); | 2248 | SEQ_PUT_HEX_FIELD_RET(s, S); |
| @@ -1728,6 +2253,7 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
| 1728 | break; | 2253 | break; |
| 1729 | } | 2254 | } |
| 1730 | case TRACE_SPECIAL: | 2255 | case TRACE_SPECIAL: |
| 2256 | case TRACE_USER_STACK: | ||
| 1731 | case TRACE_STACK: { | 2257 | case TRACE_STACK: { |
| 1732 | struct special_entry *field; | 2258 | struct special_entry *field; |
| 1733 | 2259 | ||
| @@ -1744,6 +2270,25 @@ static enum print_line_t print_hex_fmt(struct trace_iterator *iter) | |||
| 1744 | return TRACE_TYPE_HANDLED; | 2270 | return TRACE_TYPE_HANDLED; |
| 1745 | } | 2271 | } |
| 1746 | 2272 | ||
| 2273 | static enum print_line_t print_printk_msg_only(struct trace_iterator *iter) | ||
| 2274 | { | ||
| 2275 | struct trace_seq *s = &iter->seq; | ||
| 2276 | struct trace_entry *entry = iter->ent; | ||
| 2277 | struct print_entry *field; | ||
| 2278 | int ret; | ||
| 2279 | |||
| 2280 | trace_assign_type(field, entry); | ||
| 2281 | |||
| 2282 | ret = trace_seq_printf(s, field->buf); | ||
| 2283 | if (!ret) | ||
| 2284 | return TRACE_TYPE_PARTIAL_LINE; | ||
| 2285 | |||
| 2286 | if (entry->flags & TRACE_FLAG_CONT) | ||
| 2287 | trace_seq_print_cont(s, iter); | ||
| 2288 | |||
| 2289 | return TRACE_TYPE_HANDLED; | ||
| 2290 | } | ||
| 2291 | |||
| 1747 | static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | 2292 | static enum print_line_t print_bin_fmt(struct trace_iterator *iter) |
| 1748 | { | 2293 | { |
| 1749 | struct trace_seq *s = &iter->seq; | 2294 | struct trace_seq *s = &iter->seq; |
| @@ -1782,6 +2327,7 @@ static enum print_line_t print_bin_fmt(struct trace_iterator *iter) | |||
| 1782 | break; | 2327 | break; |
| 1783 | } | 2328 | } |
| 1784 | case TRACE_SPECIAL: | 2329 | case TRACE_SPECIAL: |
| 2330 | case TRACE_USER_STACK: | ||
| 1785 | case TRACE_STACK: { | 2331 | case TRACE_STACK: { |
| 1786 | struct special_entry *field; | 2332 | struct special_entry *field; |
| 1787 | 2333 | ||
| @@ -1823,6 +2369,11 @@ static enum print_line_t print_trace_line(struct trace_iterator *iter) | |||
| 1823 | return ret; | 2369 | return ret; |
| 1824 | } | 2370 | } |
| 1825 | 2371 | ||
| 2372 | if (iter->ent->type == TRACE_PRINT && | ||
| 2373 | trace_flags & TRACE_ITER_PRINTK && | ||
| 2374 | trace_flags & TRACE_ITER_PRINTK_MSGONLY) | ||
| 2375 | return print_printk_msg_only(iter); | ||
| 2376 | |||
| 1826 | if (trace_flags & TRACE_ITER_BIN) | 2377 | if (trace_flags & TRACE_ITER_BIN) |
| 1827 | return print_bin_fmt(iter); | 2378 | return print_bin_fmt(iter); |
| 1828 | 2379 | ||
| @@ -1847,7 +2398,9 @@ static int s_show(struct seq_file *m, void *v) | |||
| 1847 | seq_printf(m, "# tracer: %s\n", iter->trace->name); | 2398 | seq_printf(m, "# tracer: %s\n", iter->trace->name); |
| 1848 | seq_puts(m, "#\n"); | 2399 | seq_puts(m, "#\n"); |
| 1849 | } | 2400 | } |
| 1850 | if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | 2401 | if (iter->trace && iter->trace->print_header) |
| 2402 | iter->trace->print_header(m); | ||
| 2403 | else if (iter->iter_flags & TRACE_FILE_LAT_FMT) { | ||
| 1851 | /* print nothing if the buffers are empty */ | 2404 | /* print nothing if the buffers are empty */ |
| 1852 | if (trace_empty(iter)) | 2405 | if (trace_empty(iter)) |
| 1853 | return 0; | 2406 | return 0; |
| @@ -1899,6 +2452,15 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) | |||
| 1899 | iter->trace = current_trace; | 2452 | iter->trace = current_trace; |
| 1900 | iter->pos = -1; | 2453 | iter->pos = -1; |
| 1901 | 2454 | ||
| 2455 | /* Notify the tracer early; before we stop tracing. */ | ||
| 2456 | if (iter->trace && iter->trace->open) | ||
| 2457 | iter->trace->open(iter); | ||
| 2458 | |||
| 2459 | /* Annotate start of buffers if we had overruns */ | ||
| 2460 | if (ring_buffer_overruns(iter->tr->buffer)) | ||
| 2461 | iter->iter_flags |= TRACE_FILE_ANNOTATE; | ||
| 2462 | |||
| 2463 | |||
| 1902 | for_each_tracing_cpu(cpu) { | 2464 | for_each_tracing_cpu(cpu) { |
| 1903 | 2465 | ||
| 1904 | iter->buffer_iter[cpu] = | 2466 | iter->buffer_iter[cpu] = |
| @@ -1917,13 +2479,7 @@ __tracing_open(struct inode *inode, struct file *file, int *ret) | |||
| 1917 | m->private = iter; | 2479 | m->private = iter; |
| 1918 | 2480 | ||
| 1919 | /* stop the trace while dumping */ | 2481 | /* stop the trace while dumping */ |
| 1920 | if (iter->tr->ctrl) { | 2482 | tracing_stop(); |
| 1921 | tracer_enabled = 0; | ||
| 1922 | ftrace_function_enabled = 0; | ||
| 1923 | } | ||
| 1924 | |||
| 1925 | if (iter->trace && iter->trace->open) | ||
| 1926 | iter->trace->open(iter); | ||
| 1927 | 2483 | ||
| 1928 | mutex_unlock(&trace_types_lock); | 2484 | mutex_unlock(&trace_types_lock); |
| 1929 | 2485 | ||
| @@ -1966,14 +2522,7 @@ int tracing_release(struct inode *inode, struct file *file) | |||
| 1966 | iter->trace->close(iter); | 2522 | iter->trace->close(iter); |
| 1967 | 2523 | ||
| 1968 | /* reenable tracing if it was previously enabled */ | 2524 | /* reenable tracing if it was previously enabled */ |
| 1969 | if (iter->tr->ctrl) { | 2525 | tracing_start(); |
| 1970 | tracer_enabled = 1; | ||
| 1971 | /* | ||
| 1972 | * It is safe to enable function tracing even if it | ||
| 1973 | * isn't used | ||
| 1974 | */ | ||
| 1975 | ftrace_function_enabled = 1; | ||
| 1976 | } | ||
| 1977 | mutex_unlock(&trace_types_lock); | 2526 | mutex_unlock(&trace_types_lock); |
| 1978 | 2527 | ||
| 1979 | seq_release(inode, file); | 2528 | seq_release(inode, file); |
| @@ -2151,7 +2700,7 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf, | |||
| 2151 | if (err) | 2700 | if (err) |
| 2152 | goto err_unlock; | 2701 | goto err_unlock; |
| 2153 | 2702 | ||
| 2154 | raw_local_irq_disable(); | 2703 | local_irq_disable(); |
| 2155 | __raw_spin_lock(&ftrace_max_lock); | 2704 | __raw_spin_lock(&ftrace_max_lock); |
| 2156 | for_each_tracing_cpu(cpu) { | 2705 | for_each_tracing_cpu(cpu) { |
| 2157 | /* | 2706 | /* |
| @@ -2168,7 +2717,7 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf, | |||
| 2168 | } | 2717 | } |
| 2169 | } | 2718 | } |
| 2170 | __raw_spin_unlock(&ftrace_max_lock); | 2719 | __raw_spin_unlock(&ftrace_max_lock); |
| 2171 | raw_local_irq_enable(); | 2720 | local_irq_enable(); |
| 2172 | 2721 | ||
| 2173 | tracing_cpumask = tracing_cpumask_new; | 2722 | tracing_cpumask = tracing_cpumask_new; |
| 2174 | 2723 | ||
| @@ -2189,13 +2738,16 @@ static struct file_operations tracing_cpumask_fops = { | |||
| 2189 | }; | 2738 | }; |
| 2190 | 2739 | ||
| 2191 | static ssize_t | 2740 | static ssize_t |
| 2192 | tracing_iter_ctrl_read(struct file *filp, char __user *ubuf, | 2741 | tracing_trace_options_read(struct file *filp, char __user *ubuf, |
| 2193 | size_t cnt, loff_t *ppos) | 2742 | size_t cnt, loff_t *ppos) |
| 2194 | { | 2743 | { |
| 2744 | int i; | ||
| 2195 | char *buf; | 2745 | char *buf; |
| 2196 | int r = 0; | 2746 | int r = 0; |
| 2197 | int len = 0; | 2747 | int len = 0; |
| 2198 | int i; | 2748 | u32 tracer_flags = current_trace->flags->val; |
| 2749 | struct tracer_opt *trace_opts = current_trace->flags->opts; | ||
| 2750 | |||
| 2199 | 2751 | ||
| 2200 | /* calulate max size */ | 2752 | /* calulate max size */ |
| 2201 | for (i = 0; trace_options[i]; i++) { | 2753 | for (i = 0; trace_options[i]; i++) { |
| @@ -2203,6 +2755,15 @@ tracing_iter_ctrl_read(struct file *filp, char __user *ubuf, | |||
| 2203 | len += 3; /* "no" and space */ | 2755 | len += 3; /* "no" and space */ |
| 2204 | } | 2756 | } |
| 2205 | 2757 | ||
| 2758 | /* | ||
| 2759 | * Increase the size with names of options specific | ||
| 2760 | * of the current tracer. | ||
| 2761 | */ | ||
| 2762 | for (i = 0; trace_opts[i].name; i++) { | ||
| 2763 | len += strlen(trace_opts[i].name); | ||
| 2764 | len += 3; /* "no" and space */ | ||
| 2765 | } | ||
| 2766 | |||
| 2206 | /* +2 for \n and \0 */ | 2767 | /* +2 for \n and \0 */ |
| 2207 | buf = kmalloc(len + 2, GFP_KERNEL); | 2768 | buf = kmalloc(len + 2, GFP_KERNEL); |
| 2208 | if (!buf) | 2769 | if (!buf) |
| @@ -2215,6 +2776,15 @@ tracing_iter_ctrl_read(struct file *filp, char __user *ubuf, | |||
| 2215 | r += sprintf(buf + r, "no%s ", trace_options[i]); | 2776 | r += sprintf(buf + r, "no%s ", trace_options[i]); |
| 2216 | } | 2777 | } |
| 2217 | 2778 | ||
| 2779 | for (i = 0; trace_opts[i].name; i++) { | ||
| 2780 | if (tracer_flags & trace_opts[i].bit) | ||
| 2781 | r += sprintf(buf + r, "%s ", | ||
| 2782 | trace_opts[i].name); | ||
| 2783 | else | ||
| 2784 | r += sprintf(buf + r, "no%s ", | ||
| 2785 | trace_opts[i].name); | ||
| 2786 | } | ||
| 2787 | |||
| 2218 | r += sprintf(buf + r, "\n"); | 2788 | r += sprintf(buf + r, "\n"); |
| 2219 | WARN_ON(r >= len + 2); | 2789 | WARN_ON(r >= len + 2); |
| 2220 | 2790 | ||
| @@ -2225,13 +2795,48 @@ tracing_iter_ctrl_read(struct file *filp, char __user *ubuf, | |||
| 2225 | return r; | 2795 | return r; |
| 2226 | } | 2796 | } |
| 2227 | 2797 | ||
| 2798 | /* Try to assign a tracer specific option */ | ||
| 2799 | static int set_tracer_option(struct tracer *trace, char *cmp, int neg) | ||
| 2800 | { | ||
| 2801 | struct tracer_flags *trace_flags = trace->flags; | ||
| 2802 | struct tracer_opt *opts = NULL; | ||
| 2803 | int ret = 0, i = 0; | ||
| 2804 | int len; | ||
| 2805 | |||
| 2806 | for (i = 0; trace_flags->opts[i].name; i++) { | ||
| 2807 | opts = &trace_flags->opts[i]; | ||
| 2808 | len = strlen(opts->name); | ||
| 2809 | |||
| 2810 | if (strncmp(cmp, opts->name, len) == 0) { | ||
| 2811 | ret = trace->set_flag(trace_flags->val, | ||
| 2812 | opts->bit, !neg); | ||
| 2813 | break; | ||
| 2814 | } | ||
| 2815 | } | ||
| 2816 | /* Not found */ | ||
| 2817 | if (!trace_flags->opts[i].name) | ||
| 2818 | return -EINVAL; | ||
| 2819 | |||
| 2820 | /* Refused to handle */ | ||
| 2821 | if (ret) | ||
| 2822 | return ret; | ||
| 2823 | |||
| 2824 | if (neg) | ||
| 2825 | trace_flags->val &= ~opts->bit; | ||
| 2826 | else | ||
| 2827 | trace_flags->val |= opts->bit; | ||
| 2828 | |||
| 2829 | return 0; | ||
| 2830 | } | ||
| 2831 | |||
| 2228 | static ssize_t | 2832 | static ssize_t |
| 2229 | tracing_iter_ctrl_write(struct file *filp, const char __user *ubuf, | 2833 | tracing_trace_options_write(struct file *filp, const char __user *ubuf, |
| 2230 | size_t cnt, loff_t *ppos) | 2834 | size_t cnt, loff_t *ppos) |
| 2231 | { | 2835 | { |
| 2232 | char buf[64]; | 2836 | char buf[64]; |
| 2233 | char *cmp = buf; | 2837 | char *cmp = buf; |
| 2234 | int neg = 0; | 2838 | int neg = 0; |
| 2839 | int ret; | ||
| 2235 | int i; | 2840 | int i; |
| 2236 | 2841 | ||
| 2237 | if (cnt >= sizeof(buf)) | 2842 | if (cnt >= sizeof(buf)) |
| @@ -2258,11 +2863,13 @@ tracing_iter_ctrl_write(struct file *filp, const char __user *ubuf, | |||
| 2258 | break; | 2863 | break; |
| 2259 | } | 2864 | } |
| 2260 | } | 2865 | } |
| 2261 | /* | 2866 | |
| 2262 | * If no option could be set, return an error: | 2867 | /* If no option could be set, test the specific tracer options */ |
| 2263 | */ | 2868 | if (!trace_options[i]) { |
| 2264 | if (!trace_options[i]) | 2869 | ret = set_tracer_option(current_trace, cmp, neg); |
| 2265 | return -EINVAL; | 2870 | if (ret) |
| 2871 | return ret; | ||
| 2872 | } | ||
| 2266 | 2873 | ||
| 2267 | filp->f_pos += cnt; | 2874 | filp->f_pos += cnt; |
| 2268 | 2875 | ||
| @@ -2271,8 +2878,8 @@ tracing_iter_ctrl_write(struct file *filp, const char __user *ubuf, | |||
| 2271 | 2878 | ||
| 2272 | static struct file_operations tracing_iter_fops = { | 2879 | static struct file_operations tracing_iter_fops = { |
| 2273 | .open = tracing_open_generic, | 2880 | .open = tracing_open_generic, |
| 2274 | .read = tracing_iter_ctrl_read, | 2881 | .read = tracing_trace_options_read, |
| 2275 | .write = tracing_iter_ctrl_write, | 2882 | .write = tracing_trace_options_write, |
| 2276 | }; | 2883 | }; |
| 2277 | 2884 | ||
| 2278 | static const char readme_msg[] = | 2885 | static const char readme_msg[] = |
| @@ -2286,9 +2893,9 @@ static const char readme_msg[] = | |||
| 2286 | "# echo sched_switch > /debug/tracing/current_tracer\n" | 2893 | "# echo sched_switch > /debug/tracing/current_tracer\n" |
| 2287 | "# cat /debug/tracing/current_tracer\n" | 2894 | "# cat /debug/tracing/current_tracer\n" |
| 2288 | "sched_switch\n" | 2895 | "sched_switch\n" |
| 2289 | "# cat /debug/tracing/iter_ctrl\n" | 2896 | "# cat /debug/tracing/trace_options\n" |
| 2290 | "noprint-parent nosym-offset nosym-addr noverbose\n" | 2897 | "noprint-parent nosym-offset nosym-addr noverbose\n" |
| 2291 | "# echo print-parent > /debug/tracing/iter_ctrl\n" | 2898 | "# echo print-parent > /debug/tracing/trace_options\n" |
| 2292 | "# echo 1 > /debug/tracing/tracing_enabled\n" | 2899 | "# echo 1 > /debug/tracing/tracing_enabled\n" |
| 2293 | "# cat /debug/tracing/trace > /tmp/trace.txt\n" | 2900 | "# cat /debug/tracing/trace > /tmp/trace.txt\n" |
| 2294 | "echo 0 > /debug/tracing/tracing_enabled\n" | 2901 | "echo 0 > /debug/tracing/tracing_enabled\n" |
| @@ -2311,11 +2918,10 @@ static ssize_t | |||
| 2311 | tracing_ctrl_read(struct file *filp, char __user *ubuf, | 2918 | tracing_ctrl_read(struct file *filp, char __user *ubuf, |
| 2312 | size_t cnt, loff_t *ppos) | 2919 | size_t cnt, loff_t *ppos) |
| 2313 | { | 2920 | { |
| 2314 | struct trace_array *tr = filp->private_data; | ||
| 2315 | char buf[64]; | 2921 | char buf[64]; |
| 2316 | int r; | 2922 | int r; |
| 2317 | 2923 | ||
| 2318 | r = sprintf(buf, "%ld\n", tr->ctrl); | 2924 | r = sprintf(buf, "%u\n", tracer_enabled); |
| 2319 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 2925 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 2320 | } | 2926 | } |
| 2321 | 2927 | ||
| @@ -2343,16 +2949,18 @@ tracing_ctrl_write(struct file *filp, const char __user *ubuf, | |||
| 2343 | val = !!val; | 2949 | val = !!val; |
| 2344 | 2950 | ||
| 2345 | mutex_lock(&trace_types_lock); | 2951 | mutex_lock(&trace_types_lock); |
| 2346 | if (tr->ctrl ^ val) { | 2952 | if (tracer_enabled ^ val) { |
| 2347 | if (val) | 2953 | if (val) { |
| 2348 | tracer_enabled = 1; | 2954 | tracer_enabled = 1; |
| 2349 | else | 2955 | if (current_trace->start) |
| 2956 | current_trace->start(tr); | ||
| 2957 | tracing_start(); | ||
| 2958 | } else { | ||
| 2350 | tracer_enabled = 0; | 2959 | tracer_enabled = 0; |
| 2351 | 2960 | tracing_stop(); | |
| 2352 | tr->ctrl = val; | 2961 | if (current_trace->stop) |
| 2353 | 2962 | current_trace->stop(tr); | |
| 2354 | if (current_trace && current_trace->ctrl_update) | 2963 | } |
| 2355 | current_trace->ctrl_update(tr); | ||
| 2356 | } | 2964 | } |
| 2357 | mutex_unlock(&trace_types_lock); | 2965 | mutex_unlock(&trace_types_lock); |
| 2358 | 2966 | ||
| @@ -2378,29 +2986,11 @@ tracing_set_trace_read(struct file *filp, char __user *ubuf, | |||
| 2378 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 2986 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 2379 | } | 2987 | } |
| 2380 | 2988 | ||
| 2381 | static ssize_t | 2989 | static int tracing_set_tracer(char *buf) |
| 2382 | tracing_set_trace_write(struct file *filp, const char __user *ubuf, | ||
| 2383 | size_t cnt, loff_t *ppos) | ||
| 2384 | { | 2990 | { |
| 2385 | struct trace_array *tr = &global_trace; | 2991 | struct trace_array *tr = &global_trace; |
| 2386 | struct tracer *t; | 2992 | struct tracer *t; |
| 2387 | char buf[max_tracer_type_len+1]; | 2993 | int ret = 0; |
| 2388 | int i; | ||
| 2389 | size_t ret; | ||
| 2390 | |||
| 2391 | ret = cnt; | ||
| 2392 | |||
| 2393 | if (cnt > max_tracer_type_len) | ||
| 2394 | cnt = max_tracer_type_len; | ||
| 2395 | |||
| 2396 | if (copy_from_user(&buf, ubuf, cnt)) | ||
| 2397 | return -EFAULT; | ||
| 2398 | |||
| 2399 | buf[cnt] = 0; | ||
| 2400 | |||
| 2401 | /* strip ending whitespace. */ | ||
| 2402 | for (i = cnt - 1; i > 0 && isspace(buf[i]); i--) | ||
| 2403 | buf[i] = 0; | ||
| 2404 | 2994 | ||
| 2405 | mutex_lock(&trace_types_lock); | 2995 | mutex_lock(&trace_types_lock); |
| 2406 | for (t = trace_types; t; t = t->next) { | 2996 | for (t = trace_types; t; t = t->next) { |
| @@ -2414,18 +3004,52 @@ tracing_set_trace_write(struct file *filp, const char __user *ubuf, | |||
| 2414 | if (t == current_trace) | 3004 | if (t == current_trace) |
| 2415 | goto out; | 3005 | goto out; |
| 2416 | 3006 | ||
| 3007 | trace_branch_disable(); | ||
| 2417 | if (current_trace && current_trace->reset) | 3008 | if (current_trace && current_trace->reset) |
| 2418 | current_trace->reset(tr); | 3009 | current_trace->reset(tr); |
| 2419 | 3010 | ||
| 2420 | current_trace = t; | 3011 | current_trace = t; |
| 2421 | if (t->init) | 3012 | if (t->init) { |
| 2422 | t->init(tr); | 3013 | ret = t->init(tr); |
| 3014 | if (ret) | ||
| 3015 | goto out; | ||
| 3016 | } | ||
| 2423 | 3017 | ||
| 3018 | trace_branch_enable(tr); | ||
| 2424 | out: | 3019 | out: |
| 2425 | mutex_unlock(&trace_types_lock); | 3020 | mutex_unlock(&trace_types_lock); |
| 2426 | 3021 | ||
| 2427 | if (ret > 0) | 3022 | return ret; |
| 2428 | filp->f_pos += ret; | 3023 | } |
| 3024 | |||
| 3025 | static ssize_t | ||
| 3026 | tracing_set_trace_write(struct file *filp, const char __user *ubuf, | ||
| 3027 | size_t cnt, loff_t *ppos) | ||
| 3028 | { | ||
| 3029 | char buf[max_tracer_type_len+1]; | ||
| 3030 | int i; | ||
| 3031 | size_t ret; | ||
| 3032 | int err; | ||
| 3033 | |||
| 3034 | ret = cnt; | ||
| 3035 | |||
| 3036 | if (cnt > max_tracer_type_len) | ||
| 3037 | cnt = max_tracer_type_len; | ||
| 3038 | |||
| 3039 | if (copy_from_user(&buf, ubuf, cnt)) | ||
| 3040 | return -EFAULT; | ||
| 3041 | |||
| 3042 | buf[cnt] = 0; | ||
| 3043 | |||
| 3044 | /* strip ending whitespace. */ | ||
| 3045 | for (i = cnt - 1; i > 0 && isspace(buf[i]); i--) | ||
| 3046 | buf[i] = 0; | ||
| 3047 | |||
| 3048 | err = tracing_set_tracer(buf); | ||
| 3049 | if (err) | ||
| 3050 | return err; | ||
| 3051 | |||
| 3052 | filp->f_pos += ret; | ||
| 2429 | 3053 | ||
| 2430 | return ret; | 3054 | return ret; |
| 2431 | } | 3055 | } |
| @@ -2492,6 +3116,10 @@ static int tracing_open_pipe(struct inode *inode, struct file *filp) | |||
| 2492 | return -ENOMEM; | 3116 | return -ENOMEM; |
| 2493 | 3117 | ||
| 2494 | mutex_lock(&trace_types_lock); | 3118 | mutex_lock(&trace_types_lock); |
| 3119 | |||
| 3120 | /* trace pipe does not show start of buffer */ | ||
| 3121 | cpus_setall(iter->started); | ||
| 3122 | |||
| 2495 | iter->tr = &global_trace; | 3123 | iter->tr = &global_trace; |
| 2496 | iter->trace = current_trace; | 3124 | iter->trace = current_trace; |
| 2497 | filp->private_data = iter; | 3125 | filp->private_data = iter; |
| @@ -2667,7 +3295,7 @@ tracing_entries_read(struct file *filp, char __user *ubuf, | |||
| 2667 | char buf[64]; | 3295 | char buf[64]; |
| 2668 | int r; | 3296 | int r; |
| 2669 | 3297 | ||
| 2670 | r = sprintf(buf, "%lu\n", tr->entries); | 3298 | r = sprintf(buf, "%lu\n", tr->entries >> 10); |
| 2671 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 3299 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); |
| 2672 | } | 3300 | } |
| 2673 | 3301 | ||
| @@ -2678,7 +3306,6 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2678 | unsigned long val; | 3306 | unsigned long val; |
| 2679 | char buf[64]; | 3307 | char buf[64]; |
| 2680 | int ret, cpu; | 3308 | int ret, cpu; |
| 2681 | struct trace_array *tr = filp->private_data; | ||
| 2682 | 3309 | ||
| 2683 | if (cnt >= sizeof(buf)) | 3310 | if (cnt >= sizeof(buf)) |
| 2684 | return -EINVAL; | 3311 | return -EINVAL; |
| @@ -2698,12 +3325,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2698 | 3325 | ||
| 2699 | mutex_lock(&trace_types_lock); | 3326 | mutex_lock(&trace_types_lock); |
| 2700 | 3327 | ||
| 2701 | if (tr->ctrl) { | 3328 | tracing_stop(); |
| 2702 | cnt = -EBUSY; | ||
| 2703 | pr_info("ftrace: please disable tracing" | ||
| 2704 | " before modifying buffer size\n"); | ||
| 2705 | goto out; | ||
| 2706 | } | ||
| 2707 | 3329 | ||
| 2708 | /* disable all cpu buffers */ | 3330 | /* disable all cpu buffers */ |
| 2709 | for_each_tracing_cpu(cpu) { | 3331 | for_each_tracing_cpu(cpu) { |
| @@ -2713,6 +3335,9 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2713 | atomic_inc(&max_tr.data[cpu]->disabled); | 3335 | atomic_inc(&max_tr.data[cpu]->disabled); |
| 2714 | } | 3336 | } |
| 2715 | 3337 | ||
| 3338 | /* value is in KB */ | ||
| 3339 | val <<= 10; | ||
| 3340 | |||
| 2716 | if (val != global_trace.entries) { | 3341 | if (val != global_trace.entries) { |
| 2717 | ret = ring_buffer_resize(global_trace.buffer, val); | 3342 | ret = ring_buffer_resize(global_trace.buffer, val); |
| 2718 | if (ret < 0) { | 3343 | if (ret < 0) { |
| @@ -2751,6 +3376,7 @@ tracing_entries_write(struct file *filp, const char __user *ubuf, | |||
| 2751 | atomic_dec(&max_tr.data[cpu]->disabled); | 3376 | atomic_dec(&max_tr.data[cpu]->disabled); |
| 2752 | } | 3377 | } |
| 2753 | 3378 | ||
| 3379 | tracing_start(); | ||
| 2754 | max_tr.entries = global_trace.entries; | 3380 | max_tr.entries = global_trace.entries; |
| 2755 | mutex_unlock(&trace_types_lock); | 3381 | mutex_unlock(&trace_types_lock); |
| 2756 | 3382 | ||
| @@ -2762,7 +3388,7 @@ static int mark_printk(const char *fmt, ...) | |||
| 2762 | int ret; | 3388 | int ret; |
| 2763 | va_list args; | 3389 | va_list args; |
| 2764 | va_start(args, fmt); | 3390 | va_start(args, fmt); |
| 2765 | ret = trace_vprintk(0, fmt, args); | 3391 | ret = trace_vprintk(0, -1, fmt, args); |
| 2766 | va_end(args); | 3392 | va_end(args); |
| 2767 | return ret; | 3393 | return ret; |
| 2768 | } | 3394 | } |
| @@ -2773,9 +3399,8 @@ tracing_mark_write(struct file *filp, const char __user *ubuf, | |||
| 2773 | { | 3399 | { |
| 2774 | char *buf; | 3400 | char *buf; |
| 2775 | char *end; | 3401 | char *end; |
| 2776 | struct trace_array *tr = &global_trace; | ||
| 2777 | 3402 | ||
| 2778 | if (!tr->ctrl || tracing_disabled) | 3403 | if (tracing_disabled) |
| 2779 | return -EINVAL; | 3404 | return -EINVAL; |
| 2780 | 3405 | ||
| 2781 | if (cnt > TRACE_BUF_SIZE) | 3406 | if (cnt > TRACE_BUF_SIZE) |
| @@ -2841,22 +3466,38 @@ static struct file_operations tracing_mark_fops = { | |||
| 2841 | 3466 | ||
| 2842 | #ifdef CONFIG_DYNAMIC_FTRACE | 3467 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 2843 | 3468 | ||
| 3469 | int __weak ftrace_arch_read_dyn_info(char *buf, int size) | ||
| 3470 | { | ||
| 3471 | return 0; | ||
| 3472 | } | ||
| 3473 | |||
| 2844 | static ssize_t | 3474 | static ssize_t |
| 2845 | tracing_read_long(struct file *filp, char __user *ubuf, | 3475 | tracing_read_dyn_info(struct file *filp, char __user *ubuf, |
| 2846 | size_t cnt, loff_t *ppos) | 3476 | size_t cnt, loff_t *ppos) |
| 2847 | { | 3477 | { |
| 3478 | static char ftrace_dyn_info_buffer[1024]; | ||
| 3479 | static DEFINE_MUTEX(dyn_info_mutex); | ||
| 2848 | unsigned long *p = filp->private_data; | 3480 | unsigned long *p = filp->private_data; |
| 2849 | char buf[64]; | 3481 | char *buf = ftrace_dyn_info_buffer; |
| 3482 | int size = ARRAY_SIZE(ftrace_dyn_info_buffer); | ||
| 2850 | int r; | 3483 | int r; |
| 2851 | 3484 | ||
| 2852 | r = sprintf(buf, "%ld\n", *p); | 3485 | mutex_lock(&dyn_info_mutex); |
| 3486 | r = sprintf(buf, "%ld ", *p); | ||
| 2853 | 3487 | ||
| 2854 | return simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | 3488 | r += ftrace_arch_read_dyn_info(buf+r, (size-1)-r); |
| 3489 | buf[r++] = '\n'; | ||
| 3490 | |||
| 3491 | r = simple_read_from_buffer(ubuf, cnt, ppos, buf, r); | ||
| 3492 | |||
| 3493 | mutex_unlock(&dyn_info_mutex); | ||
| 3494 | |||
| 3495 | return r; | ||
| 2855 | } | 3496 | } |
| 2856 | 3497 | ||
| 2857 | static struct file_operations tracing_read_long_fops = { | 3498 | static struct file_operations tracing_dyn_info_fops = { |
| 2858 | .open = tracing_open_generic, | 3499 | .open = tracing_open_generic, |
| 2859 | .read = tracing_read_long, | 3500 | .read = tracing_read_dyn_info, |
| 2860 | }; | 3501 | }; |
| 2861 | #endif | 3502 | #endif |
| 2862 | 3503 | ||
| @@ -2897,10 +3538,10 @@ static __init int tracer_init_debugfs(void) | |||
| 2897 | if (!entry) | 3538 | if (!entry) |
| 2898 | pr_warning("Could not create debugfs 'tracing_enabled' entry\n"); | 3539 | pr_warning("Could not create debugfs 'tracing_enabled' entry\n"); |
| 2899 | 3540 | ||
| 2900 | entry = debugfs_create_file("iter_ctrl", 0644, d_tracer, | 3541 | entry = debugfs_create_file("trace_options", 0644, d_tracer, |
| 2901 | NULL, &tracing_iter_fops); | 3542 | NULL, &tracing_iter_fops); |
| 2902 | if (!entry) | 3543 | if (!entry) |
| 2903 | pr_warning("Could not create debugfs 'iter_ctrl' entry\n"); | 3544 | pr_warning("Could not create debugfs 'trace_options' entry\n"); |
| 2904 | 3545 | ||
| 2905 | entry = debugfs_create_file("tracing_cpumask", 0644, d_tracer, | 3546 | entry = debugfs_create_file("tracing_cpumask", 0644, d_tracer, |
| 2906 | NULL, &tracing_cpumask_fops); | 3547 | NULL, &tracing_cpumask_fops); |
| @@ -2950,11 +3591,11 @@ static __init int tracer_init_debugfs(void) | |||
| 2950 | pr_warning("Could not create debugfs " | 3591 | pr_warning("Could not create debugfs " |
| 2951 | "'trace_pipe' entry\n"); | 3592 | "'trace_pipe' entry\n"); |
| 2952 | 3593 | ||
| 2953 | entry = debugfs_create_file("trace_entries", 0644, d_tracer, | 3594 | entry = debugfs_create_file("buffer_size_kb", 0644, d_tracer, |
| 2954 | &global_trace, &tracing_entries_fops); | 3595 | &global_trace, &tracing_entries_fops); |
| 2955 | if (!entry) | 3596 | if (!entry) |
| 2956 | pr_warning("Could not create debugfs " | 3597 | pr_warning("Could not create debugfs " |
| 2957 | "'trace_entries' entry\n"); | 3598 | "'buffer_size_kb' entry\n"); |
| 2958 | 3599 | ||
| 2959 | entry = debugfs_create_file("trace_marker", 0220, d_tracer, | 3600 | entry = debugfs_create_file("trace_marker", 0220, d_tracer, |
| 2960 | NULL, &tracing_mark_fops); | 3601 | NULL, &tracing_mark_fops); |
| @@ -2965,7 +3606,7 @@ static __init int tracer_init_debugfs(void) | |||
| 2965 | #ifdef CONFIG_DYNAMIC_FTRACE | 3606 | #ifdef CONFIG_DYNAMIC_FTRACE |
| 2966 | entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer, | 3607 | entry = debugfs_create_file("dyn_ftrace_total_info", 0444, d_tracer, |
| 2967 | &ftrace_update_tot_cnt, | 3608 | &ftrace_update_tot_cnt, |
| 2968 | &tracing_read_long_fops); | 3609 | &tracing_dyn_info_fops); |
| 2969 | if (!entry) | 3610 | if (!entry) |
| 2970 | pr_warning("Could not create debugfs " | 3611 | pr_warning("Could not create debugfs " |
| 2971 | "'dyn_ftrace_total_info' entry\n"); | 3612 | "'dyn_ftrace_total_info' entry\n"); |
| @@ -2976,7 +3617,7 @@ static __init int tracer_init_debugfs(void) | |||
| 2976 | return 0; | 3617 | return 0; |
| 2977 | } | 3618 | } |
| 2978 | 3619 | ||
| 2979 | int trace_vprintk(unsigned long ip, const char *fmt, va_list args) | 3620 | int trace_vprintk(unsigned long ip, int depth, const char *fmt, va_list args) |
| 2980 | { | 3621 | { |
| 2981 | static DEFINE_SPINLOCK(trace_buf_lock); | 3622 | static DEFINE_SPINLOCK(trace_buf_lock); |
| 2982 | static char trace_buf[TRACE_BUF_SIZE]; | 3623 | static char trace_buf[TRACE_BUF_SIZE]; |
| @@ -2984,11 +3625,11 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args) | |||
| 2984 | struct ring_buffer_event *event; | 3625 | struct ring_buffer_event *event; |
| 2985 | struct trace_array *tr = &global_trace; | 3626 | struct trace_array *tr = &global_trace; |
| 2986 | struct trace_array_cpu *data; | 3627 | struct trace_array_cpu *data; |
| 2987 | struct print_entry *entry; | ||
| 2988 | unsigned long flags, irq_flags; | ||
| 2989 | int cpu, len = 0, size, pc; | 3628 | int cpu, len = 0, size, pc; |
| 3629 | struct print_entry *entry; | ||
| 3630 | unsigned long irq_flags; | ||
| 2990 | 3631 | ||
| 2991 | if (!tr->ctrl || tracing_disabled) | 3632 | if (tracing_disabled || tracing_selftest_running) |
| 2992 | return 0; | 3633 | return 0; |
| 2993 | 3634 | ||
| 2994 | pc = preempt_count(); | 3635 | pc = preempt_count(); |
| @@ -2999,7 +3640,8 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args) | |||
| 2999 | if (unlikely(atomic_read(&data->disabled))) | 3640 | if (unlikely(atomic_read(&data->disabled))) |
| 3000 | goto out; | 3641 | goto out; |
| 3001 | 3642 | ||
| 3002 | spin_lock_irqsave(&trace_buf_lock, flags); | 3643 | pause_graph_tracing(); |
| 3644 | spin_lock_irqsave(&trace_buf_lock, irq_flags); | ||
| 3003 | len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); | 3645 | len = vsnprintf(trace_buf, TRACE_BUF_SIZE, fmt, args); |
| 3004 | 3646 | ||
| 3005 | len = min(len, TRACE_BUF_SIZE-1); | 3647 | len = min(len, TRACE_BUF_SIZE-1); |
| @@ -3010,17 +3652,18 @@ int trace_vprintk(unsigned long ip, const char *fmt, va_list args) | |||
| 3010 | if (!event) | 3652 | if (!event) |
| 3011 | goto out_unlock; | 3653 | goto out_unlock; |
| 3012 | entry = ring_buffer_event_data(event); | 3654 | entry = ring_buffer_event_data(event); |
| 3013 | tracing_generic_entry_update(&entry->ent, flags, pc); | 3655 | tracing_generic_entry_update(&entry->ent, irq_flags, pc); |
| 3014 | entry->ent.type = TRACE_PRINT; | 3656 | entry->ent.type = TRACE_PRINT; |
| 3015 | entry->ip = ip; | 3657 | entry->ip = ip; |
| 3658 | entry->depth = depth; | ||
| 3016 | 3659 | ||
| 3017 | memcpy(&entry->buf, trace_buf, len); | 3660 | memcpy(&entry->buf, trace_buf, len); |
| 3018 | entry->buf[len] = 0; | 3661 | entry->buf[len] = 0; |
| 3019 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); | 3662 | ring_buffer_unlock_commit(tr->buffer, event, irq_flags); |
| 3020 | 3663 | ||
| 3021 | out_unlock: | 3664 | out_unlock: |
| 3022 | spin_unlock_irqrestore(&trace_buf_lock, flags); | 3665 | spin_unlock_irqrestore(&trace_buf_lock, irq_flags); |
| 3023 | 3666 | unpause_graph_tracing(); | |
| 3024 | out: | 3667 | out: |
| 3025 | preempt_enable_notrace(); | 3668 | preempt_enable_notrace(); |
| 3026 | 3669 | ||
| @@ -3037,7 +3680,7 @@ int __ftrace_printk(unsigned long ip, const char *fmt, ...) | |||
| 3037 | return 0; | 3680 | return 0; |
| 3038 | 3681 | ||
| 3039 | va_start(ap, fmt); | 3682 | va_start(ap, fmt); |
| 3040 | ret = trace_vprintk(ip, fmt, ap); | 3683 | ret = trace_vprintk(ip, task_curr_ret_stack(current), fmt, ap); |
| 3041 | va_end(ap); | 3684 | va_end(ap); |
| 3042 | return ret; | 3685 | return ret; |
| 3043 | } | 3686 | } |
| @@ -3046,7 +3689,8 @@ EXPORT_SYMBOL_GPL(__ftrace_printk); | |||
| 3046 | static int trace_panic_handler(struct notifier_block *this, | 3689 | static int trace_panic_handler(struct notifier_block *this, |
| 3047 | unsigned long event, void *unused) | 3690 | unsigned long event, void *unused) |
| 3048 | { | 3691 | { |
| 3049 | ftrace_dump(); | 3692 | if (ftrace_dump_on_oops) |
| 3693 | ftrace_dump(); | ||
| 3050 | return NOTIFY_OK; | 3694 | return NOTIFY_OK; |
| 3051 | } | 3695 | } |
| 3052 | 3696 | ||
| @@ -3062,7 +3706,8 @@ static int trace_die_handler(struct notifier_block *self, | |||
| 3062 | { | 3706 | { |
| 3063 | switch (val) { | 3707 | switch (val) { |
| 3064 | case DIE_OOPS: | 3708 | case DIE_OOPS: |
| 3065 | ftrace_dump(); | 3709 | if (ftrace_dump_on_oops) |
| 3710 | ftrace_dump(); | ||
| 3066 | break; | 3711 | break; |
| 3067 | default: | 3712 | default: |
| 3068 | break; | 3713 | break; |
| @@ -3103,7 +3748,6 @@ trace_printk_seq(struct trace_seq *s) | |||
| 3103 | trace_seq_reset(s); | 3748 | trace_seq_reset(s); |
| 3104 | } | 3749 | } |
| 3105 | 3750 | ||
| 3106 | |||
| 3107 | void ftrace_dump(void) | 3751 | void ftrace_dump(void) |
| 3108 | { | 3752 | { |
| 3109 | static DEFINE_SPINLOCK(ftrace_dump_lock); | 3753 | static DEFINE_SPINLOCK(ftrace_dump_lock); |
| @@ -3128,6 +3772,9 @@ void ftrace_dump(void) | |||
| 3128 | atomic_inc(&global_trace.data[cpu]->disabled); | 3772 | atomic_inc(&global_trace.data[cpu]->disabled); |
| 3129 | } | 3773 | } |
| 3130 | 3774 | ||
| 3775 | /* don't look at user memory in panic mode */ | ||
| 3776 | trace_flags &= ~TRACE_ITER_SYM_USEROBJ; | ||
| 3777 | |||
| 3131 | printk(KERN_TRACE "Dumping ftrace buffer:\n"); | 3778 | printk(KERN_TRACE "Dumping ftrace buffer:\n"); |
| 3132 | 3779 | ||
| 3133 | iter.tr = &global_trace; | 3780 | iter.tr = &global_trace; |
| @@ -3221,7 +3868,6 @@ __init static int tracer_alloc_buffers(void) | |||
| 3221 | #endif | 3868 | #endif |
| 3222 | 3869 | ||
| 3223 | /* All seems OK, enable tracing */ | 3870 | /* All seems OK, enable tracing */ |
| 3224 | global_trace.ctrl = tracer_enabled; | ||
| 3225 | tracing_disabled = 0; | 3871 | tracing_disabled = 0; |
| 3226 | 3872 | ||
| 3227 | atomic_notifier_chain_register(&panic_notifier_list, | 3873 | atomic_notifier_chain_register(&panic_notifier_list, |
