diff options
-rw-r--r-- | kernel/trace/trace.h | 14 | ||||
-rw-r--r-- | kernel/trace/trace_events.c | 9 | ||||
-rw-r--r-- | kernel/trace/trace_events_filter.c | 252 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_2.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_events_stage_3.h | 1 | ||||
-rw-r--r-- | kernel/trace/trace_export.c | 1 |
6 files changed, 150 insertions, 128 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h index 9729d14767d8..b05b6ac982a1 100644 --- a/kernel/trace/trace.h +++ b/kernel/trace/trace.h | |||
@@ -813,6 +813,7 @@ struct ftrace_event_call { | |||
813 | int (*show_format)(struct trace_seq *s); | 813 | int (*show_format)(struct trace_seq *s); |
814 | int (*define_fields)(void); | 814 | int (*define_fields)(void); |
815 | struct list_head fields; | 815 | struct list_head fields; |
816 | int n_preds; | ||
816 | struct filter_pred **preds; | 817 | struct filter_pred **preds; |
817 | 818 | ||
818 | #ifdef CONFIG_EVENT_PROFILE | 819 | #ifdef CONFIG_EVENT_PROFILE |
@@ -826,6 +827,7 @@ struct event_subsystem { | |||
826 | struct list_head list; | 827 | struct list_head list; |
827 | const char *name; | 828 | const char *name; |
828 | struct dentry *entry; | 829 | struct dentry *entry; |
830 | int n_preds; | ||
829 | struct filter_pred **preds; | 831 | struct filter_pred **preds; |
830 | }; | 832 | }; |
831 | 833 | ||
@@ -834,7 +836,8 @@ struct event_subsystem { | |||
834 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ | 836 | (unsigned long)event < (unsigned long)__stop_ftrace_events; \ |
835 | event++) | 837 | event++) |
836 | 838 | ||
837 | #define MAX_FILTER_PRED 8 | 839 | #define MAX_FILTER_PRED 8 |
840 | #define MAX_FILTER_STR_VAL 128 | ||
838 | 841 | ||
839 | struct filter_pred; | 842 | struct filter_pred; |
840 | 843 | ||
@@ -843,7 +846,7 @@ typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event); | |||
843 | struct filter_pred { | 846 | struct filter_pred { |
844 | filter_pred_fn_t fn; | 847 | filter_pred_fn_t fn; |
845 | u64 val; | 848 | u64 val; |
846 | char *str_val; | 849 | char str_val[MAX_FILTER_STR_VAL]; |
847 | int str_len; | 850 | int str_len; |
848 | char *field_name; | 851 | char *field_name; |
849 | int offset; | 852 | int offset; |
@@ -855,13 +858,14 @@ struct filter_pred { | |||
855 | 858 | ||
856 | int trace_define_field(struct ftrace_event_call *call, char *type, | 859 | int trace_define_field(struct ftrace_event_call *call, char *type, |
857 | char *name, int offset, int size); | 860 | char *name, int offset, int size); |
861 | extern int init_preds(struct ftrace_event_call *call); | ||
858 | extern void filter_free_pred(struct filter_pred *pred); | 862 | extern void filter_free_pred(struct filter_pred *pred); |
859 | extern void filter_print_preds(struct filter_pred **preds, | 863 | extern void filter_print_preds(struct filter_pred **preds, int n_preds, |
860 | struct trace_seq *s); | 864 | struct trace_seq *s); |
861 | extern int filter_parse(char **pbuf, struct filter_pred *pred); | 865 | extern int filter_parse(char **pbuf, struct filter_pred *pred); |
862 | extern int filter_add_pred(struct ftrace_event_call *call, | 866 | extern int filter_add_pred(struct ftrace_event_call *call, |
863 | struct filter_pred *pred); | 867 | struct filter_pred *pred); |
864 | extern void filter_free_preds(struct ftrace_event_call *call); | 868 | extern void filter_disable_preds(struct ftrace_event_call *call); |
865 | extern int filter_match_preds(struct ftrace_event_call *call, void *rec); | 869 | extern int filter_match_preds(struct ftrace_event_call *call, void *rec); |
866 | extern void filter_free_subsystem_preds(struct event_subsystem *system); | 870 | extern void filter_free_subsystem_preds(struct event_subsystem *system); |
867 | extern int filter_add_subsystem_pred(struct event_subsystem *system, | 871 | extern int filter_add_subsystem_pred(struct event_subsystem *system, |
@@ -875,7 +879,7 @@ filter_check_discard(struct ftrace_event_call *call, void *rec, | |||
875 | struct ring_buffer *buffer, | 879 | struct ring_buffer *buffer, |
876 | struct ring_buffer_event *event) | 880 | struct ring_buffer_event *event) |
877 | { | 881 | { |
878 | if (unlikely(call->preds) && !filter_match_preds(call, rec)) { | 882 | if (unlikely(call->n_preds) && !filter_match_preds(call, rec)) { |
879 | ring_buffer_discard_commit(buffer, event); | 883 | ring_buffer_discard_commit(buffer, event); |
880 | return 1; | 884 | return 1; |
881 | } | 885 | } |
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c index 789e14eb09a5..ead68ac99191 100644 --- a/kernel/trace/trace_events.c +++ b/kernel/trace/trace_events.c | |||
@@ -481,7 +481,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
481 | 481 | ||
482 | trace_seq_init(s); | 482 | trace_seq_init(s); |
483 | 483 | ||
484 | filter_print_preds(call->preds, s); | 484 | filter_print_preds(call->preds, call->n_preds, s); |
485 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); | 485 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); |
486 | 486 | ||
487 | kfree(s); | 487 | kfree(s); |
@@ -516,7 +516,7 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
516 | } | 516 | } |
517 | 517 | ||
518 | if (pred->clear) { | 518 | if (pred->clear) { |
519 | filter_free_preds(call); | 519 | filter_disable_preds(call); |
520 | filter_free_pred(pred); | 520 | filter_free_pred(pred); |
521 | return cnt; | 521 | return cnt; |
522 | } | 522 | } |
@@ -527,6 +527,8 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt, | |||
527 | return err; | 527 | return err; |
528 | } | 528 | } |
529 | 529 | ||
530 | filter_free_pred(pred); | ||
531 | |||
530 | *ppos += cnt; | 532 | *ppos += cnt; |
531 | 533 | ||
532 | return cnt; | 534 | return cnt; |
@@ -549,7 +551,7 @@ subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt, | |||
549 | 551 | ||
550 | trace_seq_init(s); | 552 | trace_seq_init(s); |
551 | 553 | ||
552 | filter_print_preds(system->preds, s); | 554 | filter_print_preds(system->preds, system->n_preds, s); |
553 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); | 555 | r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); |
554 | 556 | ||
555 | kfree(s); | 557 | kfree(s); |
@@ -712,6 +714,7 @@ event_subsystem_dir(const char *name, struct dentry *d_events) | |||
712 | list_add(&system->list, &event_subsystems); | 714 | list_add(&system->list, &event_subsystems); |
713 | 715 | ||
714 | system->preds = NULL; | 716 | system->preds = NULL; |
717 | system->n_preds = 0; | ||
715 | 718 | ||
716 | entry = debugfs_create_file("filter", 0644, system->entry, system, | 719 | entry = debugfs_create_file("filter", 0644, system->entry, system, |
717 | &ftrace_subsystem_filter_fops); | 720 | &ftrace_subsystem_filter_fops); |
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c index 9f8ecca34a59..de42dad42a88 100644 --- a/kernel/trace/trace_events_filter.c +++ b/kernel/trace/trace_events_filter.c | |||
@@ -82,25 +82,27 @@ static int filter_pred_string(struct filter_pred *pred, void *event) | |||
82 | return match; | 82 | return match; |
83 | } | 83 | } |
84 | 84 | ||
85 | static int filter_pred_none(struct filter_pred *pred, void *event) | ||
86 | { | ||
87 | return 0; | ||
88 | } | ||
89 | |||
85 | /* return 1 if event matches, 0 otherwise (discard) */ | 90 | /* return 1 if event matches, 0 otherwise (discard) */ |
86 | int filter_match_preds(struct ftrace_event_call *call, void *rec) | 91 | int filter_match_preds(struct ftrace_event_call *call, void *rec) |
87 | { | 92 | { |
88 | int i, matched, and_failed = 0; | 93 | int i, matched, and_failed = 0; |
89 | struct filter_pred *pred; | 94 | struct filter_pred *pred; |
90 | 95 | ||
91 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 96 | for (i = 0; i < call->n_preds; i++) { |
92 | if (call->preds[i]) { | 97 | pred = call->preds[i]; |
93 | pred = call->preds[i]; | 98 | if (and_failed && !pred->or) |
94 | if (and_failed && !pred->or) | 99 | continue; |
95 | continue; | 100 | matched = pred->fn(pred, rec); |
96 | matched = pred->fn(pred, rec); | 101 | if (!matched && !pred->or) { |
97 | if (!matched && !pred->or) { | 102 | and_failed = 1; |
98 | and_failed = 1; | 103 | continue; |
99 | continue; | 104 | } else if (matched && pred->or) |
100 | } else if (matched && pred->or) | 105 | return 1; |
101 | return 1; | ||
102 | } else | ||
103 | break; | ||
104 | } | 106 | } |
105 | 107 | ||
106 | if (and_failed) | 108 | if (and_failed) |
@@ -109,31 +111,29 @@ int filter_match_preds(struct ftrace_event_call *call, void *rec) | |||
109 | return 1; | 111 | return 1; |
110 | } | 112 | } |
111 | 113 | ||
112 | void filter_print_preds(struct filter_pred **preds, struct trace_seq *s) | 114 | void filter_print_preds(struct filter_pred **preds, int n_preds, |
115 | struct trace_seq *s) | ||
113 | { | 116 | { |
114 | char *field_name; | 117 | char *field_name; |
115 | struct filter_pred *pred; | 118 | struct filter_pred *pred; |
116 | int i; | 119 | int i; |
117 | 120 | ||
118 | if (!preds) { | 121 | if (!n_preds) { |
119 | trace_seq_printf(s, "none\n"); | 122 | trace_seq_printf(s, "none\n"); |
120 | return; | 123 | return; |
121 | } | 124 | } |
122 | 125 | ||
123 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 126 | for (i = 0; i < n_preds; i++) { |
124 | if (preds[i]) { | 127 | pred = preds[i]; |
125 | pred = preds[i]; | 128 | field_name = pred->field_name; |
126 | field_name = pred->field_name; | 129 | if (i) |
127 | if (i) | 130 | trace_seq_printf(s, pred->or ? "|| " : "&& "); |
128 | trace_seq_printf(s, pred->or ? "|| " : "&& "); | 131 | trace_seq_printf(s, "%s ", field_name); |
129 | trace_seq_printf(s, "%s ", field_name); | 132 | trace_seq_printf(s, pred->not ? "!= " : "== "); |
130 | trace_seq_printf(s, pred->not ? "!= " : "== "); | 133 | if (pred->str_len) |
131 | if (pred->str_val) | 134 | trace_seq_printf(s, "%s\n", pred->str_val); |
132 | trace_seq_printf(s, "%s\n", pred->str_val); | 135 | else |
133 | else | 136 | trace_seq_printf(s, "%llu\n", pred->val); |
134 | trace_seq_printf(s, "%llu\n", pred->val); | ||
135 | } else | ||
136 | break; | ||
137 | } | 137 | } |
138 | } | 138 | } |
139 | 139 | ||
@@ -156,20 +156,69 @@ void filter_free_pred(struct filter_pred *pred) | |||
156 | return; | 156 | return; |
157 | 157 | ||
158 | kfree(pred->field_name); | 158 | kfree(pred->field_name); |
159 | kfree(pred->str_val); | ||
160 | kfree(pred); | 159 | kfree(pred); |
161 | } | 160 | } |
162 | 161 | ||
163 | void filter_free_preds(struct ftrace_event_call *call) | 162 | static void filter_clear_pred(struct filter_pred *pred) |
163 | { | ||
164 | kfree(pred->field_name); | ||
165 | pred->field_name = NULL; | ||
166 | pred->str_len = 0; | ||
167 | } | ||
168 | |||
169 | static int filter_set_pred(struct filter_pred *dest, | ||
170 | struct filter_pred *src, | ||
171 | filter_pred_fn_t fn) | ||
172 | { | ||
173 | *dest = *src; | ||
174 | dest->field_name = kstrdup(src->field_name, GFP_KERNEL); | ||
175 | if (!dest->field_name) | ||
176 | return -ENOMEM; | ||
177 | dest->fn = fn; | ||
178 | |||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | void filter_disable_preds(struct ftrace_event_call *call) | ||
164 | { | 183 | { |
165 | int i; | 184 | int i; |
166 | 185 | ||
167 | if (call->preds) { | 186 | call->n_preds = 0; |
168 | for (i = 0; i < MAX_FILTER_PRED; i++) | 187 | |
188 | for (i = 0; i < MAX_FILTER_PRED; i++) | ||
189 | call->preds[i]->fn = filter_pred_none; | ||
190 | } | ||
191 | |||
192 | int init_preds(struct ftrace_event_call *call) | ||
193 | { | ||
194 | struct filter_pred *pred; | ||
195 | int i; | ||
196 | |||
197 | call->n_preds = 0; | ||
198 | |||
199 | call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL); | ||
200 | if (!call->preds) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | for (i = 0; i < MAX_FILTER_PRED; i++) { | ||
204 | pred = kzalloc(sizeof(*pred), GFP_KERNEL); | ||
205 | if (!pred) | ||
206 | goto oom; | ||
207 | pred->fn = filter_pred_none; | ||
208 | call->preds[i] = pred; | ||
209 | } | ||
210 | |||
211 | return 0; | ||
212 | |||
213 | oom: | ||
214 | for (i = 0; i < MAX_FILTER_PRED; i++) { | ||
215 | if (call->preds[i]) | ||
169 | filter_free_pred(call->preds[i]); | 216 | filter_free_pred(call->preds[i]); |
170 | kfree(call->preds); | ||
171 | call->preds = NULL; | ||
172 | } | 217 | } |
218 | kfree(call->preds); | ||
219 | call->preds = NULL; | ||
220 | |||
221 | return -ENOMEM; | ||
173 | } | 222 | } |
174 | 223 | ||
175 | void filter_free_subsystem_preds(struct event_subsystem *system) | 224 | void filter_free_subsystem_preds(struct event_subsystem *system) |
@@ -177,11 +226,12 @@ void filter_free_subsystem_preds(struct event_subsystem *system) | |||
177 | struct ftrace_event_call *call = __start_ftrace_events; | 226 | struct ftrace_event_call *call = __start_ftrace_events; |
178 | int i; | 227 | int i; |
179 | 228 | ||
180 | if (system->preds) { | 229 | if (system->n_preds) { |
181 | for (i = 0; i < MAX_FILTER_PRED; i++) | 230 | for (i = 0; i < system->n_preds; i++) |
182 | filter_free_pred(system->preds[i]); | 231 | filter_free_pred(system->preds[i]); |
183 | kfree(system->preds); | 232 | kfree(system->preds); |
184 | system->preds = NULL; | 233 | system->preds = NULL; |
234 | system->n_preds = 0; | ||
185 | } | 235 | } |
186 | 236 | ||
187 | events_for_each(call) { | 237 | events_for_each(call) { |
@@ -189,33 +239,31 @@ void filter_free_subsystem_preds(struct event_subsystem *system) | |||
189 | continue; | 239 | continue; |
190 | 240 | ||
191 | if (!strcmp(call->system, system->name)) | 241 | if (!strcmp(call->system, system->name)) |
192 | filter_free_preds(call); | 242 | filter_disable_preds(call); |
193 | } | 243 | } |
194 | } | 244 | } |
195 | 245 | ||
196 | static int __filter_add_pred(struct ftrace_event_call *call, | 246 | static int __filter_add_pred(struct ftrace_event_call *call, |
197 | struct filter_pred *pred) | 247 | struct filter_pred *pred, |
248 | filter_pred_fn_t fn) | ||
198 | { | 249 | { |
199 | int i; | 250 | int idx, err; |
200 | 251 | ||
201 | if (call->preds && !pred->compound) | 252 | if (call->n_preds && !pred->compound) |
202 | filter_free_preds(call); | 253 | filter_disable_preds(call); |
203 | 254 | ||
204 | if (!call->preds) { | 255 | if (call->n_preds == MAX_FILTER_PRED) |
205 | call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), | 256 | return -ENOSPC; |
206 | GFP_KERNEL); | ||
207 | if (!call->preds) | ||
208 | return -ENOMEM; | ||
209 | } | ||
210 | 257 | ||
211 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 258 | idx = call->n_preds; |
212 | if (!call->preds[i]) { | 259 | filter_clear_pred(call->preds[idx]); |
213 | call->preds[i] = pred; | 260 | err = filter_set_pred(call->preds[idx], pred, fn); |
214 | return 0; | 261 | if (err) |
215 | } | 262 | return err; |
216 | } | 263 | |
264 | call->n_preds++; | ||
217 | 265 | ||
218 | return -ENOSPC; | 266 | return 0; |
219 | } | 267 | } |
220 | 268 | ||
221 | static int is_string_field(const char *type) | 269 | static int is_string_field(const char *type) |
@@ -229,98 +277,66 @@ static int is_string_field(const char *type) | |||
229 | int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred) | 277 | int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred) |
230 | { | 278 | { |
231 | struct ftrace_event_field *field; | 279 | struct ftrace_event_field *field; |
280 | filter_pred_fn_t fn; | ||
232 | 281 | ||
233 | field = find_event_field(call, pred->field_name); | 282 | field = find_event_field(call, pred->field_name); |
234 | if (!field) | 283 | if (!field) |
235 | return -EINVAL; | 284 | return -EINVAL; |
236 | 285 | ||
286 | pred->fn = filter_pred_none; | ||
237 | pred->offset = field->offset; | 287 | pred->offset = field->offset; |
238 | 288 | ||
239 | if (is_string_field(field->type)) { | 289 | if (is_string_field(field->type)) { |
240 | if (!pred->str_val) | 290 | if (!pred->str_len) |
241 | return -EINVAL; | 291 | return -EINVAL; |
242 | pred->fn = filter_pred_string; | 292 | fn = filter_pred_string; |
243 | pred->str_len = field->size; | 293 | pred->str_len = field->size; |
244 | return __filter_add_pred(call, pred); | 294 | return __filter_add_pred(call, pred, fn); |
245 | } else { | 295 | } else { |
246 | if (pred->str_val) | 296 | if (pred->str_len) |
247 | return -EINVAL; | 297 | return -EINVAL; |
248 | } | 298 | } |
249 | 299 | ||
250 | switch (field->size) { | 300 | switch (field->size) { |
251 | case 8: | 301 | case 8: |
252 | pred->fn = filter_pred_64; | 302 | fn = filter_pred_64; |
253 | break; | 303 | break; |
254 | case 4: | 304 | case 4: |
255 | pred->fn = filter_pred_32; | 305 | fn = filter_pred_32; |
256 | break; | 306 | break; |
257 | case 2: | 307 | case 2: |
258 | pred->fn = filter_pred_16; | 308 | fn = filter_pred_16; |
259 | break; | 309 | break; |
260 | case 1: | 310 | case 1: |
261 | pred->fn = filter_pred_8; | 311 | fn = filter_pred_8; |
262 | break; | 312 | break; |
263 | default: | 313 | default: |
264 | return -EINVAL; | 314 | return -EINVAL; |
265 | } | 315 | } |
266 | 316 | ||
267 | return __filter_add_pred(call, pred); | 317 | return __filter_add_pred(call, pred, fn); |
268 | } | ||
269 | |||
270 | static struct filter_pred *copy_pred(struct filter_pred *pred) | ||
271 | { | ||
272 | struct filter_pred *new_pred = kmalloc(sizeof(*pred), GFP_KERNEL); | ||
273 | if (!new_pred) | ||
274 | return NULL; | ||
275 | |||
276 | memcpy(new_pred, pred, sizeof(*pred)); | ||
277 | |||
278 | if (pred->field_name) { | ||
279 | new_pred->field_name = kstrdup(pred->field_name, GFP_KERNEL); | ||
280 | if (!new_pred->field_name) { | ||
281 | kfree(new_pred); | ||
282 | return NULL; | ||
283 | } | ||
284 | } | ||
285 | |||
286 | if (pred->str_val) { | ||
287 | new_pred->str_val = kstrdup(pred->str_val, GFP_KERNEL); | ||
288 | if (!new_pred->str_val) { | ||
289 | filter_free_pred(new_pred); | ||
290 | return NULL; | ||
291 | } | ||
292 | } | ||
293 | |||
294 | return new_pred; | ||
295 | } | 318 | } |
296 | 319 | ||
297 | int filter_add_subsystem_pred(struct event_subsystem *system, | 320 | int filter_add_subsystem_pred(struct event_subsystem *system, |
298 | struct filter_pred *pred) | 321 | struct filter_pred *pred) |
299 | { | 322 | { |
300 | struct ftrace_event_call *call = __start_ftrace_events; | 323 | struct ftrace_event_call *call = __start_ftrace_events; |
301 | struct filter_pred *event_pred; | ||
302 | int i; | ||
303 | 324 | ||
304 | if (system->preds && !pred->compound) | 325 | if (system->n_preds && !pred->compound) |
305 | filter_free_subsystem_preds(system); | 326 | filter_free_subsystem_preds(system); |
306 | 327 | ||
307 | if (!system->preds) { | 328 | if (!system->n_preds) { |
308 | system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), | 329 | system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), |
309 | GFP_KERNEL); | 330 | GFP_KERNEL); |
310 | if (!system->preds) | 331 | if (!system->preds) |
311 | return -ENOMEM; | 332 | return -ENOMEM; |
312 | } | 333 | } |
313 | 334 | ||
314 | for (i = 0; i < MAX_FILTER_PRED; i++) { | 335 | if (system->n_preds == MAX_FILTER_PRED) |
315 | if (!system->preds[i]) { | ||
316 | system->preds[i] = pred; | ||
317 | break; | ||
318 | } | ||
319 | } | ||
320 | |||
321 | if (i == MAX_FILTER_PRED) | ||
322 | return -ENOSPC; | 336 | return -ENOSPC; |
323 | 337 | ||
338 | system->preds[system->n_preds] = pred; | ||
339 | |||
324 | events_for_each(call) { | 340 | events_for_each(call) { |
325 | int err; | 341 | int err; |
326 | 342 | ||
@@ -333,22 +349,16 @@ int filter_add_subsystem_pred(struct event_subsystem *system, | |||
333 | if (!find_event_field(call, pred->field_name)) | 349 | if (!find_event_field(call, pred->field_name)) |
334 | continue; | 350 | continue; |
335 | 351 | ||
336 | event_pred = copy_pred(pred); | 352 | err = filter_add_pred(call, pred); |
337 | if (!event_pred) | 353 | if (err == -ENOMEM) { |
338 | goto oom; | 354 | system->preds[system->n_preds] = NULL; |
339 | 355 | return err; | |
340 | err = filter_add_pred(call, event_pred); | 356 | } |
341 | if (err) | ||
342 | filter_free_pred(event_pred); | ||
343 | if (err == -ENOMEM) | ||
344 | goto oom; | ||
345 | } | 357 | } |
346 | 358 | ||
347 | return 0; | 359 | system->n_preds++; |
348 | 360 | ||
349 | oom: | 361 | return 0; |
350 | system->preds[i] = NULL; | ||
351 | return -ENOMEM; | ||
352 | } | 362 | } |
353 | 363 | ||
354 | int filter_parse(char **pbuf, struct filter_pred *pred) | 364 | int filter_parse(char **pbuf, struct filter_pred *pred) |
@@ -410,7 +420,8 @@ int filter_parse(char **pbuf, struct filter_pred *pred) | |||
410 | } | 420 | } |
411 | } | 421 | } |
412 | 422 | ||
413 | if (!val_str) { | 423 | if (!val_str || !strlen(val_str) |
424 | || strlen(val_str) >= MAX_FILTER_STR_VAL) { | ||
414 | pred->field_name = NULL; | 425 | pred->field_name = NULL; |
415 | return -EINVAL; | 426 | return -EINVAL; |
416 | } | 427 | } |
@@ -419,11 +430,12 @@ int filter_parse(char **pbuf, struct filter_pred *pred) | |||
419 | if (!pred->field_name) | 430 | if (!pred->field_name) |
420 | return -ENOMEM; | 431 | return -ENOMEM; |
421 | 432 | ||
433 | pred->str_len = 0; | ||
422 | pred->val = simple_strtoull(val_str, &tmp, 0); | 434 | pred->val = simple_strtoull(val_str, &tmp, 0); |
423 | if (tmp == val_str) { | 435 | if (tmp == val_str) { |
424 | pred->str_val = kstrdup(val_str, GFP_KERNEL); | 436 | strncpy(pred->str_val, val_str, MAX_FILTER_STR_VAL); |
425 | if (!pred->str_val) | 437 | pred->str_len = strlen(val_str); |
426 | return -ENOMEM; | 438 | pred->str_val[pred->str_len] = '\0'; |
427 | } else if (*tmp != '\0') | 439 | } else if (*tmp != '\0') |
428 | return -EINVAL; | 440 | return -EINVAL; |
429 | 441 | ||
diff --git a/kernel/trace/trace_events_stage_2.h b/kernel/trace/trace_events_stage_2.h index 02fb710193ed..59cfd7dfe68d 100644 --- a/kernel/trace/trace_events_stage_2.h +++ b/kernel/trace/trace_events_stage_2.h | |||
@@ -140,6 +140,7 @@ ftrace_format_##call(struct trace_seq *s) \ | |||
140 | 140 | ||
141 | #undef __array | 141 | #undef __array |
142 | #define __array(type, item, len) \ | 142 | #define __array(type, item, len) \ |
143 | BUILD_BUG_ON(len > MAX_FILTER_STR_VAL); \ | ||
143 | ret = trace_define_field(event_call, #type "[" #len "]", #item, \ | 144 | ret = trace_define_field(event_call, #type "[" #len "]", #item, \ |
144 | offsetof(typeof(field), item), \ | 145 | offsetof(typeof(field), item), \ |
145 | sizeof(field.item)); \ | 146 | sizeof(field.item)); \ |
diff --git a/kernel/trace/trace_events_stage_3.h b/kernel/trace/trace_events_stage_3.h index b2b298269eb0..5bb1b7ffbdb6 100644 --- a/kernel/trace/trace_events_stage_3.h +++ b/kernel/trace/trace_events_stage_3.h | |||
@@ -255,6 +255,7 @@ static int ftrace_raw_init_event_##call(void) \ | |||
255 | return -ENODEV; \ | 255 | return -ENODEV; \ |
256 | event_##call.id = id; \ | 256 | event_##call.id = id; \ |
257 | INIT_LIST_HEAD(&event_##call.fields); \ | 257 | INIT_LIST_HEAD(&event_##call.fields); \ |
258 | init_preds(&event_##call); \ | ||
258 | return 0; \ | 259 | return 0; \ |
259 | } \ | 260 | } \ |
260 | \ | 261 | \ |
diff --git a/kernel/trace/trace_export.c b/kernel/trace/trace_export.c index 77c494f5e1d6..48fc02fe73a0 100644 --- a/kernel/trace/trace_export.c +++ b/kernel/trace/trace_export.c | |||
@@ -122,6 +122,7 @@ __attribute__((section("_ftrace_events"))) event_##call = { \ | |||
122 | static int ftrace_raw_init_event_##call(void) \ | 122 | static int ftrace_raw_init_event_##call(void) \ |
123 | { \ | 123 | { \ |
124 | INIT_LIST_HEAD(&event_##call.fields); \ | 124 | INIT_LIST_HEAD(&event_##call.fields); \ |
125 | init_preds(&event_##call); \ | ||
125 | return 0; \ | 126 | return 0; \ |
126 | } \ | 127 | } \ |
127 | 128 | ||