aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--kernel/trace/trace.h14
-rw-r--r--kernel/trace/trace_events.c9
-rw-r--r--kernel/trace/trace_events_filter.c252
-rw-r--r--kernel/trace/trace_events_stage_2.h1
-rw-r--r--kernel/trace/trace_events_stage_3.h1
-rw-r--r--kernel/trace/trace_export.c1
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
839struct filter_pred; 842struct filter_pred;
840 843
@@ -843,7 +846,7 @@ typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event);
843struct filter_pred { 846struct 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
856int trace_define_field(struct ftrace_event_call *call, char *type, 859int trace_define_field(struct ftrace_event_call *call, char *type,
857 char *name, int offset, int size); 860 char *name, int offset, int size);
861extern int init_preds(struct ftrace_event_call *call);
858extern void filter_free_pred(struct filter_pred *pred); 862extern void filter_free_pred(struct filter_pred *pred);
859extern void filter_print_preds(struct filter_pred **preds, 863extern void filter_print_preds(struct filter_pred **preds, int n_preds,
860 struct trace_seq *s); 864 struct trace_seq *s);
861extern int filter_parse(char **pbuf, struct filter_pred *pred); 865extern int filter_parse(char **pbuf, struct filter_pred *pred);
862extern int filter_add_pred(struct ftrace_event_call *call, 866extern int filter_add_pred(struct ftrace_event_call *call,
863 struct filter_pred *pred); 867 struct filter_pred *pred);
864extern void filter_free_preds(struct ftrace_event_call *call); 868extern void filter_disable_preds(struct ftrace_event_call *call);
865extern int filter_match_preds(struct ftrace_event_call *call, void *rec); 869extern int filter_match_preds(struct ftrace_event_call *call, void *rec);
866extern void filter_free_subsystem_preds(struct event_subsystem *system); 870extern void filter_free_subsystem_preds(struct event_subsystem *system);
867extern int filter_add_subsystem_pred(struct event_subsystem *system, 871extern 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
85static 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) */
86int filter_match_preds(struct ftrace_event_call *call, void *rec) 91int 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
112void filter_print_preds(struct filter_pred **preds, struct trace_seq *s) 114void 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
163void filter_free_preds(struct ftrace_event_call *call) 162static 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
169static 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
182void 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
192int 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
213oom:
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
175void filter_free_subsystem_preds(struct event_subsystem *system) 224void 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
196static int __filter_add_pred(struct ftrace_event_call *call, 246static 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
221static int is_string_field(const char *type) 269static int is_string_field(const char *type)
@@ -229,98 +277,66 @@ static int is_string_field(const char *type)
229int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred) 277int 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
270static 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
297int filter_add_subsystem_pred(struct event_subsystem *system, 320int 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
349oom: 361 return 0;
350 system->preds[i] = NULL;
351 return -ENOMEM;
352} 362}
353 363
354int filter_parse(char **pbuf, struct filter_pred *pred) 364int 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 = { \
122static int ftrace_raw_init_event_##call(void) \ 122static 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