aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorNamhyung Kim <namhyung@kernel.org>2014-01-17 03:08:37 -0500
committerSteven Rostedt <rostedt@goodmis.org>2014-02-20 12:30:09 -0500
commitdd9fa555d7bbfcc7dbc63eb744806e9f6cb62e9f (patch)
treead217cf792aef4dad4b951bce456d6b0c0e5c082 /kernel/trace
parenta43b97043048eac1686f409af7ad3bb8071b9d83 (diff)
tracing/uprobes: Move argument fetching to uprobe_dispatcher()
A single uprobe event might serve different users like ftrace and perf. And this is especially important for upcoming multi buffer support. But in this case it'll fetch (same) data from userspace multiple times. So move it to the beginning of the dispatcher function and reuse it for each users. Link: http://lkml.kernel.org/r/1389946120-19610-3-git-send-email-namhyung@kernel.org Reviewed-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Cc: 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')
-rw-r--r--kernel/trace/trace_uprobe.c93
1 files changed, 56 insertions, 37 deletions
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index c5d2612bf233..d83155e0da78 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -759,30 +759,25 @@ static void uprobe_buffer_put(struct uprobe_cpu_buffer *ucb)
759} 759}
760 760
761static void __uprobe_trace_func(struct trace_uprobe *tu, 761static void __uprobe_trace_func(struct trace_uprobe *tu,
762 unsigned long func, struct pt_regs *regs) 762 unsigned long func, struct pt_regs *regs,
763 struct uprobe_cpu_buffer *ucb, int dsize)
763{ 764{
764 struct uprobe_trace_entry_head *entry; 765 struct uprobe_trace_entry_head *entry;
765 struct ring_buffer_event *event; 766 struct ring_buffer_event *event;
766 struct ring_buffer *buffer; 767 struct ring_buffer *buffer;
767 struct uprobe_cpu_buffer *ucb;
768 void *data; 768 void *data;
769 int size, dsize, esize; 769 int size, esize;
770 struct ftrace_event_call *call = &tu->tp.call; 770 struct ftrace_event_call *call = &tu->tp.call;
771 771
772 dsize = __get_data_size(&tu->tp, regs); 772 if (WARN_ON_ONCE(tu->tp.size + dsize > PAGE_SIZE))
773 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
774
775 if (WARN_ON_ONCE(!uprobe_cpu_buffer || tu->tp.size + dsize > PAGE_SIZE))
776 return; 773 return;
777 774
778 ucb = uprobe_buffer_get(); 775 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
779 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
780
781 size = esize + tu->tp.size + dsize; 776 size = esize + tu->tp.size + dsize;
782 event = trace_current_buffer_lock_reserve(&buffer, call->event.type, 777 event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
783 size, 0, 0); 778 size, 0, 0);
784 if (!event) 779 if (!event)
785 goto out; 780 return;
786 781
787 entry = ring_buffer_event_data(event); 782 entry = ring_buffer_event_data(event);
788 if (is_ret_probe(tu)) { 783 if (is_ret_probe(tu)) {
@@ -798,23 +793,22 @@ static void __uprobe_trace_func(struct trace_uprobe *tu,
798 793
799 if (!call_filter_check_discard(call, entry, buffer, event)) 794 if (!call_filter_check_discard(call, entry, buffer, event))
800 trace_buffer_unlock_commit(buffer, event, 0, 0); 795 trace_buffer_unlock_commit(buffer, event, 0, 0);
801
802out:
803 uprobe_buffer_put(ucb);
804} 796}
805 797
806/* uprobe handler */ 798/* uprobe handler */
807static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs) 799static int uprobe_trace_func(struct trace_uprobe *tu, struct pt_regs *regs,
800 struct uprobe_cpu_buffer *ucb, int dsize)
808{ 801{
809 if (!is_ret_probe(tu)) 802 if (!is_ret_probe(tu))
810 __uprobe_trace_func(tu, 0, regs); 803 __uprobe_trace_func(tu, 0, regs, ucb, dsize);
811 return 0; 804 return 0;
812} 805}
813 806
814static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func, 807static void uretprobe_trace_func(struct trace_uprobe *tu, unsigned long func,
815 struct pt_regs *regs) 808 struct pt_regs *regs,
809 struct uprobe_cpu_buffer *ucb, int dsize)
816{ 810{
817 __uprobe_trace_func(tu, func, regs); 811 __uprobe_trace_func(tu, func, regs, ucb, dsize);
818} 812}
819 813
820/* Event entry printers */ 814/* Event entry printers */
@@ -1015,30 +1009,23 @@ static bool uprobe_perf_filter(struct uprobe_consumer *uc,
1015} 1009}
1016 1010
1017static void __uprobe_perf_func(struct trace_uprobe *tu, 1011static void __uprobe_perf_func(struct trace_uprobe *tu,
1018 unsigned long func, struct pt_regs *regs) 1012 unsigned long func, struct pt_regs *regs,
1013 struct uprobe_cpu_buffer *ucb, int dsize)
1019{ 1014{
1020 struct ftrace_event_call *call = &tu->tp.call; 1015 struct ftrace_event_call *call = &tu->tp.call;
1021 struct uprobe_trace_entry_head *entry; 1016 struct uprobe_trace_entry_head *entry;
1022 struct hlist_head *head; 1017 struct hlist_head *head;
1023 struct uprobe_cpu_buffer *ucb;
1024 void *data; 1018 void *data;
1025 int size, dsize, esize; 1019 int size, esize;
1026 int rctx; 1020 int rctx;
1027 1021
1028 dsize = __get_data_size(&tu->tp, regs);
1029 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu)); 1022 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1030 1023
1031 if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1032 return;
1033
1034 size = esize + tu->tp.size + dsize; 1024 size = esize + tu->tp.size + dsize;
1035 size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32); 1025 size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
1036 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough")) 1026 if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
1037 return; 1027 return;
1038 1028
1039 ucb = uprobe_buffer_get();
1040 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
1041
1042 preempt_disable(); 1029 preempt_disable();
1043 head = this_cpu_ptr(call->perf_events); 1030 head = this_cpu_ptr(call->perf_events);
1044 if (hlist_empty(head)) 1031 if (hlist_empty(head))
@@ -1068,24 +1055,25 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
1068 perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL); 1055 perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL);
1069 out: 1056 out:
1070 preempt_enable(); 1057 preempt_enable();
1071 uprobe_buffer_put(ucb);
1072} 1058}
1073 1059
1074/* uprobe profile handler */ 1060/* uprobe profile handler */
1075static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs) 1061static int uprobe_perf_func(struct trace_uprobe *tu, struct pt_regs *regs,
1062 struct uprobe_cpu_buffer *ucb, int dsize)
1076{ 1063{
1077 if (!uprobe_perf_filter(&tu->consumer, 0, current->mm)) 1064 if (!uprobe_perf_filter(&tu->consumer, 0, current->mm))
1078 return UPROBE_HANDLER_REMOVE; 1065 return UPROBE_HANDLER_REMOVE;
1079 1066
1080 if (!is_ret_probe(tu)) 1067 if (!is_ret_probe(tu))
1081 __uprobe_perf_func(tu, 0, regs); 1068 __uprobe_perf_func(tu, 0, regs, ucb, dsize);
1082 return 0; 1069 return 0;
1083} 1070}
1084 1071
1085static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func, 1072static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
1086 struct pt_regs *regs) 1073 struct pt_regs *regs,
1074 struct uprobe_cpu_buffer *ucb, int dsize)
1087{ 1075{
1088 __uprobe_perf_func(tu, func, regs); 1076 __uprobe_perf_func(tu, func, regs, ucb, dsize);
1089} 1077}
1090#endif /* CONFIG_PERF_EVENTS */ 1078#endif /* CONFIG_PERF_EVENTS */
1091 1079
@@ -1127,8 +1115,11 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
1127{ 1115{
1128 struct trace_uprobe *tu; 1116 struct trace_uprobe *tu;
1129 struct uprobe_dispatch_data udd; 1117 struct uprobe_dispatch_data udd;
1118 struct uprobe_cpu_buffer *ucb;
1119 int dsize, esize;
1130 int ret = 0; 1120 int ret = 0;
1131 1121
1122
1132 tu = container_of(con, struct trace_uprobe, consumer); 1123 tu = container_of(con, struct trace_uprobe, consumer);
1133 tu->nhit++; 1124 tu->nhit++;
1134 1125
@@ -1137,13 +1128,29 @@ static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs)
1137 1128
1138 current->utask->vaddr = (unsigned long) &udd; 1129 current->utask->vaddr = (unsigned long) &udd;
1139 1130
1131#ifdef CONFIG_PERF_EVENTS
1132 if ((tu->tp.flags & TP_FLAG_TRACE) == 0 &&
1133 !uprobe_perf_filter(&tu->consumer, 0, current->mm))
1134 return UPROBE_HANDLER_REMOVE;
1135#endif
1136
1137 if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1138 return 0;
1139
1140 dsize = __get_data_size(&tu->tp, regs);
1141 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1142
1143 ucb = uprobe_buffer_get();
1144 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
1145
1140 if (tu->tp.flags & TP_FLAG_TRACE) 1146 if (tu->tp.flags & TP_FLAG_TRACE)
1141 ret |= uprobe_trace_func(tu, regs); 1147 ret |= uprobe_trace_func(tu, regs, ucb, dsize);
1142 1148
1143#ifdef CONFIG_PERF_EVENTS 1149#ifdef CONFIG_PERF_EVENTS
1144 if (tu->tp.flags & TP_FLAG_PROFILE) 1150 if (tu->tp.flags & TP_FLAG_PROFILE)
1145 ret |= uprobe_perf_func(tu, regs); 1151 ret |= uprobe_perf_func(tu, regs, ucb, dsize);
1146#endif 1152#endif
1153 uprobe_buffer_put(ucb);
1147 return ret; 1154 return ret;
1148} 1155}
1149 1156
@@ -1152,6 +1159,8 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
1152{ 1159{
1153 struct trace_uprobe *tu; 1160 struct trace_uprobe *tu;
1154 struct uprobe_dispatch_data udd; 1161 struct uprobe_dispatch_data udd;
1162 struct uprobe_cpu_buffer *ucb;
1163 int dsize, esize;
1155 1164
1156 tu = container_of(con, struct trace_uprobe, consumer); 1165 tu = container_of(con, struct trace_uprobe, consumer);
1157 1166
@@ -1160,13 +1169,23 @@ static int uretprobe_dispatcher(struct uprobe_consumer *con,
1160 1169
1161 current->utask->vaddr = (unsigned long) &udd; 1170 current->utask->vaddr = (unsigned long) &udd;
1162 1171
1172 if (WARN_ON_ONCE(!uprobe_cpu_buffer))
1173 return 0;
1174
1175 dsize = __get_data_size(&tu->tp, regs);
1176 esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
1177
1178 ucb = uprobe_buffer_get();
1179 store_trace_args(esize, &tu->tp, regs, ucb->buf, dsize);
1180
1163 if (tu->tp.flags & TP_FLAG_TRACE) 1181 if (tu->tp.flags & TP_FLAG_TRACE)
1164 uretprobe_trace_func(tu, func, regs); 1182 uretprobe_trace_func(tu, func, regs, ucb, dsize);
1165 1183
1166#ifdef CONFIG_PERF_EVENTS 1184#ifdef CONFIG_PERF_EVENTS
1167 if (tu->tp.flags & TP_FLAG_PROFILE) 1185 if (tu->tp.flags & TP_FLAG_PROFILE)
1168 uretprobe_perf_func(tu, func, regs); 1186 uretprobe_perf_func(tu, func, regs, ucb, dsize);
1169#endif 1187#endif
1188 uprobe_buffer_put(ucb);
1170 return 0; 1189 return 0;
1171} 1190}
1172 1191