aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorMasami Hiramatsu <masami.hiramatsu.pt@hitachi.com>2013-05-09 01:44:49 -0400
committerSteven Rostedt <rostedt@goodmis.org>2013-05-09 20:21:47 -0400
commit41a7dd420c57323391d58b553318c1fad8e7ebc2 (patch)
tree5e1d64afa7395335381203d64f2ce91b09bd0f9b /kernel
parent2b106aabe6c566ba19c352f22683381e1ea41326 (diff)
tracing/kprobes: Support ftrace_event_file base multibuffer
Support multi-buffer on kprobe-based dynamic events by using ftrace_event_file. Link: http://lkml.kernel.org/r/20130509054449.30398.88343.stgit@mhiramat-M0-7522 Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Tom Zanussi <tom.zanussi@intel.com> Cc: Oleg Nesterov <oleg@redhat.com> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com> Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Signed-off-by: Steven Rostedt <rostedt@goodmis.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/trace/trace_kprobe.c250
1 files changed, 214 insertions, 36 deletions
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 9ca44fc3fb0b..fee865d8a7c4 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -27,7 +27,6 @@
27/** 27/**
28 * Kprobe event core functions 28 * Kprobe event core functions
29 */ 29 */
30
31struct trace_probe { 30struct trace_probe {
32 struct list_head list; 31 struct list_head list;
33 struct kretprobe rp; /* Use rp.kp for kprobe use */ 32 struct kretprobe rp; /* Use rp.kp for kprobe use */
@@ -36,6 +35,7 @@ struct trace_probe {
36 const char *symbol; /* symbol name */ 35 const char *symbol; /* symbol name */
37 struct ftrace_event_class class; 36 struct ftrace_event_class class;
38 struct ftrace_event_call call; 37 struct ftrace_event_call call;
38 struct ftrace_event_file **files;
39 ssize_t size; /* trace entry size */ 39 ssize_t size; /* trace entry size */
40 unsigned int nr_args; 40 unsigned int nr_args;
41 struct probe_arg args[]; 41 struct probe_arg args[];
@@ -183,12 +183,57 @@ static struct trace_probe *find_trace_probe(const char *event,
183 return NULL; 183 return NULL;
184} 184}
185 185
186/* Enable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ 186static int trace_probe_nr_files(struct trace_probe *tp)
187static int enable_trace_probe(struct trace_probe *tp, int flag) 187{
188 struct ftrace_event_file **file = tp->files;
189 int ret = 0;
190
191 if (file)
192 while (*(file++))
193 ret++;
194
195 return ret;
196}
197
198static DEFINE_MUTEX(probe_enable_lock);
199
200/*
201 * Enable trace_probe
202 * if the file is NULL, enable "perf" handler, or enable "trace" handler.
203 */
204static int
205enable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
188{ 206{
189 int ret = 0; 207 int ret = 0;
190 208
191 tp->flags |= flag; 209 mutex_lock(&probe_enable_lock);
210
211 if (file) {
212 struct ftrace_event_file **new, **old = tp->files;
213 int n = trace_probe_nr_files(tp);
214
215 /* 1 is for new one and 1 is for stopper */
216 new = kzalloc((n + 2) * sizeof(struct ftrace_event_file *),
217 GFP_KERNEL);
218 if (!new) {
219 ret = -ENOMEM;
220 goto out_unlock;
221 }
222 memcpy(new, old, n * sizeof(struct ftrace_event_file *));
223 new[n] = file;
224 /* The last one keeps a NULL */
225
226 rcu_assign_pointer(tp->files, new);
227 tp->flags |= TP_FLAG_TRACE;
228
229 if (old) {
230 /* Make sure the probe is done with old files */
231 synchronize_sched();
232 kfree(old);
233 }
234 } else
235 tp->flags |= TP_FLAG_PROFILE;
236
192 if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) && 237 if (trace_probe_is_enabled(tp) && trace_probe_is_registered(tp) &&
193 !trace_probe_has_gone(tp)) { 238 !trace_probe_has_gone(tp)) {
194 if (trace_probe_is_return(tp)) 239 if (trace_probe_is_return(tp))
@@ -197,19 +242,83 @@ static int enable_trace_probe(struct trace_probe *tp, int flag)
197 ret = enable_kprobe(&tp->rp.kp); 242 ret = enable_kprobe(&tp->rp.kp);
198 } 243 }
199 244
245 out_unlock:
246 mutex_unlock(&probe_enable_lock);
247
200 return ret; 248 return ret;
201} 249}
202 250
203/* Disable trace_probe - @flag must be TP_FLAG_TRACE or TP_FLAG_PROFILE */ 251static int
204static void disable_trace_probe(struct trace_probe *tp, int flag) 252trace_probe_file_index(struct trace_probe *tp, struct ftrace_event_file *file)
253{
254 int i;
255
256 if (tp->files) {
257 for (i = 0; tp->files[i]; i++)
258 if (tp->files[i] == file)
259 return i;
260 }
261
262 return -1;
263}
264
265/*
266 * Disable trace_probe
267 * if the file is NULL, disable "perf" handler, or disable "trace" handler.
268 */
269static int
270disable_trace_probe(struct trace_probe *tp, struct ftrace_event_file *file)
205{ 271{
206 tp->flags &= ~flag; 272 int ret = 0;
273
274 mutex_lock(&probe_enable_lock);
275
276 if (file) {
277 struct ftrace_event_file **new, **old = tp->files;
278 int n = trace_probe_nr_files(tp);
279 int i, j;
280
281 if (n == 0 || trace_probe_file_index(tp, file) < 0) {
282 ret = -EINVAL;
283 goto out_unlock;
284 }
285
286 if (n == 1) { /* Remove the last file */
287 tp->flags &= ~TP_FLAG_TRACE;
288 new = NULL;
289 } else {
290 new = kzalloc(n * sizeof(struct ftrace_event_file *),
291 GFP_KERNEL);
292 if (!new) {
293 ret = -ENOMEM;
294 goto out_unlock;
295 }
296
297 /* This copy & check loop copies the NULL stopper too */
298 for (i = 0, j = 0; j < n && i < n + 1; i++)
299 if (old[i] != file)
300 new[j++] = old[i];
301 }
302
303 rcu_assign_pointer(tp->files, new);
304
305 /* Make sure the probe is done with old files */
306 synchronize_sched();
307 kfree(old);
308 } else
309 tp->flags &= ~TP_FLAG_PROFILE;
310
207 if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) { 311 if (!trace_probe_is_enabled(tp) && trace_probe_is_registered(tp)) {
208 if (trace_probe_is_return(tp)) 312 if (trace_probe_is_return(tp))
209 disable_kretprobe(&tp->rp); 313 disable_kretprobe(&tp->rp);
210 else 314 else
211 disable_kprobe(&tp->rp.kp); 315 disable_kprobe(&tp->rp.kp);
212 } 316 }
317
318 out_unlock:
319 mutex_unlock(&probe_enable_lock);
320
321 return ret;
213} 322}
214 323
215/* Internal register function - just handle k*probes and flags */ 324/* Internal register function - just handle k*probes and flags */
@@ -724,7 +833,8 @@ static __kprobes void store_trace_args(int ent_size, struct trace_probe *tp,
724 833
725/* Kprobe handler */ 834/* Kprobe handler */
726static __kprobes void 835static __kprobes void
727kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs) 836__kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs,
837 struct ftrace_event_file *ftrace_file)
728{ 838{
729 struct kprobe_trace_entry_head *entry; 839 struct kprobe_trace_entry_head *entry;
730 struct ring_buffer_event *event; 840 struct ring_buffer_event *event;
@@ -733,14 +843,17 @@ kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs)
733 unsigned long irq_flags; 843 unsigned long irq_flags;
734 struct ftrace_event_call *call = &tp->call; 844 struct ftrace_event_call *call = &tp->call;
735 845
846 WARN_ON(call != ftrace_file->event_call);
847
736 local_save_flags(irq_flags); 848 local_save_flags(irq_flags);
737 pc = preempt_count(); 849 pc = preempt_count();
738 850
739 dsize = __get_data_size(tp, regs); 851 dsize = __get_data_size(tp, regs);
740 size = sizeof(*entry) + tp->size + dsize; 852 size = sizeof(*entry) + tp->size + dsize;
741 853
742 event = trace_current_buffer_lock_reserve(&buffer, call->event.type, 854 event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
743 size, irq_flags, pc); 855 call->event.type,
856 size, irq_flags, pc);
744 if (!event) 857 if (!event)
745 return; 858 return;
746 859
@@ -753,10 +866,23 @@ kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs)
753 irq_flags, pc, regs); 866 irq_flags, pc, regs);
754} 867}
755 868
869static __kprobes void
870kprobe_trace_func(struct trace_probe *tp, struct pt_regs *regs)
871{
872 struct ftrace_event_file **file = tp->files;
873
874 /* Note: preempt is already disabled around the kprobe handler */
875 while (*file) {
876 __kprobe_trace_func(tp, regs, *file);
877 file++;
878 }
879}
880
756/* Kretprobe handler */ 881/* Kretprobe handler */
757static __kprobes void 882static __kprobes void
758kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri, 883__kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
759 struct pt_regs *regs) 884 struct pt_regs *regs,
885 struct ftrace_event_file *ftrace_file)
760{ 886{
761 struct kretprobe_trace_entry_head *entry; 887 struct kretprobe_trace_entry_head *entry;
762 struct ring_buffer_event *event; 888 struct ring_buffer_event *event;
@@ -765,14 +891,17 @@ kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
765 unsigned long irq_flags; 891 unsigned long irq_flags;
766 struct ftrace_event_call *call = &tp->call; 892 struct ftrace_event_call *call = &tp->call;
767 893
894 WARN_ON(call != ftrace_file->event_call);
895
768 local_save_flags(irq_flags); 896 local_save_flags(irq_flags);
769 pc = preempt_count(); 897 pc = preempt_count();
770 898
771 dsize = __get_data_size(tp, regs); 899 dsize = __get_data_size(tp, regs);
772 size = sizeof(*entry) + tp->size + dsize; 900 size = sizeof(*entry) + tp->size + dsize;
773 901
774 event = trace_current_buffer_lock_reserve(&buffer, call->event.type, 902 event = trace_event_buffer_lock_reserve(&buffer, ftrace_file,
775 size, irq_flags, pc); 903 call->event.type,
904 size, irq_flags, pc);
776 if (!event) 905 if (!event)
777 return; 906 return;
778 907
@@ -786,6 +915,19 @@ kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
786 irq_flags, pc, regs); 915 irq_flags, pc, regs);
787} 916}
788 917
918static __kprobes void
919kretprobe_trace_func(struct trace_probe *tp, struct kretprobe_instance *ri,
920 struct pt_regs *regs)
921{
922 struct ftrace_event_file **file = tp->files;
923
924 /* Note: preempt is already disabled around the kprobe handler */
925 while (*file) {
926 __kretprobe_trace_func(tp, ri, regs, *file);
927 file++;
928 }
929}
930
789/* Event entry printers */ 931/* Event entry printers */
790enum print_line_t 932enum print_line_t
791print_kprobe_event(struct trace_iterator *iter, int flags, 933print_kprobe_event(struct trace_iterator *iter, int flags,
@@ -1041,20 +1183,19 @@ int kprobe_register(struct ftrace_event_call *event,
1041 enum trace_reg type, void *data) 1183 enum trace_reg type, void *data)
1042{ 1184{
1043 struct trace_probe *tp = (struct trace_probe *)event->data; 1185 struct trace_probe *tp = (struct trace_probe *)event->data;
1186 struct ftrace_event_file *file = data;
1044 1187
1045 switch (type) { 1188 switch (type) {
1046 case TRACE_REG_REGISTER: 1189 case TRACE_REG_REGISTER:
1047 return enable_trace_probe(tp, TP_FLAG_TRACE); 1190 return enable_trace_probe(tp, file);
1048 case TRACE_REG_UNREGISTER: 1191 case TRACE_REG_UNREGISTER:
1049 disable_trace_probe(tp, TP_FLAG_TRACE); 1192 return disable_trace_probe(tp, file);
1050 return 0;
1051 1193
1052#ifdef CONFIG_PERF_EVENTS 1194#ifdef CONFIG_PERF_EVENTS
1053 case TRACE_REG_PERF_REGISTER: 1195 case TRACE_REG_PERF_REGISTER:
1054 return enable_trace_probe(tp, TP_FLAG_PROFILE); 1196 return enable_trace_probe(tp, NULL);
1055 case TRACE_REG_PERF_UNREGISTER: 1197 case TRACE_REG_PERF_UNREGISTER:
1056 disable_trace_probe(tp, TP_FLAG_PROFILE); 1198 return disable_trace_probe(tp, NULL);
1057 return 0;
1058 case TRACE_REG_PERF_OPEN: 1199 case TRACE_REG_PERF_OPEN:
1059 case TRACE_REG_PERF_CLOSE: 1200 case TRACE_REG_PERF_CLOSE:
1060 case TRACE_REG_PERF_ADD: 1201 case TRACE_REG_PERF_ADD:
@@ -1190,11 +1331,24 @@ static __used int kprobe_trace_selftest_target(int a1, int a2, int a3,
1190 return a1 + a2 + a3 + a4 + a5 + a6; 1331 return a1 + a2 + a3 + a4 + a5 + a6;
1191} 1332}
1192 1333
1334static struct ftrace_event_file *
1335find_trace_probe_file(struct trace_probe *tp, struct trace_array *tr)
1336{
1337 struct ftrace_event_file *file;
1338
1339 list_for_each_entry(file, &tr->events, list)
1340 if (file->event_call == &tp->call)
1341 return file;
1342
1343 return NULL;
1344}
1345
1193static __init int kprobe_trace_self_tests_init(void) 1346static __init int kprobe_trace_self_tests_init(void)
1194{ 1347{
1195 int ret, warn = 0; 1348 int ret, warn = 0;
1196 int (*target)(int, int, int, int, int, int); 1349 int (*target)(int, int, int, int, int, int);
1197 struct trace_probe *tp; 1350 struct trace_probe *tp;
1351 struct ftrace_event_file *file;
1198 1352
1199 target = kprobe_trace_selftest_target; 1353 target = kprobe_trace_selftest_target;
1200 1354
@@ -1204,31 +1358,43 @@ static __init int kprobe_trace_self_tests_init(void)
1204 "$stack $stack0 +0($stack)", 1358 "$stack $stack0 +0($stack)",
1205 create_trace_probe); 1359 create_trace_probe);
1206 if (WARN_ON_ONCE(ret)) { 1360 if (WARN_ON_ONCE(ret)) {
1207 pr_warning("error on probing function entry.\n"); 1361 pr_warn("error on probing function entry.\n");
1208 warn++; 1362 warn++;
1209 } else { 1363 } else {
1210 /* Enable trace point */ 1364 /* Enable trace point */
1211 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); 1365 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
1212 if (WARN_ON_ONCE(tp == NULL)) { 1366 if (WARN_ON_ONCE(tp == NULL)) {
1213 pr_warning("error on getting new probe.\n"); 1367 pr_warn("error on getting new probe.\n");
1214 warn++; 1368 warn++;
1215 } else 1369 } else {
1216 enable_trace_probe(tp, TP_FLAG_TRACE); 1370 file = find_trace_probe_file(tp, top_trace_array());
1371 if (WARN_ON_ONCE(file == NULL)) {
1372 pr_warn("error on getting probe file.\n");
1373 warn++;
1374 } else
1375 enable_trace_probe(tp, file);
1376 }
1217 } 1377 }
1218 1378
1219 ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target " 1379 ret = traceprobe_command("r:testprobe2 kprobe_trace_selftest_target "
1220 "$retval", create_trace_probe); 1380 "$retval", create_trace_probe);
1221 if (WARN_ON_ONCE(ret)) { 1381 if (WARN_ON_ONCE(ret)) {
1222 pr_warning("error on probing function return.\n"); 1382 pr_warn("error on probing function return.\n");
1223 warn++; 1383 warn++;
1224 } else { 1384 } else {
1225 /* Enable trace point */ 1385 /* Enable trace point */
1226 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); 1386 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
1227 if (WARN_ON_ONCE(tp == NULL)) { 1387 if (WARN_ON_ONCE(tp == NULL)) {
1228 pr_warning("error on getting new probe.\n"); 1388 pr_warn("error on getting 2nd new probe.\n");
1229 warn++; 1389 warn++;
1230 } else 1390 } else {
1231 enable_trace_probe(tp, TP_FLAG_TRACE); 1391 file = find_trace_probe_file(tp, top_trace_array());
1392 if (WARN_ON_ONCE(file == NULL)) {
1393 pr_warn("error on getting probe file.\n");
1394 warn++;
1395 } else
1396 enable_trace_probe(tp, file);
1397 }
1232 } 1398 }
1233 1399
1234 if (warn) 1400 if (warn)
@@ -1239,27 +1405,39 @@ static __init int kprobe_trace_self_tests_init(void)
1239 /* Disable trace points before removing it */ 1405 /* Disable trace points before removing it */
1240 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM); 1406 tp = find_trace_probe("testprobe", KPROBE_EVENT_SYSTEM);
1241 if (WARN_ON_ONCE(tp == NULL)) { 1407 if (WARN_ON_ONCE(tp == NULL)) {
1242 pr_warning("error on getting test probe.\n"); 1408 pr_warn("error on getting test probe.\n");
1243 warn++; 1409 warn++;
1244 } else 1410 } else {
1245 disable_trace_probe(tp, TP_FLAG_TRACE); 1411 file = find_trace_probe_file(tp, top_trace_array());
1412 if (WARN_ON_ONCE(file == NULL)) {
1413 pr_warn("error on getting probe file.\n");
1414 warn++;
1415 } else
1416 disable_trace_probe(tp, file);
1417 }
1246 1418
1247 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM); 1419 tp = find_trace_probe("testprobe2", KPROBE_EVENT_SYSTEM);
1248 if (WARN_ON_ONCE(tp == NULL)) { 1420 if (WARN_ON_ONCE(tp == NULL)) {
1249 pr_warning("error on getting 2nd test probe.\n"); 1421 pr_warn("error on getting 2nd test probe.\n");
1250 warn++; 1422 warn++;
1251 } else 1423 } else {
1252 disable_trace_probe(tp, TP_FLAG_TRACE); 1424 file = find_trace_probe_file(tp, top_trace_array());
1425 if (WARN_ON_ONCE(file == NULL)) {
1426 pr_warn("error on getting probe file.\n");
1427 warn++;
1428 } else
1429 disable_trace_probe(tp, file);
1430 }
1253 1431
1254 ret = traceprobe_command("-:testprobe", create_trace_probe); 1432 ret = traceprobe_command("-:testprobe", create_trace_probe);
1255 if (WARN_ON_ONCE(ret)) { 1433 if (WARN_ON_ONCE(ret)) {
1256 pr_warning("error on deleting a probe.\n"); 1434 pr_warn("error on deleting a probe.\n");
1257 warn++; 1435 warn++;
1258 } 1436 }
1259 1437
1260 ret = traceprobe_command("-:testprobe2", create_trace_probe); 1438 ret = traceprobe_command("-:testprobe2", create_trace_probe);
1261 if (WARN_ON_ONCE(ret)) { 1439 if (WARN_ON_ONCE(ret)) {
1262 pr_warning("error on deleting a probe.\n"); 1440 pr_warn("error on deleting a probe.\n");
1263 warn++; 1441 warn++;
1264 } 1442 }
1265 1443