aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace_events.c
diff options
context:
space:
mode:
authorTom Zanussi <tzanussi@gmail.com>2009-04-28 04:04:59 -0400
committerIngo Molnar <mingo@elte.hu>2009-04-29 08:06:11 -0400
commit8b3725621074040d380664964ffbc40610aef8c6 (patch)
tree3a78292a08cc9c87653be2e42d084a7d7f5989bf /kernel/trace/trace_events.c
parenta118e4d1402f1349fe3d953493e4168a300a752d (diff)
tracing/filters: a better event parser
Replace the current event parser hack with a better one. Filters are no longer specified predicate by predicate, but all at once and can use parens and any of the following operators: numeric fields: ==, !=, <, <=, >, >= string fields: ==, != predicates can be combined with the logical operators: &&, || examples: "common_preempt_count > 4" > filter "((sig >= 10 && sig < 15) || sig == 17) && comm != bash" > filter If there was an error, the erroneous string along with an error message can be seen by looking at the filter e.g.: ((sig >= 10 && sig < 15) || dsig == 17) && comm != bash ^ parse_error: Field not found Currently the caret for an error always appears at the beginning of the filter; a real position should be used, but the error message should be useful even without it. To clear a filter, '0' can be written to the filter file. Filters can also be set or cleared for a complete subsystem by writing the same filter as would be written to an individual event to the filter file at the root of the subsytem. Note however, that if any event in the subsystem lacks a field specified in the filter being set, the set will fail and all filters in the subsytem are automatically cleared. This change from the previous version was made because using only the fields that happen to exist for a given event would most likely result in a meaningless filter. Because the logical operators are now implemented as predicates, the maximum number of predicates in a filter was increased from 8 to 16. [ Impact: add new, extended trace-filter implementation ] Signed-off-by: Tom Zanussi <tzanussi@gmail.com> Acked-by: Steven Rostedt <rostedt@goodmis.org> Cc: fweisbec@gmail.com Cc: Li Zefan <lizf@cn.fujitsu.com> LKML-Reference: <1240905899.6416.121.camel@tropicana> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'kernel/trace/trace_events.c')
-rw-r--r--kernel/trace/trace_events.c86
1 files changed, 35 insertions, 51 deletions
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index bbbea7479371..f789ca540fe1 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -492,7 +492,7 @@ event_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
492 492
493 trace_seq_init(s); 493 trace_seq_init(s);
494 494
495 filter_print_preds(call, s); 495 print_event_filter(call, s);
496 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); 496 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
497 497
498 kfree(s); 498 kfree(s);
@@ -505,40 +505,26 @@ event_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
505 loff_t *ppos) 505 loff_t *ppos)
506{ 506{
507 struct ftrace_event_call *call = filp->private_data; 507 struct ftrace_event_call *call = filp->private_data;
508 char buf[64], *pbuf = buf; 508 char *buf;
509 struct filter_pred *pred;
510 int err; 509 int err;
511 510
512 if (cnt >= sizeof(buf)) 511 if (cnt >= PAGE_SIZE)
513 return -EINVAL; 512 return -EINVAL;
514 513
515 if (copy_from_user(&buf, ubuf, cnt)) 514 buf = (char *)__get_free_page(GFP_TEMPORARY);
516 return -EFAULT; 515 if (!buf)
517 buf[cnt] = '\0';
518
519 pred = kzalloc(sizeof(*pred), GFP_KERNEL);
520 if (!pred)
521 return -ENOMEM; 516 return -ENOMEM;
522 517
523 err = filter_parse(&pbuf, pred); 518 if (copy_from_user(buf, ubuf, cnt)) {
524 if (err < 0) { 519 free_page((unsigned long) buf);
525 filter_free_pred(pred); 520 return -EFAULT;
526 return err;
527 }
528
529 if (pred->clear) {
530 filter_disable_preds(call);
531 filter_free_pred(pred);
532 return cnt;
533 } 521 }
522 buf[cnt] = '\0';
534 523
535 err = filter_add_pred(call, pred); 524 err = apply_event_filter(call, buf);
536 if (err < 0) { 525 free_page((unsigned long) buf);
537 filter_free_pred(pred); 526 if (err < 0)
538 return err; 527 return err;
539 }
540
541 filter_free_pred(pred);
542 528
543 *ppos += cnt; 529 *ppos += cnt;
544 530
@@ -562,7 +548,7 @@ subsystem_filter_read(struct file *filp, char __user *ubuf, size_t cnt,
562 548
563 trace_seq_init(s); 549 trace_seq_init(s);
564 550
565 filter_print_subsystem_preds(system, s); 551 print_subsystem_event_filter(system, s);
566 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len); 552 r = simple_read_from_buffer(ubuf, cnt, ppos, s->buffer, s->len);
567 553
568 kfree(s); 554 kfree(s);
@@ -575,38 +561,26 @@ subsystem_filter_write(struct file *filp, const char __user *ubuf, size_t cnt,
575 loff_t *ppos) 561 loff_t *ppos)
576{ 562{
577 struct event_subsystem *system = filp->private_data; 563 struct event_subsystem *system = filp->private_data;
578 char buf[64], *pbuf = buf; 564 char *buf;
579 struct filter_pred *pred;
580 int err; 565 int err;
581 566
582 if (cnt >= sizeof(buf)) 567 if (cnt >= PAGE_SIZE)
583 return -EINVAL; 568 return -EINVAL;
584 569
585 if (copy_from_user(&buf, ubuf, cnt)) 570 buf = (char *)__get_free_page(GFP_TEMPORARY);
586 return -EFAULT; 571 if (!buf)
587 buf[cnt] = '\0';
588
589 pred = kzalloc(sizeof(*pred), GFP_KERNEL);
590 if (!pred)
591 return -ENOMEM; 572 return -ENOMEM;
592 573
593 err = filter_parse(&pbuf, pred); 574 if (copy_from_user(buf, ubuf, cnt)) {
594 if (err < 0) { 575 free_page((unsigned long) buf);
595 filter_free_pred(pred); 576 return -EFAULT;
596 return err;
597 }
598
599 if (pred->clear) {
600 filter_free_subsystem_preds(system);
601 filter_free_pred(pred);
602 return cnt;
603 } 577 }
578 buf[cnt] = '\0';
604 579
605 err = filter_add_subsystem_pred(system, pred); 580 err = apply_subsystem_event_filter(system, buf);
606 if (err < 0) { 581 free_page((unsigned long) buf);
607 filter_free_pred(pred); 582 if (err < 0)
608 return err; 583 return err;
609 }
610 584
611 *ppos += cnt; 585 *ppos += cnt;
612 586
@@ -760,11 +734,21 @@ event_subsystem_dir(const char *name, struct dentry *d_events)
760 734
761 system->filter = NULL; 735 system->filter = NULL;
762 736
737 system->filter = kzalloc(sizeof(struct event_filter), GFP_KERNEL);
738 if (!system->filter) {
739 pr_warning("Could not allocate filter for subsystem "
740 "'%s'\n", name);
741 return system->entry;
742 }
743
763 entry = debugfs_create_file("filter", 0644, system->entry, system, 744 entry = debugfs_create_file("filter", 0644, system->entry, system,
764 &ftrace_subsystem_filter_fops); 745 &ftrace_subsystem_filter_fops);
765 if (!entry) 746 if (!entry) {
747 kfree(system->filter);
748 system->filter = NULL;
766 pr_warning("Could not create debugfs " 749 pr_warning("Could not create debugfs "
767 "'%s/filter' entry\n", name); 750 "'%s/filter' entry\n", name);
751 }
768 752
769 return system->entry; 753 return system->entry;
770} 754}