diff options
Diffstat (limited to 'kernel/trace')
-rw-r--r-- | kernel/trace/trace.h | 3 | ||||
-rw-r--r-- | kernel/trace/trace_events_filter.c | 133 |
2 files changed, 109 insertions, 27 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index ffe53ddbe67a..4959ada9e0bb 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -743,7 +743,8 @@ filter_check_discard(struct ftrace_event_call *call, void *rec, | |||
743 | struct ring_buffer *buffer, | 743 | struct ring_buffer *buffer, |
744 | struct ring_buffer_event *event) | 744 | struct ring_buffer_event *event) |
745 | { | 745 | { |
746 | if (unlikely(call->filter_active) && !filter_match_preds(call, rec)) { | 746 | if (unlikely(call->filter_active) && |
747 | !filter_match_preds(call->filter, rec)) { | ||
747 | ring_buffer_discard_commit(buffer, event); | 748 | ring_buffer_discard_commit(buffer, event); |
748 | return 1; | 749 | return 1; |
749 | } | 750 | } |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 273845fce393..e27bb6acc2dd 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | #include <linux/ctype.h> | 22 | #include <linux/ctype.h> |
23 | #include <linux/mutex.h> | 23 | #include <linux/mutex.h> |
24 | #include <linux/perf_event.h> | ||
24 | 25 | ||
25 | #include "trace.h" | 26 | #include "trace.h" |
26 | #include "trace_output.h" | 27 | #include "trace_output.h" |
@@ -363,9 +364,8 @@ static void filter_build_regex(struct filter_pred *pred) | |||
363 | } | 364 | } |
364 | 365 | ||
365 | /* return 1 if event matches, 0 otherwise (discard) */ | 366 | /* return 1 if event matches, 0 otherwise (discard) */ |
366 | int filter_match_preds(struct ftrace_event_call *call, void *rec) | 367 | int filter_match_preds(struct event_filter *filter, void *rec) |
367 | { | 368 | { |
368 | struct event_filter *filter = call->filter; | ||
369 | int match, top = 0, val1 = 0, val2 = 0; | 369 | int match, top = 0, val1 = 0, val2 = 0; |
370 | int stack[MAX_FILTER_PRED]; | 370 | int stack[MAX_FILTER_PRED]; |
371 | struct filter_pred *pred; | 371 | struct filter_pred *pred; |
@@ -538,9 +538,8 @@ static void filter_disable_preds(struct ftrace_event_call *call) | |||
538 | filter->preds[i]->fn = filter_pred_none; | 538 | filter->preds[i]->fn = filter_pred_none; |
539 | } | 539 | } |
540 | 540 | ||
541 | void destroy_preds(struct ftrace_event_call *call) | 541 | static void __free_preds(struct event_filter *filter) |
542 | { | 542 | { |
543 | struct event_filter *filter = call->filter; | ||
544 | int i; | 543 | int i; |
545 | 544 | ||
546 | if (!filter) | 545 | if (!filter) |
@@ -553,21 +552,24 @@ void destroy_preds(struct ftrace_event_call *call) | |||
553 | kfree(filter->preds); | 552 | kfree(filter->preds); |
554 | kfree(filter->filter_string); | 553 | kfree(filter->filter_string); |
555 | kfree(filter); | 554 | kfree(filter); |
555 | } | ||
556 | |||
557 | void destroy_preds(struct ftrace_event_call *call) | ||
558 | { | ||
559 | __free_preds(call->filter); | ||
556 | call->filter = NULL; | 560 | call->filter = NULL; |
561 | call->filter_active = 0; | ||
557 | } | 562 | } |
558 | 563 | ||
559 | static int init_preds(struct ftrace_event_call *call) | 564 | static struct event_filter *__alloc_preds(void) |
560 | { | 565 | { |
561 | struct event_filter *filter; | 566 | struct event_filter *filter; |
562 | struct filter_pred *pred; | 567 | struct filter_pred *pred; |
563 | int i; | 568 | int i; |
564 | 569 | ||
565 | if (call->filter) | 570 | filter = kzalloc(sizeof(*filter), GFP_KERNEL); |
566 | return 0; | 571 | if (!filter) |
567 | 572 | return ERR_PTR(-ENOMEM); | |
568 | filter = call->filter = kzalloc(sizeof(*filter), GFP_KERNEL); | ||
569 | if (!call->filter) | ||
570 | return -ENOMEM; | ||
571 | 573 | ||
572 | filter->n_preds = 0; | 574 | filter->n_preds = 0; |
573 | 575 | ||
@@ -583,12 +585,24 @@ static int init_preds(struct ftrace_event_call *call) | |||
583 | filter->preds[i] = pred; | 585 | filter->preds[i] = pred; |
584 | } | 586 | } |
585 | 587 | ||
586 | return 0; | 588 | return filter; |
587 | 589 | ||
588 | oom: | 590 | oom: |
589 | destroy_preds(call); | 591 | __free_preds(filter); |
592 | return ERR_PTR(-ENOMEM); | ||
593 | } | ||
594 | |||
595 | static int init_preds(struct ftrace_event_call *call) | ||
596 | { | ||
597 | if (call->filter) | ||
598 | return 0; | ||
599 | |||
600 | call->filter_active = 0; | ||
601 | call->filter = __alloc_preds(); | ||
602 | if (IS_ERR(call->filter)) | ||
603 | return PTR_ERR(call->filter); | ||
590 | 604 | ||
591 | return -ENOMEM; | 605 | return 0; |
592 | } | 606 | } |
593 | 607 | ||
594 | static int init_subsystem_preds(struct event_subsystem *system) | 608 | static int init_subsystem_preds(struct event_subsystem *system) |
@@ -629,10 +643,10 @@ static void filter_free_subsystem_preds(struct event_subsystem *system) | |||
629 | 643 | ||
630 | static int filter_add_pred_fn(struct filter_parse_state *ps, | 644 | static int filter_add_pred_fn(struct filter_parse_state *ps, |
631 | struct ftrace_event_call *call, | 645 | struct ftrace_event_call *call, |
646 | struct event_filter *filter, | ||
632 | struct filter_pred *pred, | 647 | struct filter_pred *pred, |
633 | filter_pred_fn_t fn) | 648 | filter_pred_fn_t fn) |
634 | { | 649 | { |
635 | struct event_filter *filter = call->filter; | ||
636 | int idx, err; | 650 | int idx, err; |
637 | 651 | ||
638 | if (filter->n_preds == MAX_FILTER_PRED) { | 652 | if (filter->n_preds == MAX_FILTER_PRED) { |
@@ -647,7 +661,6 @@ static int filter_add_pred_fn(struct filter_parse_state *ps, | |||
647 | return err; | 661 | return err; |
648 | 662 | ||
649 | filter->n_preds++; | 663 | filter->n_preds++; |
650 | call->filter_active = 1; | ||
651 | 664 | ||
652 | return 0; | 665 | return 0; |
653 | } | 666 | } |
@@ -726,6 +739,7 @@ static filter_pred_fn_t select_comparison_fn(int op, int field_size, | |||
726 | 739 | ||
727 | static int filter_add_pred(struct filter_parse_state *ps, | 740 | static int filter_add_pred(struct filter_parse_state *ps, |
728 | struct ftrace_event_call *call, | 741 | struct ftrace_event_call *call, |
742 | struct event_filter *filter, | ||
729 | struct filter_pred *pred, | 743 | struct filter_pred *pred, |
730 | bool dry_run) | 744 | bool dry_run) |
731 | { | 745 | { |
@@ -795,7 +809,7 @@ static int filter_add_pred(struct filter_parse_state *ps, | |||
795 | 809 | ||
796 | add_pred_fn: | 810 | add_pred_fn: |
797 | if (!dry_run) | 811 | if (!dry_run) |
798 | return filter_add_pred_fn(ps, call, pred, fn); | 812 | return filter_add_pred_fn(ps, call, filter, pred, fn); |
799 | return 0; | 813 | return 0; |
800 | } | 814 | } |
801 | 815 | ||
@@ -1154,6 +1168,7 @@ static int check_preds(struct filter_parse_state *ps) | |||
1154 | } | 1168 | } |
1155 | 1169 | ||
1156 | static int replace_preds(struct ftrace_event_call *call, | 1170 | static int replace_preds(struct ftrace_event_call *call, |
1171 | struct event_filter *filter, | ||
1157 | struct filter_parse_state *ps, | 1172 | struct filter_parse_state *ps, |
1158 | char *filter_string, | 1173 | char *filter_string, |
1159 | bool dry_run) | 1174 | bool dry_run) |
@@ -1200,7 +1215,7 @@ static int replace_preds(struct ftrace_event_call *call, | |||
1200 | add_pred: | 1215 | add_pred: |
1201 | if (!pred) | 1216 | if (!pred) |
1202 | return -ENOMEM; | 1217 | return -ENOMEM; |
1203 | err = filter_add_pred(ps, call, pred, dry_run); | 1218 | err = filter_add_pred(ps, call, filter, pred, dry_run); |
1204 | filter_free_pred(pred); | 1219 | filter_free_pred(pred); |
1205 | if (err) | 1220 | if (err) |
1206 | return err; | 1221 | return err; |
@@ -1216,6 +1231,7 @@ static int replace_system_preds(struct event_subsystem *system, | |||
1216 | char *filter_string) | 1231 | char *filter_string) |
1217 | { | 1232 | { |
1218 | struct ftrace_event_call *call; | 1233 | struct ftrace_event_call *call; |
1234 | struct event_filter *filter; | ||
1219 | int err; | 1235 | int err; |
1220 | bool fail = true; | 1236 | bool fail = true; |
1221 | 1237 | ||
@@ -1228,17 +1244,19 @@ static int replace_system_preds(struct event_subsystem *system, | |||
1228 | continue; | 1244 | continue; |
1229 | 1245 | ||
1230 | /* try to see if the filter can be applied */ | 1246 | /* try to see if the filter can be applied */ |
1231 | err = replace_preds(call, ps, filter_string, true); | 1247 | err = replace_preds(call, filter, ps, filter_string, true); |
1232 | if (err) | 1248 | if (err) |
1233 | continue; | 1249 | continue; |
1234 | 1250 | ||
1235 | /* really apply the filter */ | 1251 | /* really apply the filter */ |
1236 | filter_disable_preds(call); | 1252 | filter_disable_preds(call); |
1237 | err = replace_preds(call, ps, filter_string, false); | 1253 | err = replace_preds(call, filter, ps, filter_string, false); |
1238 | if (err) | 1254 | if (err) |
1239 | filter_disable_preds(call); | 1255 | filter_disable_preds(call); |
1240 | else | 1256 | else { |
1241 | replace_filter_string(call->filter, filter_string); | 1257 | call->filter_active = 1; |
1258 | replace_filter_string(filter, filter_string); | ||
1259 | } | ||
1242 | fail = false; | 1260 | fail = false; |
1243 | } | 1261 | } |
1244 | 1262 | ||
@@ -1252,7 +1270,6 @@ static int replace_system_preds(struct event_subsystem *system, | |||
1252 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | 1270 | int apply_event_filter(struct ftrace_event_call *call, char *filter_string) |
1253 | { | 1271 | { |
1254 | int err; | 1272 | int err; |
1255 | |||
1256 | struct filter_parse_state *ps; | 1273 | struct filter_parse_state *ps; |
1257 | 1274 | ||
1258 | mutex_lock(&event_mutex); | 1275 | mutex_lock(&event_mutex); |
@@ -1283,10 +1300,11 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string) | |||
1283 | goto out; | 1300 | goto out; |
1284 | } | 1301 | } |
1285 | 1302 | ||
1286 | err = replace_preds(call, ps, filter_string, false); | 1303 | err = replace_preds(call, call->filter, ps, filter_string, false); |
1287 | if (err) | 1304 | if (err) |
1288 | append_filter_err(ps, call->filter); | 1305 | append_filter_err(ps, call->filter); |
1289 | 1306 | else | |
1307 | call->filter_active = 1; | ||
1290 | out: | 1308 | out: |
1291 | filter_opstack_clear(ps); | 1309 | filter_opstack_clear(ps); |
1292 | postfix_clear(ps); | 1310 | postfix_clear(ps); |
@@ -1301,7 +1319,6 @@ int apply_subsystem_event_filter(struct event_subsystem *system, | |||
1301 | char *filter_string) | 1319 | char *filter_string) |
1302 | { | 1320 | { |
1303 | int err; | 1321 | int err; |
1304 | |||
1305 | struct filter_parse_state *ps; | 1322 | struct filter_parse_state *ps; |
1306 | 1323 | ||
1307 | mutex_lock(&event_mutex); | 1324 | mutex_lock(&event_mutex); |
@@ -1345,3 +1362,67 @@ out_unlock: | |||
1345 | return err; | 1362 | return err; |
1346 | } | 1363 | } |
1347 | 1364 | ||
1365 | #ifdef CONFIG_EVENT_PROFILE | ||
1366 | |||
1367 | void ftrace_profile_free_filter(struct perf_event *event) | ||
1368 | { | ||
1369 | struct event_filter *filter = event->filter; | ||
1370 | |||
1371 | event->filter = NULL; | ||
1372 | __free_preds(filter); | ||
1373 | } | ||
1374 | |||
1375 | int ftrace_profile_set_filter(struct perf_event *event, int event_id, | ||
1376 | char *filter_str) | ||
1377 | { | ||
1378 | int err; | ||
1379 | struct event_filter *filter; | ||
1380 | struct filter_parse_state *ps; | ||
1381 | struct ftrace_event_call *call = NULL; | ||
1382 | |||
1383 | mutex_lock(&event_mutex); | ||
1384 | |||
1385 | list_for_each_entry(call, &ftrace_events, list) { | ||
1386 | if (call->id == event_id) | ||
1387 | break; | ||
1388 | } | ||
1389 | if (!call) | ||
1390 | return -EINVAL; | ||
1391 | |||
1392 | if (event->filter) | ||
1393 | return -EEXIST; | ||
1394 | |||
1395 | filter = __alloc_preds(); | ||
1396 | if (IS_ERR(filter)) | ||
1397 | return PTR_ERR(filter); | ||
1398 | |||
1399 | err = -ENOMEM; | ||
1400 | ps = kzalloc(sizeof(*ps), GFP_KERNEL); | ||
1401 | if (!ps) | ||
1402 | goto free_preds; | ||
1403 | |||
1404 | parse_init(ps, filter_ops, filter_str); | ||
1405 | err = filter_parse(ps); | ||
1406 | if (err) | ||
1407 | goto free_ps; | ||
1408 | |||
1409 | err = replace_preds(call, filter, ps, filter_str, false); | ||
1410 | if (!err) | ||
1411 | event->filter = filter; | ||
1412 | |||
1413 | free_ps: | ||
1414 | filter_opstack_clear(ps); | ||
1415 | postfix_clear(ps); | ||
1416 | kfree(ps); | ||
1417 | |||
1418 | free_preds: | ||
1419 | if (err) | ||
1420 | __free_preds(filter); | ||
1421 | |||
1422 | mutex_unlock(&event_mutex); | ||
1423 | |||
1424 | return err; | ||
1425 | } | ||
1426 | |||
1427 | #endif /* CONFIG_EVENT_PROFILE */ | ||
1428 | |||