| .. | .. |
|---|
| 12 | 12 | #define pr_fmt(fmt) fmt |
|---|
| 13 | 13 | |
|---|
| 14 | 14 | #include <linux/workqueue.h> |
|---|
| 15 | +#include <linux/security.h> |
|---|
| 15 | 16 | #include <linux/spinlock.h> |
|---|
| 16 | 17 | #include <linux/kthread.h> |
|---|
| 17 | 18 | #include <linux/tracefs.h> |
|---|
| .. | .. |
|---|
| 23 | 24 | #include <linux/delay.h> |
|---|
| 24 | 25 | |
|---|
| 25 | 26 | #include <trace/events/sched.h> |
|---|
| 27 | +#include <trace/syscall.h> |
|---|
| 26 | 28 | |
|---|
| 27 | 29 | #include <asm/setup.h> |
|---|
| 28 | 30 | |
|---|
| .. | .. |
|---|
| 36 | 38 | LIST_HEAD(ftrace_events); |
|---|
| 37 | 39 | static LIST_HEAD(ftrace_generic_fields); |
|---|
| 38 | 40 | static LIST_HEAD(ftrace_common_fields); |
|---|
| 41 | +static bool eventdir_initialized; |
|---|
| 39 | 42 | |
|---|
| 40 | 43 | #define GFP_TRACE (GFP_KERNEL | __GFP_ZERO) |
|---|
| 41 | 44 | |
|---|
| .. | .. |
|---|
| 69 | 72 | |
|---|
| 70 | 73 | #define while_for_each_event_file() \ |
|---|
| 71 | 74 | } |
|---|
| 72 | | - |
|---|
| 73 | | -static struct list_head * |
|---|
| 74 | | -trace_get_fields(struct trace_event_call *event_call) |
|---|
| 75 | | -{ |
|---|
| 76 | | - if (!event_call->class->get_fields) |
|---|
| 77 | | - return &event_call->class->fields; |
|---|
| 78 | | - return event_call->class->get_fields(event_call); |
|---|
| 79 | | -} |
|---|
| 80 | 75 | |
|---|
| 81 | 76 | static struct ftrace_event_field * |
|---|
| 82 | 77 | __find_event_field(struct list_head *head, char *name) |
|---|
| .. | .. |
|---|
| 173 | 168 | |
|---|
| 174 | 169 | __generic_field(int, CPU, FILTER_CPU); |
|---|
| 175 | 170 | __generic_field(int, cpu, FILTER_CPU); |
|---|
| 171 | + __generic_field(int, common_cpu, FILTER_CPU); |
|---|
| 176 | 172 | __generic_field(char *, COMM, FILTER_COMM); |
|---|
| 177 | 173 | __generic_field(char *, comm, FILTER_COMM); |
|---|
| 178 | 174 | |
|---|
| .. | .. |
|---|
| 238 | 234 | { |
|---|
| 239 | 235 | struct trace_array *tr = trace_file->tr; |
|---|
| 240 | 236 | struct trace_array_cpu *data; |
|---|
| 237 | + struct trace_pid_list *no_pid_list; |
|---|
| 241 | 238 | struct trace_pid_list *pid_list; |
|---|
| 242 | 239 | |
|---|
| 243 | 240 | pid_list = rcu_dereference_raw(tr->filtered_pids); |
|---|
| 244 | | - if (!pid_list) |
|---|
| 241 | + no_pid_list = rcu_dereference_raw(tr->filtered_no_pids); |
|---|
| 242 | + |
|---|
| 243 | + if (!pid_list && !no_pid_list) |
|---|
| 245 | 244 | return false; |
|---|
| 246 | 245 | |
|---|
| 247 | | - data = this_cpu_ptr(tr->trace_buffer.data); |
|---|
| 246 | + data = this_cpu_ptr(tr->array_buffer.data); |
|---|
| 248 | 247 | |
|---|
| 249 | 248 | return data->ignore_pid; |
|---|
| 250 | 249 | } |
|---|
| .. | .. |
|---|
| 263 | 262 | local_save_flags(fbuffer->flags); |
|---|
| 264 | 263 | fbuffer->pc = preempt_count(); |
|---|
| 265 | 264 | /* |
|---|
| 266 | | - * If CONFIG_PREEMPT is enabled, then the tracepoint itself disables |
|---|
| 265 | + * If CONFIG_PREEMPTION is enabled, then the tracepoint itself disables |
|---|
| 267 | 266 | * preemption (adding one to the preempt_count). Since we are |
|---|
| 268 | 267 | * interested in the preempt_count at the time the tracepoint was |
|---|
| 269 | 268 | * hit, we need to subtract one to offset the increment. |
|---|
| 270 | 269 | */ |
|---|
| 271 | | - if (IS_ENABLED(CONFIG_PREEMPT)) |
|---|
| 270 | + if (IS_ENABLED(CONFIG_PREEMPTION)) |
|---|
| 272 | 271 | fbuffer->pc--; |
|---|
| 273 | 272 | fbuffer->trace_file = trace_file; |
|---|
| 274 | 273 | |
|---|
| .. | .. |
|---|
| 279 | 278 | if (!fbuffer->event) |
|---|
| 280 | 279 | return NULL; |
|---|
| 281 | 280 | |
|---|
| 281 | + fbuffer->regs = NULL; |
|---|
| 282 | 282 | fbuffer->entry = ring_buffer_event_data(fbuffer->event); |
|---|
| 283 | 283 | return fbuffer->entry; |
|---|
| 284 | 284 | } |
|---|
| .. | .. |
|---|
| 515 | 515 | |
|---|
| 516 | 516 | pid_list = rcu_dereference_raw(tr->filtered_pids); |
|---|
| 517 | 517 | trace_filter_add_remove_task(pid_list, NULL, task); |
|---|
| 518 | + |
|---|
| 519 | + pid_list = rcu_dereference_raw(tr->filtered_no_pids); |
|---|
| 520 | + trace_filter_add_remove_task(pid_list, NULL, task); |
|---|
| 518 | 521 | } |
|---|
| 519 | 522 | |
|---|
| 520 | 523 | static void |
|---|
| .. | .. |
|---|
| 526 | 529 | struct trace_array *tr = data; |
|---|
| 527 | 530 | |
|---|
| 528 | 531 | pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 532 | + trace_filter_add_remove_task(pid_list, self, task); |
|---|
| 533 | + |
|---|
| 534 | + pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 529 | 535 | trace_filter_add_remove_task(pid_list, self, task); |
|---|
| 530 | 536 | } |
|---|
| 531 | 537 | |
|---|
| .. | .. |
|---|
| 549 | 555 | struct task_struct *prev, struct task_struct *next) |
|---|
| 550 | 556 | { |
|---|
| 551 | 557 | struct trace_array *tr = data; |
|---|
| 558 | + struct trace_pid_list *no_pid_list; |
|---|
| 552 | 559 | struct trace_pid_list *pid_list; |
|---|
| 560 | + bool ret; |
|---|
| 553 | 561 | |
|---|
| 554 | 562 | pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 563 | + no_pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 555 | 564 | |
|---|
| 556 | | - this_cpu_write(tr->trace_buffer.data->ignore_pid, |
|---|
| 557 | | - trace_ignore_this_task(pid_list, prev) && |
|---|
| 558 | | - trace_ignore_this_task(pid_list, next)); |
|---|
| 565 | + /* |
|---|
| 566 | + * Sched switch is funny, as we only want to ignore it |
|---|
| 567 | + * in the notrace case if both prev and next should be ignored. |
|---|
| 568 | + */ |
|---|
| 569 | + ret = trace_ignore_this_task(NULL, no_pid_list, prev) && |
|---|
| 570 | + trace_ignore_this_task(NULL, no_pid_list, next); |
|---|
| 571 | + |
|---|
| 572 | + this_cpu_write(tr->array_buffer.data->ignore_pid, ret || |
|---|
| 573 | + (trace_ignore_this_task(pid_list, NULL, prev) && |
|---|
| 574 | + trace_ignore_this_task(pid_list, NULL, next))); |
|---|
| 559 | 575 | } |
|---|
| 560 | 576 | |
|---|
| 561 | 577 | static void |
|---|
| .. | .. |
|---|
| 563 | 579 | struct task_struct *prev, struct task_struct *next) |
|---|
| 564 | 580 | { |
|---|
| 565 | 581 | struct trace_array *tr = data; |
|---|
| 582 | + struct trace_pid_list *no_pid_list; |
|---|
| 566 | 583 | struct trace_pid_list *pid_list; |
|---|
| 567 | 584 | |
|---|
| 568 | 585 | pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 586 | + no_pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 569 | 587 | |
|---|
| 570 | | - this_cpu_write(tr->trace_buffer.data->ignore_pid, |
|---|
| 571 | | - trace_ignore_this_task(pid_list, next)); |
|---|
| 588 | + this_cpu_write(tr->array_buffer.data->ignore_pid, |
|---|
| 589 | + trace_ignore_this_task(pid_list, no_pid_list, next)); |
|---|
| 572 | 590 | } |
|---|
| 573 | 591 | |
|---|
| 574 | 592 | static void |
|---|
| 575 | 593 | event_filter_pid_sched_wakeup_probe_pre(void *data, struct task_struct *task) |
|---|
| 576 | 594 | { |
|---|
| 577 | 595 | struct trace_array *tr = data; |
|---|
| 596 | + struct trace_pid_list *no_pid_list; |
|---|
| 578 | 597 | struct trace_pid_list *pid_list; |
|---|
| 579 | 598 | |
|---|
| 580 | 599 | /* Nothing to do if we are already tracing */ |
|---|
| 581 | | - if (!this_cpu_read(tr->trace_buffer.data->ignore_pid)) |
|---|
| 600 | + if (!this_cpu_read(tr->array_buffer.data->ignore_pid)) |
|---|
| 582 | 601 | return; |
|---|
| 583 | 602 | |
|---|
| 584 | 603 | pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 604 | + no_pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 585 | 605 | |
|---|
| 586 | | - this_cpu_write(tr->trace_buffer.data->ignore_pid, |
|---|
| 587 | | - trace_ignore_this_task(pid_list, task)); |
|---|
| 606 | + this_cpu_write(tr->array_buffer.data->ignore_pid, |
|---|
| 607 | + trace_ignore_this_task(pid_list, no_pid_list, task)); |
|---|
| 588 | 608 | } |
|---|
| 589 | 609 | |
|---|
| 590 | 610 | static void |
|---|
| 591 | 611 | event_filter_pid_sched_wakeup_probe_post(void *data, struct task_struct *task) |
|---|
| 592 | 612 | { |
|---|
| 593 | 613 | struct trace_array *tr = data; |
|---|
| 614 | + struct trace_pid_list *no_pid_list; |
|---|
| 594 | 615 | struct trace_pid_list *pid_list; |
|---|
| 595 | 616 | |
|---|
| 596 | 617 | /* Nothing to do if we are not tracing */ |
|---|
| 597 | | - if (this_cpu_read(tr->trace_buffer.data->ignore_pid)) |
|---|
| 618 | + if (this_cpu_read(tr->array_buffer.data->ignore_pid)) |
|---|
| 598 | 619 | return; |
|---|
| 599 | 620 | |
|---|
| 600 | 621 | pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 622 | + no_pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 601 | 623 | |
|---|
| 602 | 624 | /* Set tracing if current is enabled */ |
|---|
| 603 | | - this_cpu_write(tr->trace_buffer.data->ignore_pid, |
|---|
| 604 | | - trace_ignore_this_task(pid_list, current)); |
|---|
| 625 | + this_cpu_write(tr->array_buffer.data->ignore_pid, |
|---|
| 626 | + trace_ignore_this_task(pid_list, no_pid_list, current)); |
|---|
| 605 | 627 | } |
|---|
| 606 | 628 | |
|---|
| 607 | | -static void __ftrace_clear_event_pids(struct trace_array *tr) |
|---|
| 629 | +static void unregister_pid_events(struct trace_array *tr) |
|---|
| 608 | 630 | { |
|---|
| 609 | | - struct trace_pid_list *pid_list; |
|---|
| 610 | | - struct trace_event_file *file; |
|---|
| 611 | | - int cpu; |
|---|
| 612 | | - |
|---|
| 613 | | - pid_list = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 614 | | - lockdep_is_held(&event_mutex)); |
|---|
| 615 | | - if (!pid_list) |
|---|
| 616 | | - return; |
|---|
| 617 | | - |
|---|
| 618 | 631 | unregister_trace_sched_switch(event_filter_pid_sched_switch_probe_pre, tr); |
|---|
| 619 | 632 | unregister_trace_sched_switch(event_filter_pid_sched_switch_probe_post, tr); |
|---|
| 620 | 633 | |
|---|
| .. | .. |
|---|
| 626 | 639 | |
|---|
| 627 | 640 | unregister_trace_sched_waking(event_filter_pid_sched_wakeup_probe_pre, tr); |
|---|
| 628 | 641 | unregister_trace_sched_waking(event_filter_pid_sched_wakeup_probe_post, tr); |
|---|
| 642 | +} |
|---|
| 629 | 643 | |
|---|
| 630 | | - list_for_each_entry(file, &tr->events, list) { |
|---|
| 631 | | - clear_bit(EVENT_FILE_FL_PID_FILTER_BIT, &file->flags); |
|---|
| 644 | +static void __ftrace_clear_event_pids(struct trace_array *tr, int type) |
|---|
| 645 | +{ |
|---|
| 646 | + struct trace_pid_list *pid_list; |
|---|
| 647 | + struct trace_pid_list *no_pid_list; |
|---|
| 648 | + struct trace_event_file *file; |
|---|
| 649 | + int cpu; |
|---|
| 650 | + |
|---|
| 651 | + pid_list = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 652 | + lockdep_is_held(&event_mutex)); |
|---|
| 653 | + no_pid_list = rcu_dereference_protected(tr->filtered_no_pids, |
|---|
| 654 | + lockdep_is_held(&event_mutex)); |
|---|
| 655 | + |
|---|
| 656 | + /* Make sure there's something to do */ |
|---|
| 657 | + if (!pid_type_enabled(type, pid_list, no_pid_list)) |
|---|
| 658 | + return; |
|---|
| 659 | + |
|---|
| 660 | + if (!still_need_pid_events(type, pid_list, no_pid_list)) { |
|---|
| 661 | + unregister_pid_events(tr); |
|---|
| 662 | + |
|---|
| 663 | + list_for_each_entry(file, &tr->events, list) { |
|---|
| 664 | + clear_bit(EVENT_FILE_FL_PID_FILTER_BIT, &file->flags); |
|---|
| 665 | + } |
|---|
| 666 | + |
|---|
| 667 | + for_each_possible_cpu(cpu) |
|---|
| 668 | + per_cpu_ptr(tr->array_buffer.data, cpu)->ignore_pid = false; |
|---|
| 632 | 669 | } |
|---|
| 633 | 670 | |
|---|
| 634 | | - for_each_possible_cpu(cpu) |
|---|
| 635 | | - per_cpu_ptr(tr->trace_buffer.data, cpu)->ignore_pid = false; |
|---|
| 671 | + if (type & TRACE_PIDS) |
|---|
| 672 | + rcu_assign_pointer(tr->filtered_pids, NULL); |
|---|
| 636 | 673 | |
|---|
| 637 | | - rcu_assign_pointer(tr->filtered_pids, NULL); |
|---|
| 674 | + if (type & TRACE_NO_PIDS) |
|---|
| 675 | + rcu_assign_pointer(tr->filtered_no_pids, NULL); |
|---|
| 638 | 676 | |
|---|
| 639 | 677 | /* Wait till all users are no longer using pid filtering */ |
|---|
| 640 | 678 | tracepoint_synchronize_unregister(); |
|---|
| 641 | 679 | |
|---|
| 642 | | - trace_free_pid_list(pid_list); |
|---|
| 680 | + if ((type & TRACE_PIDS) && pid_list) |
|---|
| 681 | + trace_free_pid_list(pid_list); |
|---|
| 682 | + |
|---|
| 683 | + if ((type & TRACE_NO_PIDS) && no_pid_list) |
|---|
| 684 | + trace_free_pid_list(no_pid_list); |
|---|
| 643 | 685 | } |
|---|
| 644 | 686 | |
|---|
| 645 | | -static void ftrace_clear_event_pids(struct trace_array *tr) |
|---|
| 687 | +static void ftrace_clear_event_pids(struct trace_array *tr, int type) |
|---|
| 646 | 688 | { |
|---|
| 647 | 689 | mutex_lock(&event_mutex); |
|---|
| 648 | | - __ftrace_clear_event_pids(tr); |
|---|
| 690 | + __ftrace_clear_event_pids(tr, type); |
|---|
| 649 | 691 | mutex_unlock(&event_mutex); |
|---|
| 650 | 692 | } |
|---|
| 651 | 693 | |
|---|
| .. | .. |
|---|
| 704 | 746 | return; |
|---|
| 705 | 747 | |
|---|
| 706 | 748 | if (!--dir->nr_events) { |
|---|
| 707 | | - tracefs_remove_recursive(dir->entry); |
|---|
| 749 | + tracefs_remove(dir->entry); |
|---|
| 708 | 750 | list_del(&dir->list); |
|---|
| 709 | 751 | __put_system_dir(dir); |
|---|
| 710 | 752 | } |
|---|
| .. | .. |
|---|
| 723 | 765 | } |
|---|
| 724 | 766 | spin_unlock(&dir->d_lock); |
|---|
| 725 | 767 | |
|---|
| 726 | | - tracefs_remove_recursive(dir); |
|---|
| 768 | + tracefs_remove(dir); |
|---|
| 727 | 769 | } |
|---|
| 728 | 770 | |
|---|
| 729 | 771 | list_del(&file->list); |
|---|
| .. | .. |
|---|
| 795 | 837 | return ret; |
|---|
| 796 | 838 | } |
|---|
| 797 | 839 | |
|---|
| 798 | | -static int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set) |
|---|
| 840 | +int ftrace_set_clr_event(struct trace_array *tr, char *buf, int set) |
|---|
| 799 | 841 | { |
|---|
| 800 | 842 | char *event = NULL, *sub = NULL, *match; |
|---|
| 801 | 843 | int ret; |
|---|
| .. | .. |
|---|
| 857 | 899 | return __ftrace_set_clr_event(tr, NULL, system, event, set); |
|---|
| 858 | 900 | } |
|---|
| 859 | 901 | EXPORT_SYMBOL_GPL(trace_set_clr_event); |
|---|
| 902 | + |
|---|
| 903 | +/** |
|---|
| 904 | + * trace_array_set_clr_event - enable or disable an event for a trace array. |
|---|
| 905 | + * @tr: concerned trace array. |
|---|
| 906 | + * @system: system name to match (NULL for any system) |
|---|
| 907 | + * @event: event name to match (NULL for all events, within system) |
|---|
| 908 | + * @enable: true to enable, false to disable |
|---|
| 909 | + * |
|---|
| 910 | + * This is a way for other parts of the kernel to enable or disable |
|---|
| 911 | + * event recording. |
|---|
| 912 | + * |
|---|
| 913 | + * Returns 0 on success, -EINVAL if the parameters do not match any |
|---|
| 914 | + * registered events. |
|---|
| 915 | + */ |
|---|
| 916 | +int trace_array_set_clr_event(struct trace_array *tr, const char *system, |
|---|
| 917 | + const char *event, bool enable) |
|---|
| 918 | +{ |
|---|
| 919 | + int set; |
|---|
| 920 | + |
|---|
| 921 | + if (!tr) |
|---|
| 922 | + return -ENOENT; |
|---|
| 923 | + |
|---|
| 924 | + set = (enable == true) ? 1 : 0; |
|---|
| 925 | + return __ftrace_set_clr_event(tr, NULL, system, event, set); |
|---|
| 926 | +} |
|---|
| 927 | +EXPORT_SYMBOL_GPL(trace_array_set_clr_event); |
|---|
| 860 | 928 | |
|---|
| 861 | 929 | /* 128 should be much more than enough */ |
|---|
| 862 | 930 | #define EVENT_BUF_SIZE 127 |
|---|
| .. | .. |
|---|
| 992 | 1060 | } |
|---|
| 993 | 1061 | |
|---|
| 994 | 1062 | static void * |
|---|
| 995 | | -p_next(struct seq_file *m, void *v, loff_t *pos) |
|---|
| 1063 | +__next(struct seq_file *m, void *v, loff_t *pos, int type) |
|---|
| 996 | 1064 | { |
|---|
| 997 | 1065 | struct trace_array *tr = m->private; |
|---|
| 998 | | - struct trace_pid_list *pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 1066 | + struct trace_pid_list *pid_list; |
|---|
| 1067 | + |
|---|
| 1068 | + if (type == TRACE_PIDS) |
|---|
| 1069 | + pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 1070 | + else |
|---|
| 1071 | + pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 999 | 1072 | |
|---|
| 1000 | 1073 | return trace_pid_next(pid_list, v, pos); |
|---|
| 1001 | 1074 | } |
|---|
| 1002 | 1075 | |
|---|
| 1003 | | -static void *p_start(struct seq_file *m, loff_t *pos) |
|---|
| 1076 | +static void * |
|---|
| 1077 | +p_next(struct seq_file *m, void *v, loff_t *pos) |
|---|
| 1078 | +{ |
|---|
| 1079 | + return __next(m, v, pos, TRACE_PIDS); |
|---|
| 1080 | +} |
|---|
| 1081 | + |
|---|
| 1082 | +static void * |
|---|
| 1083 | +np_next(struct seq_file *m, void *v, loff_t *pos) |
|---|
| 1084 | +{ |
|---|
| 1085 | + return __next(m, v, pos, TRACE_NO_PIDS); |
|---|
| 1086 | +} |
|---|
| 1087 | + |
|---|
| 1088 | +static void *__start(struct seq_file *m, loff_t *pos, int type) |
|---|
| 1004 | 1089 | __acquires(RCU) |
|---|
| 1005 | 1090 | { |
|---|
| 1006 | 1091 | struct trace_pid_list *pid_list; |
|---|
| .. | .. |
|---|
| 1015 | 1100 | mutex_lock(&event_mutex); |
|---|
| 1016 | 1101 | rcu_read_lock_sched(); |
|---|
| 1017 | 1102 | |
|---|
| 1018 | | - pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 1103 | + if (type == TRACE_PIDS) |
|---|
| 1104 | + pid_list = rcu_dereference_sched(tr->filtered_pids); |
|---|
| 1105 | + else |
|---|
| 1106 | + pid_list = rcu_dereference_sched(tr->filtered_no_pids); |
|---|
| 1019 | 1107 | |
|---|
| 1020 | 1108 | if (!pid_list) |
|---|
| 1021 | 1109 | return NULL; |
|---|
| 1022 | 1110 | |
|---|
| 1023 | 1111 | return trace_pid_start(pid_list, pos); |
|---|
| 1112 | +} |
|---|
| 1113 | + |
|---|
| 1114 | +static void *p_start(struct seq_file *m, loff_t *pos) |
|---|
| 1115 | + __acquires(RCU) |
|---|
| 1116 | +{ |
|---|
| 1117 | + return __start(m, pos, TRACE_PIDS); |
|---|
| 1118 | +} |
|---|
| 1119 | + |
|---|
| 1120 | +static void *np_start(struct seq_file *m, loff_t *pos) |
|---|
| 1121 | + __acquires(RCU) |
|---|
| 1122 | +{ |
|---|
| 1123 | + return __start(m, pos, TRACE_NO_PIDS); |
|---|
| 1024 | 1124 | } |
|---|
| 1025 | 1125 | |
|---|
| 1026 | 1126 | static void p_stop(struct seq_file *m, void *p) |
|---|
| .. | .. |
|---|
| 1254 | 1354 | */ |
|---|
| 1255 | 1355 | array_descriptor = strchr(field->type, '['); |
|---|
| 1256 | 1356 | |
|---|
| 1257 | | - if (!strncmp(field->type, "__data_loc", 10)) |
|---|
| 1357 | + if (str_has_prefix(field->type, "__data_loc")) |
|---|
| 1258 | 1358 | array_descriptor = NULL; |
|---|
| 1259 | 1359 | |
|---|
| 1260 | 1360 | if (!array_descriptor) |
|---|
| .. | .. |
|---|
| 1303 | 1403 | { |
|---|
| 1304 | 1404 | struct seq_file *m; |
|---|
| 1305 | 1405 | int ret; |
|---|
| 1406 | + |
|---|
| 1407 | + /* Do we want to hide event format files on tracefs lockdown? */ |
|---|
| 1306 | 1408 | |
|---|
| 1307 | 1409 | ret = seq_open(file, &trace_format_seq_ops); |
|---|
| 1308 | 1410 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 1450 | 1552 | struct trace_array *tr = inode->i_private; |
|---|
| 1451 | 1553 | int ret; |
|---|
| 1452 | 1554 | |
|---|
| 1453 | | - if (tracing_is_disabled()) |
|---|
| 1454 | | - return -ENODEV; |
|---|
| 1455 | | - |
|---|
| 1456 | | - if (trace_array_get(tr) < 0) |
|---|
| 1457 | | - return -ENODEV; |
|---|
| 1458 | | - |
|---|
| 1459 | 1555 | /* Make a temporary dir that has no system but points to tr */ |
|---|
| 1460 | 1556 | dir = kzalloc(sizeof(*dir), GFP_KERNEL); |
|---|
| 1461 | | - if (!dir) { |
|---|
| 1462 | | - trace_array_put(tr); |
|---|
| 1557 | + if (!dir) |
|---|
| 1463 | 1558 | return -ENOMEM; |
|---|
| 1464 | | - } |
|---|
| 1465 | 1559 | |
|---|
| 1466 | | - dir->tr = tr; |
|---|
| 1467 | | - |
|---|
| 1468 | | - ret = tracing_open_generic(inode, filp); |
|---|
| 1560 | + ret = tracing_open_generic_tr(inode, filp); |
|---|
| 1469 | 1561 | if (ret < 0) { |
|---|
| 1470 | | - trace_array_put(tr); |
|---|
| 1471 | 1562 | kfree(dir); |
|---|
| 1472 | 1563 | return ret; |
|---|
| 1473 | 1564 | } |
|---|
| 1474 | | - |
|---|
| 1565 | + dir->tr = tr; |
|---|
| 1475 | 1566 | filp->private_data = dir; |
|---|
| 1476 | 1567 | |
|---|
| 1477 | 1568 | return 0; |
|---|
| .. | .. |
|---|
| 1577 | 1668 | { |
|---|
| 1578 | 1669 | struct trace_array *tr = data; |
|---|
| 1579 | 1670 | struct trace_pid_list *pid_list; |
|---|
| 1671 | + struct trace_pid_list *no_pid_list; |
|---|
| 1580 | 1672 | |
|---|
| 1581 | 1673 | /* |
|---|
| 1582 | 1674 | * This function is called by on_each_cpu() while the |
|---|
| .. | .. |
|---|
| 1584 | 1676 | */ |
|---|
| 1585 | 1677 | pid_list = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 1586 | 1678 | mutex_is_locked(&event_mutex)); |
|---|
| 1679 | + no_pid_list = rcu_dereference_protected(tr->filtered_no_pids, |
|---|
| 1680 | + mutex_is_locked(&event_mutex)); |
|---|
| 1587 | 1681 | |
|---|
| 1588 | | - this_cpu_write(tr->trace_buffer.data->ignore_pid, |
|---|
| 1589 | | - trace_ignore_this_task(pid_list, current)); |
|---|
| 1682 | + this_cpu_write(tr->array_buffer.data->ignore_pid, |
|---|
| 1683 | + trace_ignore_this_task(pid_list, no_pid_list, current)); |
|---|
| 1684 | +} |
|---|
| 1685 | + |
|---|
| 1686 | +static void register_pid_events(struct trace_array *tr) |
|---|
| 1687 | +{ |
|---|
| 1688 | + /* |
|---|
| 1689 | + * Register a probe that is called before all other probes |
|---|
| 1690 | + * to set ignore_pid if next or prev do not match. |
|---|
| 1691 | + * Register a probe this is called after all other probes |
|---|
| 1692 | + * to only keep ignore_pid set if next pid matches. |
|---|
| 1693 | + */ |
|---|
| 1694 | + register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_pre, |
|---|
| 1695 | + tr, INT_MAX); |
|---|
| 1696 | + register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_post, |
|---|
| 1697 | + tr, 0); |
|---|
| 1698 | + |
|---|
| 1699 | + register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1700 | + tr, INT_MAX); |
|---|
| 1701 | + register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1702 | + tr, 0); |
|---|
| 1703 | + |
|---|
| 1704 | + register_trace_prio_sched_wakeup_new(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1705 | + tr, INT_MAX); |
|---|
| 1706 | + register_trace_prio_sched_wakeup_new(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1707 | + tr, 0); |
|---|
| 1708 | + |
|---|
| 1709 | + register_trace_prio_sched_waking(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1710 | + tr, INT_MAX); |
|---|
| 1711 | + register_trace_prio_sched_waking(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1712 | + tr, 0); |
|---|
| 1590 | 1713 | } |
|---|
| 1591 | 1714 | |
|---|
| 1592 | 1715 | static ssize_t |
|---|
| 1593 | | -ftrace_event_pid_write(struct file *filp, const char __user *ubuf, |
|---|
| 1594 | | - size_t cnt, loff_t *ppos) |
|---|
| 1716 | +event_pid_write(struct file *filp, const char __user *ubuf, |
|---|
| 1717 | + size_t cnt, loff_t *ppos, int type) |
|---|
| 1595 | 1718 | { |
|---|
| 1596 | 1719 | struct seq_file *m = filp->private_data; |
|---|
| 1597 | 1720 | struct trace_array *tr = m->private; |
|---|
| 1598 | 1721 | struct trace_pid_list *filtered_pids = NULL; |
|---|
| 1722 | + struct trace_pid_list *other_pids = NULL; |
|---|
| 1599 | 1723 | struct trace_pid_list *pid_list; |
|---|
| 1600 | 1724 | struct trace_event_file *file; |
|---|
| 1601 | 1725 | ssize_t ret; |
|---|
| .. | .. |
|---|
| 1609 | 1733 | |
|---|
| 1610 | 1734 | mutex_lock(&event_mutex); |
|---|
| 1611 | 1735 | |
|---|
| 1612 | | - filtered_pids = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 1613 | | - lockdep_is_held(&event_mutex)); |
|---|
| 1736 | + if (type == TRACE_PIDS) { |
|---|
| 1737 | + filtered_pids = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 1738 | + lockdep_is_held(&event_mutex)); |
|---|
| 1739 | + other_pids = rcu_dereference_protected(tr->filtered_no_pids, |
|---|
| 1740 | + lockdep_is_held(&event_mutex)); |
|---|
| 1741 | + } else { |
|---|
| 1742 | + filtered_pids = rcu_dereference_protected(tr->filtered_no_pids, |
|---|
| 1743 | + lockdep_is_held(&event_mutex)); |
|---|
| 1744 | + other_pids = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 1745 | + lockdep_is_held(&event_mutex)); |
|---|
| 1746 | + } |
|---|
| 1614 | 1747 | |
|---|
| 1615 | 1748 | ret = trace_pid_write(filtered_pids, &pid_list, ubuf, cnt); |
|---|
| 1616 | 1749 | if (ret < 0) |
|---|
| 1617 | 1750 | goto out; |
|---|
| 1618 | 1751 | |
|---|
| 1619 | | - rcu_assign_pointer(tr->filtered_pids, pid_list); |
|---|
| 1752 | + if (type == TRACE_PIDS) |
|---|
| 1753 | + rcu_assign_pointer(tr->filtered_pids, pid_list); |
|---|
| 1754 | + else |
|---|
| 1755 | + rcu_assign_pointer(tr->filtered_no_pids, pid_list); |
|---|
| 1620 | 1756 | |
|---|
| 1621 | 1757 | list_for_each_entry(file, &tr->events, list) { |
|---|
| 1622 | 1758 | set_bit(EVENT_FILE_FL_PID_FILTER_BIT, &file->flags); |
|---|
| .. | .. |
|---|
| 1625 | 1761 | if (filtered_pids) { |
|---|
| 1626 | 1762 | tracepoint_synchronize_unregister(); |
|---|
| 1627 | 1763 | trace_free_pid_list(filtered_pids); |
|---|
| 1628 | | - } else if (pid_list) { |
|---|
| 1629 | | - /* |
|---|
| 1630 | | - * Register a probe that is called before all other probes |
|---|
| 1631 | | - * to set ignore_pid if next or prev do not match. |
|---|
| 1632 | | - * Register a probe this is called after all other probes |
|---|
| 1633 | | - * to only keep ignore_pid set if next pid matches. |
|---|
| 1634 | | - */ |
|---|
| 1635 | | - register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_pre, |
|---|
| 1636 | | - tr, INT_MAX); |
|---|
| 1637 | | - register_trace_prio_sched_switch(event_filter_pid_sched_switch_probe_post, |
|---|
| 1638 | | - tr, 0); |
|---|
| 1639 | | - |
|---|
| 1640 | | - register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1641 | | - tr, INT_MAX); |
|---|
| 1642 | | - register_trace_prio_sched_wakeup(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1643 | | - tr, 0); |
|---|
| 1644 | | - |
|---|
| 1645 | | - register_trace_prio_sched_wakeup_new(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1646 | | - tr, INT_MAX); |
|---|
| 1647 | | - register_trace_prio_sched_wakeup_new(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1648 | | - tr, 0); |
|---|
| 1649 | | - |
|---|
| 1650 | | - register_trace_prio_sched_waking(event_filter_pid_sched_wakeup_probe_pre, |
|---|
| 1651 | | - tr, INT_MAX); |
|---|
| 1652 | | - register_trace_prio_sched_waking(event_filter_pid_sched_wakeup_probe_post, |
|---|
| 1653 | | - tr, 0); |
|---|
| 1764 | + } else if (pid_list && !other_pids) { |
|---|
| 1765 | + register_pid_events(tr); |
|---|
| 1654 | 1766 | } |
|---|
| 1655 | 1767 | |
|---|
| 1656 | 1768 | /* |
|---|
| .. | .. |
|---|
| 1669 | 1781 | return ret; |
|---|
| 1670 | 1782 | } |
|---|
| 1671 | 1783 | |
|---|
| 1784 | +static ssize_t |
|---|
| 1785 | +ftrace_event_pid_write(struct file *filp, const char __user *ubuf, |
|---|
| 1786 | + size_t cnt, loff_t *ppos) |
|---|
| 1787 | +{ |
|---|
| 1788 | + return event_pid_write(filp, ubuf, cnt, ppos, TRACE_PIDS); |
|---|
| 1789 | +} |
|---|
| 1790 | + |
|---|
| 1791 | +static ssize_t |
|---|
| 1792 | +ftrace_event_npid_write(struct file *filp, const char __user *ubuf, |
|---|
| 1793 | + size_t cnt, loff_t *ppos) |
|---|
| 1794 | +{ |
|---|
| 1795 | + return event_pid_write(filp, ubuf, cnt, ppos, TRACE_NO_PIDS); |
|---|
| 1796 | +} |
|---|
| 1797 | + |
|---|
| 1672 | 1798 | static int ftrace_event_avail_open(struct inode *inode, struct file *file); |
|---|
| 1673 | 1799 | static int ftrace_event_set_open(struct inode *inode, struct file *file); |
|---|
| 1674 | 1800 | static int ftrace_event_set_pid_open(struct inode *inode, struct file *file); |
|---|
| 1801 | +static int ftrace_event_set_npid_open(struct inode *inode, struct file *file); |
|---|
| 1675 | 1802 | static int ftrace_event_release(struct inode *inode, struct file *file); |
|---|
| 1676 | 1803 | |
|---|
| 1677 | 1804 | static const struct seq_operations show_event_seq_ops = { |
|---|
| .. | .. |
|---|
| 1695 | 1822 | .stop = p_stop, |
|---|
| 1696 | 1823 | }; |
|---|
| 1697 | 1824 | |
|---|
| 1825 | +static const struct seq_operations show_set_no_pid_seq_ops = { |
|---|
| 1826 | + .start = np_start, |
|---|
| 1827 | + .next = np_next, |
|---|
| 1828 | + .show = trace_pid_show, |
|---|
| 1829 | + .stop = p_stop, |
|---|
| 1830 | +}; |
|---|
| 1831 | + |
|---|
| 1698 | 1832 | static const struct file_operations ftrace_avail_fops = { |
|---|
| 1699 | 1833 | .open = ftrace_event_avail_open, |
|---|
| 1700 | 1834 | .read = seq_read, |
|---|
| .. | .. |
|---|
| 1714 | 1848 | .open = ftrace_event_set_pid_open, |
|---|
| 1715 | 1849 | .read = seq_read, |
|---|
| 1716 | 1850 | .write = ftrace_event_pid_write, |
|---|
| 1851 | + .llseek = seq_lseek, |
|---|
| 1852 | + .release = ftrace_event_release, |
|---|
| 1853 | +}; |
|---|
| 1854 | + |
|---|
| 1855 | +static const struct file_operations ftrace_set_event_notrace_pid_fops = { |
|---|
| 1856 | + .open = ftrace_event_set_npid_open, |
|---|
| 1857 | + .read = seq_read, |
|---|
| 1858 | + .write = ftrace_event_npid_write, |
|---|
| 1717 | 1859 | .llseek = seq_lseek, |
|---|
| 1718 | 1860 | .release = ftrace_event_release, |
|---|
| 1719 | 1861 | }; |
|---|
| .. | .. |
|---|
| 1781 | 1923 | struct seq_file *m; |
|---|
| 1782 | 1924 | int ret; |
|---|
| 1783 | 1925 | |
|---|
| 1926 | + ret = security_locked_down(LOCKDOWN_TRACEFS); |
|---|
| 1927 | + if (ret) |
|---|
| 1928 | + return ret; |
|---|
| 1929 | + |
|---|
| 1784 | 1930 | ret = seq_open(file, seq_ops); |
|---|
| 1785 | 1931 | if (ret < 0) |
|---|
| 1786 | 1932 | return ret; |
|---|
| .. | .. |
|---|
| 1805 | 1951 | { |
|---|
| 1806 | 1952 | const struct seq_operations *seq_ops = &show_event_seq_ops; |
|---|
| 1807 | 1953 | |
|---|
| 1954 | + /* Checks for tracefs lockdown */ |
|---|
| 1808 | 1955 | return ftrace_event_open(inode, file, seq_ops); |
|---|
| 1809 | 1956 | } |
|---|
| 1810 | 1957 | |
|---|
| .. | .. |
|---|
| 1815 | 1962 | struct trace_array *tr = inode->i_private; |
|---|
| 1816 | 1963 | int ret; |
|---|
| 1817 | 1964 | |
|---|
| 1818 | | - if (trace_array_get(tr) < 0) |
|---|
| 1819 | | - return -ENODEV; |
|---|
| 1965 | + ret = tracing_check_open_get_tr(tr); |
|---|
| 1966 | + if (ret) |
|---|
| 1967 | + return ret; |
|---|
| 1820 | 1968 | |
|---|
| 1821 | 1969 | if ((file->f_mode & FMODE_WRITE) && |
|---|
| 1822 | 1970 | (file->f_flags & O_TRUNC)) |
|---|
| .. | .. |
|---|
| 1835 | 1983 | struct trace_array *tr = inode->i_private; |
|---|
| 1836 | 1984 | int ret; |
|---|
| 1837 | 1985 | |
|---|
| 1838 | | - if (trace_array_get(tr) < 0) |
|---|
| 1839 | | - return -ENODEV; |
|---|
| 1986 | + ret = tracing_check_open_get_tr(tr); |
|---|
| 1987 | + if (ret) |
|---|
| 1988 | + return ret; |
|---|
| 1840 | 1989 | |
|---|
| 1841 | 1990 | if ((file->f_mode & FMODE_WRITE) && |
|---|
| 1842 | 1991 | (file->f_flags & O_TRUNC)) |
|---|
| 1843 | | - ftrace_clear_event_pids(tr); |
|---|
| 1992 | + ftrace_clear_event_pids(tr, TRACE_PIDS); |
|---|
| 1993 | + |
|---|
| 1994 | + ret = ftrace_event_open(inode, file, seq_ops); |
|---|
| 1995 | + if (ret < 0) |
|---|
| 1996 | + trace_array_put(tr); |
|---|
| 1997 | + return ret; |
|---|
| 1998 | +} |
|---|
| 1999 | + |
|---|
| 2000 | +static int |
|---|
| 2001 | +ftrace_event_set_npid_open(struct inode *inode, struct file *file) |
|---|
| 2002 | +{ |
|---|
| 2003 | + const struct seq_operations *seq_ops = &show_set_no_pid_seq_ops; |
|---|
| 2004 | + struct trace_array *tr = inode->i_private; |
|---|
| 2005 | + int ret; |
|---|
| 2006 | + |
|---|
| 2007 | + ret = tracing_check_open_get_tr(tr); |
|---|
| 2008 | + if (ret) |
|---|
| 2009 | + return ret; |
|---|
| 2010 | + |
|---|
| 2011 | + if ((file->f_mode & FMODE_WRITE) && |
|---|
| 2012 | + (file->f_flags & O_TRUNC)) |
|---|
| 2013 | + ftrace_clear_event_pids(tr, TRACE_NO_PIDS); |
|---|
| 1844 | 2014 | |
|---|
| 1845 | 2015 | ret = ftrace_event_open(inode, file, seq_ops); |
|---|
| 1846 | 2016 | if (ret < 0) |
|---|
| .. | .. |
|---|
| 1957 | 2127 | } |
|---|
| 1958 | 2128 | |
|---|
| 1959 | 2129 | static int |
|---|
| 2130 | +event_define_fields(struct trace_event_call *call) |
|---|
| 2131 | +{ |
|---|
| 2132 | + struct list_head *head; |
|---|
| 2133 | + int ret = 0; |
|---|
| 2134 | + |
|---|
| 2135 | + /* |
|---|
| 2136 | + * Other events may have the same class. Only update |
|---|
| 2137 | + * the fields if they are not already defined. |
|---|
| 2138 | + */ |
|---|
| 2139 | + head = trace_get_fields(call); |
|---|
| 2140 | + if (list_empty(head)) { |
|---|
| 2141 | + struct trace_event_fields *field = call->class->fields_array; |
|---|
| 2142 | + unsigned int offset = sizeof(struct trace_entry); |
|---|
| 2143 | + |
|---|
| 2144 | + for (; field->type; field++) { |
|---|
| 2145 | + if (field->type == TRACE_FUNCTION_TYPE) { |
|---|
| 2146 | + field->define_fields(call); |
|---|
| 2147 | + break; |
|---|
| 2148 | + } |
|---|
| 2149 | + |
|---|
| 2150 | + offset = ALIGN(offset, field->align); |
|---|
| 2151 | + ret = trace_define_field(call, field->type, field->name, |
|---|
| 2152 | + offset, field->size, |
|---|
| 2153 | + field->is_signed, field->filter_type); |
|---|
| 2154 | + if (WARN_ON_ONCE(ret)) { |
|---|
| 2155 | + pr_err("error code is %d\n", ret); |
|---|
| 2156 | + break; |
|---|
| 2157 | + } |
|---|
| 2158 | + |
|---|
| 2159 | + offset += field->size; |
|---|
| 2160 | + } |
|---|
| 2161 | + } |
|---|
| 2162 | + |
|---|
| 2163 | + return ret; |
|---|
| 2164 | +} |
|---|
| 2165 | + |
|---|
| 2166 | +static int |
|---|
| 1960 | 2167 | event_create_dir(struct dentry *parent, struct trace_event_file *file) |
|---|
| 1961 | 2168 | { |
|---|
| 1962 | 2169 | struct trace_event_call *call = file->event_call; |
|---|
| 1963 | 2170 | struct trace_array *tr = file->tr; |
|---|
| 1964 | | - struct list_head *head; |
|---|
| 1965 | 2171 | struct dentry *d_events; |
|---|
| 1966 | 2172 | const char *name; |
|---|
| 1967 | 2173 | int ret; |
|---|
| .. | .. |
|---|
| 1995 | 2201 | &ftrace_event_id_fops); |
|---|
| 1996 | 2202 | #endif |
|---|
| 1997 | 2203 | |
|---|
| 1998 | | - /* |
|---|
| 1999 | | - * Other events may have the same class. Only update |
|---|
| 2000 | | - * the fields if they are not already defined. |
|---|
| 2001 | | - */ |
|---|
| 2002 | | - head = trace_get_fields(call); |
|---|
| 2003 | | - if (list_empty(head)) { |
|---|
| 2004 | | - ret = call->class->define_fields(call); |
|---|
| 2005 | | - if (ret < 0) { |
|---|
| 2006 | | - pr_warn("Could not initialize trace point events/%s\n", |
|---|
| 2007 | | - name); |
|---|
| 2008 | | - return -1; |
|---|
| 2009 | | - } |
|---|
| 2204 | + ret = event_define_fields(call); |
|---|
| 2205 | + if (ret < 0) { |
|---|
| 2206 | + pr_warn("Could not initialize trace point events/%s\n", name); |
|---|
| 2207 | + return ret; |
|---|
| 2010 | 2208 | } |
|---|
| 2011 | 2209 | |
|---|
| 2012 | 2210 | /* |
|---|
| .. | .. |
|---|
| 2025 | 2223 | trace_create_file("hist", 0444, file->dir, file, |
|---|
| 2026 | 2224 | &event_hist_fops); |
|---|
| 2027 | 2225 | #endif |
|---|
| 2226 | +#ifdef CONFIG_HIST_TRIGGERS_DEBUG |
|---|
| 2227 | + trace_create_file("hist_debug", 0444, file->dir, file, |
|---|
| 2228 | + &event_hist_debug_fops); |
|---|
| 2229 | +#endif |
|---|
| 2028 | 2230 | trace_create_file("format", 0444, file->dir, call, |
|---|
| 2029 | 2231 | &ftrace_event_format_fops); |
|---|
| 2232 | + |
|---|
| 2233 | +#ifdef CONFIG_TRACE_EVENT_INJECT |
|---|
| 2234 | + if (call->event.type && call->class->reg) |
|---|
| 2235 | + trace_create_file("inject", 0200, file->dir, file, |
|---|
| 2236 | + &event_inject_fops); |
|---|
| 2237 | +#endif |
|---|
| 2030 | 2238 | |
|---|
| 2031 | 2239 | return 0; |
|---|
| 2032 | 2240 | } |
|---|
| .. | .. |
|---|
| 2255 | 2463 | trace_create_new_event(struct trace_event_call *call, |
|---|
| 2256 | 2464 | struct trace_array *tr) |
|---|
| 2257 | 2465 | { |
|---|
| 2466 | + struct trace_pid_list *no_pid_list; |
|---|
| 2258 | 2467 | struct trace_pid_list *pid_list; |
|---|
| 2259 | 2468 | struct trace_event_file *file; |
|---|
| 2260 | 2469 | |
|---|
| .. | .. |
|---|
| 2264 | 2473 | |
|---|
| 2265 | 2474 | pid_list = rcu_dereference_protected(tr->filtered_pids, |
|---|
| 2266 | 2475 | lockdep_is_held(&event_mutex)); |
|---|
| 2476 | + no_pid_list = rcu_dereference_protected(tr->filtered_no_pids, |
|---|
| 2477 | + lockdep_is_held(&event_mutex)); |
|---|
| 2267 | 2478 | |
|---|
| 2268 | | - if (pid_list) |
|---|
| 2479 | + if (pid_list || no_pid_list) |
|---|
| 2269 | 2480 | file->flags |= EVENT_FILE_FL_PID_FILTER; |
|---|
| 2270 | 2481 | |
|---|
| 2271 | 2482 | file->event_call = call; |
|---|
| .. | .. |
|---|
| 2288 | 2499 | if (!file) |
|---|
| 2289 | 2500 | return -ENOMEM; |
|---|
| 2290 | 2501 | |
|---|
| 2291 | | - return event_create_dir(tr->event_dir, file); |
|---|
| 2502 | + if (eventdir_initialized) |
|---|
| 2503 | + return event_create_dir(tr->event_dir, file); |
|---|
| 2504 | + else |
|---|
| 2505 | + return event_define_fields(call); |
|---|
| 2292 | 2506 | } |
|---|
| 2293 | 2507 | |
|---|
| 2294 | 2508 | /* |
|---|
| .. | .. |
|---|
| 2296 | 2510 | * for enabling events at boot. We want to enable events before |
|---|
| 2297 | 2511 | * the filesystem is initialized. |
|---|
| 2298 | 2512 | */ |
|---|
| 2299 | | -static __init int |
|---|
| 2513 | +static int |
|---|
| 2300 | 2514 | __trace_early_add_new_event(struct trace_event_call *call, |
|---|
| 2301 | 2515 | struct trace_array *tr) |
|---|
| 2302 | 2516 | { |
|---|
| .. | .. |
|---|
| 2306 | 2520 | if (!file) |
|---|
| 2307 | 2521 | return -ENOMEM; |
|---|
| 2308 | 2522 | |
|---|
| 2309 | | - return 0; |
|---|
| 2523 | + return event_define_fields(call); |
|---|
| 2310 | 2524 | } |
|---|
| 2311 | 2525 | |
|---|
| 2312 | 2526 | struct ftrace_module_file_ops; |
|---|
| 2313 | 2527 | static void __add_event_to_tracers(struct trace_event_call *call); |
|---|
| 2314 | 2528 | |
|---|
| 2315 | | -int trace_add_event_call_nolock(struct trace_event_call *call) |
|---|
| 2529 | +/* Add an additional event_call dynamically */ |
|---|
| 2530 | +int trace_add_event_call(struct trace_event_call *call) |
|---|
| 2316 | 2531 | { |
|---|
| 2317 | 2532 | int ret; |
|---|
| 2318 | 2533 | lockdep_assert_held(&event_mutex); |
|---|
| .. | .. |
|---|
| 2324 | 2539 | __add_event_to_tracers(call); |
|---|
| 2325 | 2540 | |
|---|
| 2326 | 2541 | mutex_unlock(&trace_types_lock); |
|---|
| 2327 | | - return ret; |
|---|
| 2328 | | -} |
|---|
| 2329 | | - |
|---|
| 2330 | | -/* Add an additional event_call dynamically */ |
|---|
| 2331 | | -int trace_add_event_call(struct trace_event_call *call) |
|---|
| 2332 | | -{ |
|---|
| 2333 | | - int ret; |
|---|
| 2334 | | - |
|---|
| 2335 | | - mutex_lock(&event_mutex); |
|---|
| 2336 | | - ret = trace_add_event_call_nolock(call); |
|---|
| 2337 | | - mutex_unlock(&event_mutex); |
|---|
| 2338 | 2542 | return ret; |
|---|
| 2339 | 2543 | } |
|---|
| 2340 | 2544 | |
|---|
| .. | .. |
|---|
| 2368 | 2572 | * TRACE_REG_UNREGISTER. |
|---|
| 2369 | 2573 | */ |
|---|
| 2370 | 2574 | if (file->flags & EVENT_FILE_FL_ENABLED) |
|---|
| 2371 | | - return -EBUSY; |
|---|
| 2575 | + goto busy; |
|---|
| 2576 | + |
|---|
| 2577 | + if (file->flags & EVENT_FILE_FL_WAS_ENABLED) |
|---|
| 2578 | + tr->clear_trace = true; |
|---|
| 2372 | 2579 | /* |
|---|
| 2373 | 2580 | * The do_for_each_event_file_safe() is |
|---|
| 2374 | 2581 | * a double loop. After finding the call for this |
|---|
| .. | .. |
|---|
| 2381 | 2588 | __trace_remove_event_call(call); |
|---|
| 2382 | 2589 | |
|---|
| 2383 | 2590 | return 0; |
|---|
| 2591 | + busy: |
|---|
| 2592 | + /* No need to clear the trace now */ |
|---|
| 2593 | + list_for_each_entry(tr, &ftrace_trace_arrays, list) { |
|---|
| 2594 | + tr->clear_trace = false; |
|---|
| 2595 | + } |
|---|
| 2596 | + return -EBUSY; |
|---|
| 2384 | 2597 | } |
|---|
| 2385 | 2598 | |
|---|
| 2386 | | -/* no event_mutex version */ |
|---|
| 2387 | | -int trace_remove_event_call_nolock(struct trace_event_call *call) |
|---|
| 2599 | +/* Remove an event_call */ |
|---|
| 2600 | +int trace_remove_event_call(struct trace_event_call *call) |
|---|
| 2388 | 2601 | { |
|---|
| 2389 | 2602 | int ret; |
|---|
| 2390 | 2603 | |
|---|
| .. | .. |
|---|
| 2395 | 2608 | ret = probe_remove_event_call(call); |
|---|
| 2396 | 2609 | up_write(&trace_event_sem); |
|---|
| 2397 | 2610 | mutex_unlock(&trace_types_lock); |
|---|
| 2398 | | - |
|---|
| 2399 | | - return ret; |
|---|
| 2400 | | -} |
|---|
| 2401 | | - |
|---|
| 2402 | | -/* Remove an event_call */ |
|---|
| 2403 | | -int trace_remove_event_call(struct trace_event_call *call) |
|---|
| 2404 | | -{ |
|---|
| 2405 | | - int ret; |
|---|
| 2406 | | - |
|---|
| 2407 | | - mutex_lock(&event_mutex); |
|---|
| 2408 | | - ret = trace_remove_event_call_nolock(call); |
|---|
| 2409 | | - mutex_unlock(&event_mutex); |
|---|
| 2410 | 2611 | |
|---|
| 2411 | 2612 | return ret; |
|---|
| 2412 | 2613 | } |
|---|
| .. | .. |
|---|
| 2481 | 2682 | mutex_unlock(&trace_types_lock); |
|---|
| 2482 | 2683 | mutex_unlock(&event_mutex); |
|---|
| 2483 | 2684 | |
|---|
| 2484 | | - return 0; |
|---|
| 2685 | + return NOTIFY_OK; |
|---|
| 2485 | 2686 | } |
|---|
| 2486 | 2687 | |
|---|
| 2487 | 2688 | static struct notifier_block trace_module_nb = { |
|---|
| .. | .. |
|---|
| 2541 | 2742 | |
|---|
| 2542 | 2743 | return file; |
|---|
| 2543 | 2744 | } |
|---|
| 2745 | + |
|---|
| 2746 | +/** |
|---|
| 2747 | + * trace_get_event_file - Find and return a trace event file |
|---|
| 2748 | + * @instance: The name of the trace instance containing the event |
|---|
| 2749 | + * @system: The name of the system containing the event |
|---|
| 2750 | + * @event: The name of the event |
|---|
| 2751 | + * |
|---|
| 2752 | + * Return a trace event file given the trace instance name, trace |
|---|
| 2753 | + * system, and trace event name. If the instance name is NULL, it |
|---|
| 2754 | + * refers to the top-level trace array. |
|---|
| 2755 | + * |
|---|
| 2756 | + * This function will look it up and return it if found, after calling |
|---|
| 2757 | + * trace_array_get() to prevent the instance from going away, and |
|---|
| 2758 | + * increment the event's module refcount to prevent it from being |
|---|
| 2759 | + * removed. |
|---|
| 2760 | + * |
|---|
| 2761 | + * To release the file, call trace_put_event_file(), which will call |
|---|
| 2762 | + * trace_array_put() and decrement the event's module refcount. |
|---|
| 2763 | + * |
|---|
| 2764 | + * Return: The trace event on success, ERR_PTR otherwise. |
|---|
| 2765 | + */ |
|---|
| 2766 | +struct trace_event_file *trace_get_event_file(const char *instance, |
|---|
| 2767 | + const char *system, |
|---|
| 2768 | + const char *event) |
|---|
| 2769 | +{ |
|---|
| 2770 | + struct trace_array *tr = top_trace_array(); |
|---|
| 2771 | + struct trace_event_file *file = NULL; |
|---|
| 2772 | + int ret = -EINVAL; |
|---|
| 2773 | + |
|---|
| 2774 | + if (instance) { |
|---|
| 2775 | + tr = trace_array_find_get(instance); |
|---|
| 2776 | + if (!tr) |
|---|
| 2777 | + return ERR_PTR(-ENOENT); |
|---|
| 2778 | + } else { |
|---|
| 2779 | + ret = trace_array_get(tr); |
|---|
| 2780 | + if (ret) |
|---|
| 2781 | + return ERR_PTR(ret); |
|---|
| 2782 | + } |
|---|
| 2783 | + |
|---|
| 2784 | + mutex_lock(&event_mutex); |
|---|
| 2785 | + |
|---|
| 2786 | + file = find_event_file(tr, system, event); |
|---|
| 2787 | + if (!file) { |
|---|
| 2788 | + trace_array_put(tr); |
|---|
| 2789 | + ret = -EINVAL; |
|---|
| 2790 | + goto out; |
|---|
| 2791 | + } |
|---|
| 2792 | + |
|---|
| 2793 | + /* Don't let event modules unload while in use */ |
|---|
| 2794 | + ret = try_module_get(file->event_call->mod); |
|---|
| 2795 | + if (!ret) { |
|---|
| 2796 | + trace_array_put(tr); |
|---|
| 2797 | + ret = -EBUSY; |
|---|
| 2798 | + goto out; |
|---|
| 2799 | + } |
|---|
| 2800 | + |
|---|
| 2801 | + ret = 0; |
|---|
| 2802 | + out: |
|---|
| 2803 | + mutex_unlock(&event_mutex); |
|---|
| 2804 | + |
|---|
| 2805 | + if (ret) |
|---|
| 2806 | + file = ERR_PTR(ret); |
|---|
| 2807 | + |
|---|
| 2808 | + return file; |
|---|
| 2809 | +} |
|---|
| 2810 | +EXPORT_SYMBOL_GPL(trace_get_event_file); |
|---|
| 2811 | + |
|---|
| 2812 | +/** |
|---|
| 2813 | + * trace_put_event_file - Release a file from trace_get_event_file() |
|---|
| 2814 | + * @file: The trace event file |
|---|
| 2815 | + * |
|---|
| 2816 | + * If a file was retrieved using trace_get_event_file(), this should |
|---|
| 2817 | + * be called when it's no longer needed. It will cancel the previous |
|---|
| 2818 | + * trace_array_get() called by that function, and decrement the |
|---|
| 2819 | + * event's module refcount. |
|---|
| 2820 | + */ |
|---|
| 2821 | +void trace_put_event_file(struct trace_event_file *file) |
|---|
| 2822 | +{ |
|---|
| 2823 | + mutex_lock(&event_mutex); |
|---|
| 2824 | + module_put(file->event_call->mod); |
|---|
| 2825 | + mutex_unlock(&event_mutex); |
|---|
| 2826 | + |
|---|
| 2827 | + trace_array_put(file->tr); |
|---|
| 2828 | +} |
|---|
| 2829 | +EXPORT_SYMBOL_GPL(trace_put_event_file); |
|---|
| 2544 | 2830 | |
|---|
| 2545 | 2831 | #ifdef CONFIG_DYNAMIC_FTRACE |
|---|
| 2546 | 2832 | |
|---|
| .. | .. |
|---|
| 2866 | 3152 | #endif /* CONFIG_DYNAMIC_FTRACE */ |
|---|
| 2867 | 3153 | |
|---|
| 2868 | 3154 | /* |
|---|
| 2869 | | - * The top level array has already had its trace_event_file |
|---|
| 2870 | | - * descriptors created in order to allow for early events to |
|---|
| 2871 | | - * be recorded. This function is called after the tracefs has been |
|---|
| 2872 | | - * initialized, and we now have to create the files associated |
|---|
| 2873 | | - * to the events. |
|---|
| 3155 | + * The top level array and trace arrays created by boot-time tracing |
|---|
| 3156 | + * have already had its trace_event_file descriptors created in order |
|---|
| 3157 | + * to allow for early events to be recorded. |
|---|
| 3158 | + * This function is called after the tracefs has been initialized, |
|---|
| 3159 | + * and we now have to create the files associated to the events. |
|---|
| 2874 | 3160 | */ |
|---|
| 2875 | | -static __init void |
|---|
| 2876 | | -__trace_early_add_event_dirs(struct trace_array *tr) |
|---|
| 3161 | +static void __trace_early_add_event_dirs(struct trace_array *tr) |
|---|
| 2877 | 3162 | { |
|---|
| 2878 | 3163 | struct trace_event_file *file; |
|---|
| 2879 | 3164 | int ret; |
|---|
| .. | .. |
|---|
| 2888 | 3173 | } |
|---|
| 2889 | 3174 | |
|---|
| 2890 | 3175 | /* |
|---|
| 2891 | | - * For early boot up, the top trace array requires to have |
|---|
| 2892 | | - * a list of events that can be enabled. This must be done before |
|---|
| 2893 | | - * the filesystem is set up in order to allow events to be traced |
|---|
| 2894 | | - * early. |
|---|
| 3176 | + * For early boot up, the top trace array and the trace arrays created |
|---|
| 3177 | + * by boot-time tracing require to have a list of events that can be |
|---|
| 3178 | + * enabled. This must be done before the filesystem is set up in order |
|---|
| 3179 | + * to allow events to be traced early. |
|---|
| 2895 | 3180 | */ |
|---|
| 2896 | | -static __init void |
|---|
| 2897 | | -__trace_early_add_events(struct trace_array *tr) |
|---|
| 3181 | +void __trace_early_add_events(struct trace_array *tr) |
|---|
| 2898 | 3182 | { |
|---|
| 2899 | 3183 | struct trace_event_call *call; |
|---|
| 2900 | 3184 | int ret; |
|---|
| .. | .. |
|---|
| 2938 | 3222 | { |
|---|
| 2939 | 3223 | strlcpy(bootup_event_buf, str, COMMAND_LINE_SIZE); |
|---|
| 2940 | 3224 | ring_buffer_expanded = true; |
|---|
| 2941 | | - tracing_selftest_disabled = true; |
|---|
| 3225 | + disable_tracing_selftest("running event tracing"); |
|---|
| 2942 | 3226 | |
|---|
| 2943 | 3227 | return 1; |
|---|
| 2944 | 3228 | } |
|---|
| .. | .. |
|---|
| 2977 | 3261 | tr, &ftrace_set_event_pid_fops); |
|---|
| 2978 | 3262 | if (!entry) |
|---|
| 2979 | 3263 | pr_warn("Could not create tracefs 'set_event_pid' entry\n"); |
|---|
| 3264 | + |
|---|
| 3265 | + entry = tracefs_create_file("set_event_notrace_pid", 0644, parent, |
|---|
| 3266 | + tr, &ftrace_set_event_notrace_pid_fops); |
|---|
| 3267 | + if (!entry) |
|---|
| 3268 | + pr_warn("Could not create tracefs 'set_event_notrace_pid' entry\n"); |
|---|
| 2980 | 3269 | |
|---|
| 2981 | 3270 | /* ring buffer internal formats */ |
|---|
| 2982 | 3271 | entry = trace_create_file("header_page", 0444, d_events, |
|---|
| .. | .. |
|---|
| 3020 | 3309 | goto out; |
|---|
| 3021 | 3310 | |
|---|
| 3022 | 3311 | down_write(&trace_event_sem); |
|---|
| 3023 | | - __trace_add_event_dirs(tr); |
|---|
| 3312 | + /* If tr already has the event list, it is initialized in early boot. */ |
|---|
| 3313 | + if (unlikely(!list_empty(&tr->events))) |
|---|
| 3314 | + __trace_early_add_event_dirs(tr); |
|---|
| 3315 | + else |
|---|
| 3316 | + __trace_add_event_dirs(tr); |
|---|
| 3024 | 3317 | up_write(&trace_event_sem); |
|---|
| 3025 | 3318 | |
|---|
| 3026 | 3319 | out: |
|---|
| .. | .. |
|---|
| 3061 | 3354 | clear_event_triggers(tr); |
|---|
| 3062 | 3355 | |
|---|
| 3063 | 3356 | /* Clear the pid list */ |
|---|
| 3064 | | - __ftrace_clear_event_pids(tr); |
|---|
| 3357 | + __ftrace_clear_event_pids(tr, TRACE_PIDS | TRACE_NO_PIDS); |
|---|
| 3065 | 3358 | |
|---|
| 3066 | 3359 | /* Disable any running events */ |
|---|
| 3067 | 3360 | __ftrace_set_clr_event_nolock(tr, NULL, NULL, NULL, 0); |
|---|
| .. | .. |
|---|
| 3071 | 3364 | |
|---|
| 3072 | 3365 | down_write(&trace_event_sem); |
|---|
| 3073 | 3366 | __trace_remove_event_dirs(tr); |
|---|
| 3074 | | - tracefs_remove_recursive(tr->event_dir); |
|---|
| 3367 | + tracefs_remove(tr->event_dir); |
|---|
| 3075 | 3368 | up_write(&trace_event_sem); |
|---|
| 3076 | 3369 | |
|---|
| 3077 | 3370 | tr->event_dir = NULL; |
|---|
| .. | .. |
|---|
| 3176 | 3469 | |
|---|
| 3177 | 3470 | early_initcall(event_trace_enable_again); |
|---|
| 3178 | 3471 | |
|---|
| 3472 | +/* Init fields which doesn't related to the tracefs */ |
|---|
| 3473 | +static __init int event_trace_init_fields(void) |
|---|
| 3474 | +{ |
|---|
| 3475 | + if (trace_define_generic_fields()) |
|---|
| 3476 | + pr_warn("tracing: Failed to allocated generic fields"); |
|---|
| 3477 | + |
|---|
| 3478 | + if (trace_define_common_fields()) |
|---|
| 3479 | + pr_warn("tracing: Failed to allocate common fields"); |
|---|
| 3480 | + |
|---|
| 3481 | + return 0; |
|---|
| 3482 | +} |
|---|
| 3483 | + |
|---|
| 3179 | 3484 | __init int event_trace_init(void) |
|---|
| 3180 | 3485 | { |
|---|
| 3181 | 3486 | struct trace_array *tr; |
|---|
| 3182 | | - struct dentry *d_tracer; |
|---|
| 3183 | 3487 | struct dentry *entry; |
|---|
| 3184 | 3488 | int ret; |
|---|
| 3185 | 3489 | |
|---|
| .. | .. |
|---|
| 3187 | 3491 | if (!tr) |
|---|
| 3188 | 3492 | return -ENODEV; |
|---|
| 3189 | 3493 | |
|---|
| 3190 | | - d_tracer = tracing_init_dentry(); |
|---|
| 3191 | | - if (IS_ERR(d_tracer)) |
|---|
| 3192 | | - return 0; |
|---|
| 3193 | | - |
|---|
| 3194 | | - entry = tracefs_create_file("available_events", 0444, d_tracer, |
|---|
| 3494 | + entry = tracefs_create_file("available_events", 0444, NULL, |
|---|
| 3195 | 3495 | tr, &ftrace_avail_fops); |
|---|
| 3196 | 3496 | if (!entry) |
|---|
| 3197 | 3497 | pr_warn("Could not create tracefs 'available_events' entry\n"); |
|---|
| 3198 | 3498 | |
|---|
| 3199 | | - if (trace_define_generic_fields()) |
|---|
| 3200 | | - pr_warn("tracing: Failed to allocated generic fields"); |
|---|
| 3201 | | - |
|---|
| 3202 | | - if (trace_define_common_fields()) |
|---|
| 3203 | | - pr_warn("tracing: Failed to allocate common fields"); |
|---|
| 3204 | | - |
|---|
| 3205 | | - ret = early_event_add_tracer(d_tracer, tr); |
|---|
| 3499 | + ret = early_event_add_tracer(NULL, tr); |
|---|
| 3206 | 3500 | if (ret) |
|---|
| 3207 | 3501 | return ret; |
|---|
| 3208 | 3502 | |
|---|
| .. | .. |
|---|
| 3211 | 3505 | if (ret) |
|---|
| 3212 | 3506 | pr_warn("Failed to register trace events module notifier\n"); |
|---|
| 3213 | 3507 | #endif |
|---|
| 3508 | + |
|---|
| 3509 | + eventdir_initialized = true; |
|---|
| 3510 | + |
|---|
| 3214 | 3511 | return 0; |
|---|
| 3215 | 3512 | } |
|---|
| 3216 | 3513 | |
|---|
| .. | .. |
|---|
| 3219 | 3516 | event_trace_memsetup(); |
|---|
| 3220 | 3517 | init_ftrace_syscalls(); |
|---|
| 3221 | 3518 | event_trace_enable(); |
|---|
| 3519 | + event_trace_init_fields(); |
|---|
| 3222 | 3520 | } |
|---|
| 3223 | 3521 | |
|---|
| 3224 | | -#ifdef CONFIG_FTRACE_STARTUP_TEST |
|---|
| 3522 | +#ifdef CONFIG_EVENT_TRACE_STARTUP_TEST |
|---|
| 3225 | 3523 | |
|---|
| 3226 | 3524 | static DEFINE_SPINLOCK(test_spinlock); |
|---|
| 3227 | 3525 | static DEFINE_SPINLOCK(test_spinlock_irq); |
|---|
| .. | .. |
|---|
| 3398 | 3696 | function_test_events_call(unsigned long ip, unsigned long parent_ip, |
|---|
| 3399 | 3697 | struct ftrace_ops *op, struct pt_regs *pt_regs) |
|---|
| 3400 | 3698 | { |
|---|
| 3699 | + struct trace_buffer *buffer; |
|---|
| 3401 | 3700 | struct ring_buffer_event *event; |
|---|
| 3402 | | - struct ring_buffer *buffer; |
|---|
| 3403 | 3701 | struct ftrace_entry *entry; |
|---|
| 3404 | 3702 | unsigned long flags; |
|---|
| 3405 | 3703 | long disabled; |
|---|