aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_uprobe.c
diff options
context:
space:
mode:
authorzhangwei(Jovi) <jovi.zhangwei@huawei.com>2014-01-17 03:08:38 -0500
committerSteven Rostedt <rostedt@goodmis.org>2014-02-20 12:30:09 -0500
commit70ed91c6ec7f8bf20369634017d887d48ac979d2 (patch)
treec8b69373ee58aa2294016ddfb773a3490f5dca6d /kernel/trace/trace_uprobe.c
parentdd9fa555d7bbfcc7dbc63eb744806e9f6cb62e9f (diff)
tracing/uprobes: Support ftrace_event_file base multibuffer
Support multi-buffer on uprobe-based dynamic events by using ftrace_event_file. This patch is based kprobe-based dynamic events multibuffer support work initially, commited by Masami(commit 41a7dd420c), but revised as below: Oleg changed the kprobe-based multibuffer design from array-pointers of ftrace_event_file into simple list, so this patch also change to the list design. rcu_read_lock/unlock added into uprobe_trace_func/uretprobe_trace_func, to synchronize with ftrace_event_file list add and delete. Even though we allow multi-uprobes instances now, but TP_FLAG_PROFILE/TP_FLAG_TRACE are still mutually exclusive in probe_event_enable currently, this means we cannot allow one user is using uprobe-tracer, and another user is using perf-probe on same uprobe concurrently. (Perhaps this will be fix in future, kprobe don't have this limitation now) Link: http://lkml.kernel.org/r/1389946120-19610-4-git-send-email-namhyung@kernel.org Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Reviewed-by: Oleg Nesterov <oleg@redhat.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: zhangwei(Jovi) <jovi.zhangwei@huawei.com> Signed-off-by: Namhyung Kim <namhyung@kernel.org> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel/trace/trace_uprobe.c')
-rw-r--r--kernel/trace/trace_uprobe.c105
1 files changed, 84 insertions, 21 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index d83155e0da78..349c6df9e332 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -260,6 +260,7 @@ alloc_trace_uprobe(const char *group, const char *event, int nargs, bool is_ret)
260 goto error; 260 goto error;
261 261
262 INIT_LIST_HEAD(&tu->list); 262 INIT_LIST_HEAD(&tu->list);
263 INIT_LIST_HEAD(&tu->tp.files);
263 tu->consumer.handler = uprobe_dispatcher; 264 tu->consumer.handler = uprobe_dispatcher;
264 if (is_ret) 265 if (is_ret)
265 tu->consumer.ret_handler = uretprobe_dispatcher; 266 tu->consumer.ret_handler = uretprobe_dispatcher;
@@ -760,7 +761,8 @@ static void uprobe_buffer_put(struct uprobe_cpu_buffer *ucb)
760 761
761static void __uprobe_trace_func(struct trace_uprobe *tu, 762static void __uprobe_trace_func(struct trace_uprobe *tu,
762 unsigned long func, struct pt_regs *regs, 763 unsigned long func, struct pt_regs *regs,
763 struct uprobe_cpu_buffer *ucb, int dsize) 764 struct uprobe_cpu_buffer *ucb, int dsize,
765 struct ftrace_event_file *ftrace_file)
764{ 766{
765 struct uprobe_trace_entry_head *entry; 767 struct uprobe_trace_entry_head *entry;
766 struct ring_buffer_event *event; 768 struct ring_buffer_event *event;
@@ -769,13 +771,15 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
769 int size, esize; 771 int size, esize;
770 struct ftrace_event_call *call = &tu->tp.call; 772 struct ftrace_event_call *call = &tu->tp.call;
771 773
774 WARN_ON(call != ftrace_file->event_call);
775
772 if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE)) 776 if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE))
773 return; 777 return;
774 778
775 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu)); 779 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
776 size = esize + tu->tp.size + dsize; 780 size = esize + tu->tp.size + dsize;
777 event = trace_current_buffer_lock_reserve(&buffer, call->event.type, 781 event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
778 size, 0, 0); 782 call->event.type, size, 0, 0);
779 if (!event) 783 if (!event)
780 return; 784 return;
781 785
@@ -799,8 +803,16 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
799static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs, 803static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
800 struct uprobe_cpu_buffer *ucb, int dsize) 804 struct uprobe_cpu_buffer *ucb, int dsize)
801{ 805{
802 if (!is_ret_probe(tu)) 806 struct event_file_link *link;
803 __uprobe_trace_func(tu, 0, regs, ucb, dsize); 807
808 if (is_ret_probe(tu))
809 return 0;
810
811 rcu_read_lock();
812 list_for_each_entry_rcu(link, &tu->tp.files, list)
813 __uprobe_trace_func(tu, 0, regs, ucb, dsize, link->file);
814 rcu_read_unlock();
815
804 return 0; 816 return 0;
805} 817}
806 818
@@ -808,7 +820,12 @@ static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
808 struct pt_regs *regs, 820 struct pt_regs *regs,
809 struct uprobe_cpu_buffer *ucb, int dsize) 821 struct uprobe_cpu_buffer *ucb, int dsize)
810{ 822{
811 __uprobe_trace_func(tu, func, regs, ucb, dsize); 823 struct event_file_link *link;
824
825 rcu_read_lock();
826 list_for_each_entry_rcu(link, &tu->tp.files, list)
827 __uprobe_trace_func(tu, func, regs, ucb, dsize, link->file);
828 rcu_read_unlock();
812} 829}
813 830
814/* Event entry printers */ 831/* Event entry printers */
@@ -855,12 +872,31 @@ typedef bool (*filter_func_t)(struct uprobe_consumer *self,
855 struct mm_struct *mm); 872 struct mm_struct *mm);
856 873
857static int 874static int
858probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter) 875probe_event_enable(struct trace_uprobe *tu, struct ftrace_event_file *file,
876 filter_func_t filter)
859{ 877{
860 int ret = 0; 878 bool enabled = trace_probe_is_enabled(&tu->tp);
879 struct event_file_link *link = NULL;
880 int ret;
881
882 if (file) {
883 if (tu->tp.flags & TP_FLAG_PROFILE)
884 return -EINTR;
861 885
862 if (trace_probe_is_enabled(&tu->tp)) 886 link = kmalloc(sizeof(*link), GFP_KERNEL);
863 return -EINTR; 887 if (!link)
888 return -ENOMEM;
889
890 link->file = file;
891 list_add_tail_rcu(&link->list, &tu->tp.files);
892
893 tu->tp.flags |= TP_FLAG_TRACE;
894 } else {
895 if (tu->tp.flags & TP_FLAG_TRACE)
896 return -EINTR;
897
898 tu->tp.flags |= TP_FLAG_PROFILE;
899 }
864 900
865 ret = uprobe_buffer_enable(); 901 ret = uprobe_buffer_enable();
866 if (ret < 0) 902 if (ret < 0)
@@ -868,24 +904,49 @@ probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter)
868 904
869 WARN_ON(!uprobe_filter_is_empty(&tu->filter)); 905 WARN_ON(!uprobe_filter_is_empty(&tu->filter));
870 906
871 tu->tp.flags |= flag; 907 if (enabled)
908 return 0;
909
872 tu->consumer.filter = filter; 910 tu->consumer.filter = filter;
873 ret = uprobe_register(tu->inode, tu->offset, &tu->consumer); 911 ret = uprobe_register(tu->inode, tu->offset, &tu->consumer);
874 if (ret) 912 if (ret) {
875 tu->tp.flags &= ~flag; 913 if (file) {
914 list_del(&link->list);
915 kfree(link);
916 tu->tp.flags &= ~TP_FLAG_TRACE;
917 } else
918 tu->tp.flags &= ~TP_FLAG_PROFILE;
919 }
876 920
877 return ret; 921 return ret;
878} 922}
879 923
880static void probe_event_disable(struct trace_uprobe *tu, int flag) 924static void
925probe_event_disable(struct trace_uprobe *tu, struct ftrace_event_file *file)
881{ 926{
882 if (!trace_probe_is_enabled(&tu->tp)) 927 if (!trace_probe_is_enabled(&tu->tp))
883 return; 928 return;
884 929
930 if (file) {
931 struct event_file_link *link;
932
933 link = find_event_file_link(&tu->tp, file);
934 if (!link)
935 return;
936
937 list_del_rcu(&link->list);
938 /* synchronize with u{,ret}probe_trace_func */
939 synchronize_sched();
940 kfree(link);
941
942 if (!list_empty(&tu->tp.files))
943 return;
944 }
945
885 WARN_ON(!uprobe_filter_is_empty(&tu->filter)); 946 WARN_ON(!uprobe_filter_is_empty(&tu->filter));
886 947
887 uprobe_unregister(tu->inode, tu->offset, &tu->consumer); 948 uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
888 tu->tp.flags &= ~flag; 949 tu->tp.flags &= file ? ~TP_FLAG_TRACE : ~TP_FLAG_PROFILE;
889 950
890 uprobe_buffer_disable(); 951 uprobe_buffer_disable();
891} 952}
@@ -1077,25 +1138,27 @@ static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
1077} 1138}
1078#endif /* CONFIG_PERF_EVENTS */ 1139#endif /* CONFIG_PERF_EVENTS */
1079 1140
1080static 1141static int
1081int trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type, void *data) 1142trace_uprobe_register(struct ftrace_event_call *event, enum trace_reg type,
1143 void *data)
1082{ 1144{
1083 struct trace_uprobe *tu = event->data; 1145 struct trace_uprobe *tu = event->data;
1146 struct ftrace_event_file *file = data;
1084 1147
1085 switch (type) { 1148 switch (type) {
1086 case TRACE_REG_REGISTER: 1149 case TRACE_REG_REGISTER:
1087 return probe_event_enable(tu, TP_FLAG_TRACE, NULL); 1150 return probe_event_enable(tu, file, NULL);
1088 1151
1089 case TRACE_REG_UNREGISTER: 1152 case TRACE_REG_UNREGISTER:
1090 probe_event_disable(tu, TP_FLAG_TRACE); 1153 probe_event_disable(tu, file);
1091 return 0; 1154 return 0;
1092 1155
1093#ifdef CONFIG_PERF_EVENTS 1156#ifdef CONFIG_PERF_EVENTS
1094 case TRACE_REG_PERF_REGISTER: 1157 case TRACE_REG_PERF_REGISTER:
1095 return probe_event_enable(tu, TP_FLAG_PROFILE, uprobe_perf_filter); 1158 return probe_event_enable(tu, NULL, uprobe_perf_filter);
1096 1159
1097 case TRACE_REG_PERF_UNREGISTER: 1160 case TRACE_REG_PERF_UNREGISTER:
1098 probe_event_disable(tu, TP_FLAG_PROFILE); 1161 probe_event_disable(tu, NULL);
1099 return 0; 1162 return 0;
1100 1163
1101 case TRACE_REG_PERF_OPEN: 1164 case TRACE_REG_PERF_OPEN: