aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/ftrace_event.h4
-rw-r--r--kernel/trace/trace.h3
-rw-r--r--kernel/trace/trace_events_filter.c124
3 files changed, 87 insertions, 44 deletions
diff --git a/include/linux/ftrace_event.h b/include/linux/ftrace_event.h
index 5c093ffc655b..26d3673d5143 100644
--- a/include/linux/ftrace_event.h
+++ b/include/linux/ftrace_event.h
@@ -101,6 +101,8 @@ void trace_current_buffer_discard_commit(struct ring_buffer_event *event);
101 101
102void tracing_record_cmdline(struct task_struct *tsk); 102void tracing_record_cmdline(struct task_struct *tsk);
103 103
104struct event_filter;
105
104struct ftrace_event_call { 106struct ftrace_event_call {
105 struct list_head list; 107 struct list_head list;
106 char *name; 108 char *name;
@@ -116,7 +118,7 @@ struct ftrace_event_call {
116 int (*define_fields)(void); 118 int (*define_fields)(void);
117 struct list_head fields; 119 struct list_head fields;
118 int filter_active; 120 int filter_active;
119 void *filter; 121 struct event_filter *filter;
120 void *mod; 122 void *mod;
121 123
122#ifdef CONFIG_EVENT_PROFILE 124#ifdef CONFIG_EVENT_PROFILE
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 94305c7bc11c..758b0dbed552 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -750,13 +750,14 @@ struct event_filter {
750 int n_preds; 750 int n_preds;
751 struct filter_pred **preds; 751 struct filter_pred **preds;
752 char *filter_string; 752 char *filter_string;
753 bool no_reset;
753}; 754};
754 755
755struct event_subsystem { 756struct event_subsystem {
756 struct list_head list; 757 struct list_head list;
757 const char *name; 758 const char *name;
758 struct dentry *entry; 759 struct dentry *entry;
759 void *filter; 760 struct event_filter *filter;
760 int nr_events; 761 int nr_events;
761}; 762};
762 763
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 1c80ef702b83..27c2dbea3710 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -420,7 +420,14 @@ oom:
420} 420}
421EXPORT_SYMBOL_GPL(init_preds); 421EXPORT_SYMBOL_GPL(init_preds);
422 422
423static void filter_free_subsystem_preds(struct event_subsystem *system) 423enum {
424 FILTER_DISABLE_ALL,
425 FILTER_INIT_NO_RESET,
426 FILTER_SKIP_NO_RESET,
427};
428
429static void filter_free_subsystem_preds(struct event_subsystem *system,
430 int flag)
424{ 431{
425 struct ftrace_event_call *call; 432 struct ftrace_event_call *call;
426 433
@@ -428,6 +435,14 @@ static void filter_free_subsystem_preds(struct event_subsystem *system)
428 if (!call->define_fields) 435 if (!call->define_fields)
429 continue; 436 continue;
430 437
438 if (flag == FILTER_INIT_NO_RESET) {
439 call->filter->no_reset = false;
440 continue;
441 }
442
443 if (flag == FILTER_SKIP_NO_RESET && call->filter->no_reset)
444 continue;
445
431 if (!strcmp(call->system, system->name)) { 446 if (!strcmp(call->system, system->name)) {
432 filter_disable_preds(call); 447 filter_disable_preds(call);
433 remove_filter_string(call->filter); 448 remove_filter_string(call->filter);
@@ -529,7 +544,8 @@ static filter_pred_fn_t select_comparison_fn(int op, int field_size,
529 544
530static int filter_add_pred(struct filter_parse_state *ps, 545static int filter_add_pred(struct filter_parse_state *ps,
531 struct ftrace_event_call *call, 546 struct ftrace_event_call *call,
532 struct filter_pred *pred) 547 struct filter_pred *pred,
548 bool dry_run)
533{ 549{
534 struct ftrace_event_field *field; 550 struct ftrace_event_field *field;
535 filter_pred_fn_t fn; 551 filter_pred_fn_t fn;
@@ -541,10 +557,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
541 557
542 if (pred->op == OP_AND) { 558 if (pred->op == OP_AND) {
543 pred->pop_n = 2; 559 pred->pop_n = 2;
544 return filter_add_pred_fn(ps, call, pred, filter_pred_and); 560 fn = filter_pred_and;
561 goto add_pred_fn;
545 } else if (pred->op == OP_OR) { 562 } else if (pred->op == OP_OR) {
546 pred->pop_n = 2; 563 pred->pop_n = 2;
547 return filter_add_pred_fn(ps, call, pred, filter_pred_or); 564 fn = filter_pred_or;
565 goto add_pred_fn;
548 } 566 }
549 567
550 field = find_event_field(call, pred->field_name); 568 field = find_event_field(call, pred->field_name);
@@ -567,9 +585,6 @@ static int filter_add_pred(struct filter_parse_state *ps,
567 else 585 else
568 fn = filter_pred_strloc; 586 fn = filter_pred_strloc;
569 pred->str_len = field->size; 587 pred->str_len = field->size;
570 if (pred->op == OP_NE)
571 pred->not = 1;
572 return filter_add_pred_fn(ps, call, pred, fn);
573 } else { 588 } else {
574 if (field->is_signed) 589 if (field->is_signed)
575 ret = strict_strtoll(pred->str_val, 0, &val); 590 ret = strict_strtoll(pred->str_val, 0, &val);
@@ -580,27 +595,33 @@ static int filter_add_pred(struct filter_parse_state *ps,
580 return -EINVAL; 595 return -EINVAL;
581 } 596 }
582 pred->val = val; 597 pred->val = val;
583 }
584 598
585 fn = select_comparison_fn(pred->op, field->size, field->is_signed); 599 fn = select_comparison_fn(pred->op, field->size,
586 if (!fn) { 600 field->is_signed);
587 parse_error(ps, FILT_ERR_INVALID_OP, 0); 601 if (!fn) {
588 return -EINVAL; 602 parse_error(ps, FILT_ERR_INVALID_OP, 0);
603 return -EINVAL;
604 }
589 } 605 }
590 606
591 if (pred->op == OP_NE) 607 if (pred->op == OP_NE)
592 pred->not = 1; 608 pred->not = 1;
593 609
594 return filter_add_pred_fn(ps, call, pred, fn); 610add_pred_fn:
611 if (!dry_run)
612 return filter_add_pred_fn(ps, call, pred, fn);
613 return 0;
595} 614}
596 615
597static int filter_add_subsystem_pred(struct filter_parse_state *ps, 616static int filter_add_subsystem_pred(struct filter_parse_state *ps,
598 struct event_subsystem *system, 617 struct event_subsystem *system,
599 struct filter_pred *pred, 618 struct filter_pred *pred,
600 char *filter_string) 619 char *filter_string,
620 bool dry_run)
601{ 621{
602 struct ftrace_event_call *call; 622 struct ftrace_event_call *call;
603 int err = 0; 623 int err = 0;
624 bool fail = true;
604 625
605 list_for_each_entry(call, &ftrace_events, list) { 626 list_for_each_entry(call, &ftrace_events, list) {
606 627
@@ -610,16 +631,24 @@ static int filter_add_subsystem_pred(struct filter_parse_state *ps,
610 if (strcmp(call->system, system->name)) 631 if (strcmp(call->system, system->name))
611 continue; 632 continue;
612 633
613 err = filter_add_pred(ps, call, pred); 634 if (call->filter->no_reset)
614 if (err) { 635 continue;
615 filter_free_subsystem_preds(system); 636
616 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0); 637 err = filter_add_pred(ps, call, pred, dry_run);
617 goto out; 638 if (err)
618 } 639 call->filter->no_reset = true;
619 replace_filter_string(call->filter, filter_string); 640 else
641 fail = false;
642
643 if (!dry_run)
644 replace_filter_string(call->filter, filter_string);
620 } 645 }
621out: 646
622 return err; 647 if (fail) {
648 parse_error(ps, FILT_ERR_BAD_SUBSYS_FILTER, 0);
649 return err;
650 }
651 return 0;
623} 652}
624 653
625static void parse_init(struct filter_parse_state *ps, 654static void parse_init(struct filter_parse_state *ps,
@@ -978,12 +1007,14 @@ static int check_preds(struct filter_parse_state *ps)
978static int replace_preds(struct event_subsystem *system, 1007static int replace_preds(struct event_subsystem *system,
979 struct ftrace_event_call *call, 1008 struct ftrace_event_call *call,
980 struct filter_parse_state *ps, 1009 struct filter_parse_state *ps,
981 char *filter_string) 1010 char *filter_string,
1011 bool dry_run)
982{ 1012{
983 char *operand1 = NULL, *operand2 = NULL; 1013 char *operand1 = NULL, *operand2 = NULL;
984 struct filter_pred *pred; 1014 struct filter_pred *pred;
985 struct postfix_elt *elt; 1015 struct postfix_elt *elt;
986 int err; 1016 int err;
1017 int n_preds = 0;
987 1018
988 err = check_preds(ps); 1019 err = check_preds(ps);
989 if (err) 1020 if (err)
@@ -1002,19 +1033,14 @@ static int replace_preds(struct event_subsystem *system,
1002 continue; 1033 continue;
1003 } 1034 }
1004 1035
1036 if (n_preds++ == MAX_FILTER_PRED) {
1037 parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
1038 return -ENOSPC;
1039 }
1040
1005 if (elt->op == OP_AND || elt->op == OP_OR) { 1041 if (elt->op == OP_AND || elt->op == OP_OR) {
1006 pred = create_logical_pred(elt->op); 1042 pred = create_logical_pred(elt->op);
1007 if (call) 1043 goto add_pred;
1008 err = filter_add_pred(ps, call, pred);
1009 else
1010 err = filter_add_subsystem_pred(ps, system,
1011 pred, filter_string);
1012 filter_free_pred(pred);
1013 if (err)
1014 return err;
1015
1016 operand1 = operand2 = NULL;
1017 continue;
1018 } 1044 }
1019 1045
1020 if (!operand1 || !operand2) { 1046 if (!operand1 || !operand2) {
@@ -1023,11 +1049,12 @@ static int replace_preds(struct event_subsystem *system,
1023 } 1049 }
1024 1050
1025 pred = create_pred(elt->op, operand1, operand2); 1051 pred = create_pred(elt->op, operand1, operand2);
1052add_pred:
1026 if (call) 1053 if (call)
1027 err = filter_add_pred(ps, call, pred); 1054 err = filter_add_pred(ps, call, pred, false);
1028 else 1055 else
1029 err = filter_add_subsystem_pred(ps, system, pred, 1056 err = filter_add_subsystem_pred(ps, system, pred,
1030 filter_string); 1057 filter_string, dry_run);
1031 filter_free_pred(pred); 1058 filter_free_pred(pred);
1032 if (err) 1059 if (err)
1033 return err; 1060 return err;
@@ -1068,7 +1095,7 @@ int apply_event_filter(struct ftrace_event_call *call, char *filter_string)
1068 goto out; 1095 goto out;
1069 } 1096 }
1070 1097
1071 err = replace_preds(NULL, call, ps, filter_string); 1098 err = replace_preds(NULL, call, ps, filter_string, false);
1072 if (err) 1099 if (err)
1073 append_filter_err(ps, call->filter); 1100 append_filter_err(ps, call->filter);
1074 1101
@@ -1092,7 +1119,7 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1092 mutex_lock(&event_mutex); 1119 mutex_lock(&event_mutex);
1093 1120
1094 if (!strcmp(strstrip(filter_string), "0")) { 1121 if (!strcmp(strstrip(filter_string), "0")) {
1095 filter_free_subsystem_preds(system); 1122 filter_free_subsystem_preds(system, FILTER_DISABLE_ALL);
1096 remove_filter_string(system->filter); 1123 remove_filter_string(system->filter);
1097 mutex_unlock(&event_mutex); 1124 mutex_unlock(&event_mutex);
1098 return 0; 1125 return 0;
@@ -1103,7 +1130,6 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1103 if (!ps) 1130 if (!ps)
1104 goto out_unlock; 1131 goto out_unlock;
1105 1132
1106 filter_free_subsystem_preds(system);
1107 replace_filter_string(system->filter, filter_string); 1133 replace_filter_string(system->filter, filter_string);
1108 1134
1109 parse_init(ps, filter_ops, filter_string); 1135 parse_init(ps, filter_ops, filter_string);
@@ -1113,9 +1139,23 @@ int apply_subsystem_event_filter(struct event_subsystem *system,
1113 goto out; 1139 goto out;
1114 } 1140 }
1115 1141
1116 err = replace_preds(system, NULL, ps, filter_string); 1142 filter_free_subsystem_preds(system, FILTER_INIT_NO_RESET);
1117 if (err) 1143
1144 /* try to see the filter can be applied to which events */
1145 err = replace_preds(system, NULL, ps, filter_string, true);
1146 if (err) {
1147 append_filter_err(ps, system->filter);
1148 goto out;
1149 }
1150
1151 filter_free_subsystem_preds(system, FILTER_SKIP_NO_RESET);
1152
1153 /* really apply the filter to the events */
1154 err = replace_preds(system, NULL, ps, filter_string, false);
1155 if (err) {
1118 append_filter_err(ps, system->filter); 1156 append_filter_err(ps, system->filter);
1157 filter_free_subsystem_preds(system, 2);
1158 }
1119 1159
1120out: 1160out:
1121 filter_opstack_clear(ps); 1161 filter_opstack_clear(ps);