aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace/trace.h
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.h
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.h')
-rw-r--r--kernel/trace/trace.h66
1 files changed, 52 insertions, 14 deletions
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 866d0108fd2f..7736fe8c1b76 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -735,6 +735,7 @@ struct ftrace_event_field {
735struct event_filter { 735struct event_filter {
736 int n_preds; 736 int n_preds;
737 struct filter_pred **preds; 737 struct filter_pred **preds;
738 char *filter_string;
738}; 739};
739 740
740struct event_subsystem { 741struct event_subsystem {
@@ -746,7 +747,8 @@ struct event_subsystem {
746 747
747struct filter_pred; 748struct filter_pred;
748 749
749typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event); 750typedef int (*filter_pred_fn_t) (struct filter_pred *pred, void *event,
751 int val1, int val2);
750 752
751struct filter_pred { 753struct filter_pred {
752 filter_pred_fn_t fn; 754 filter_pred_fn_t fn;
@@ -756,23 +758,18 @@ struct filter_pred {
756 char *field_name; 758 char *field_name;
757 int offset; 759 int offset;
758 int not; 760 int not;
759 int or; 761 int op;
760 int compound; 762 int pop_n;
761 int clear;
762}; 763};
763 764
764extern void filter_free_pred(struct filter_pred *pred); 765extern void print_event_filter(struct ftrace_event_call *call,
765extern void filter_print_preds(struct ftrace_event_call *call,
766 struct trace_seq *s); 766 struct trace_seq *s);
767extern int filter_parse(char **pbuf, struct filter_pred *pred); 767extern int apply_event_filter(struct ftrace_event_call *call,
768extern int filter_add_pred(struct ftrace_event_call *call, 768 char *filter_string);
769 struct filter_pred *pred); 769extern int apply_subsystem_event_filter(struct event_subsystem *system,
770extern void filter_disable_preds(struct ftrace_event_call *call); 770 char *filter_string);
771extern void filter_free_subsystem_preds(struct event_subsystem *system); 771extern void print_subsystem_event_filter(struct event_subsystem *system,
772extern void filter_print_subsystem_preds(struct event_subsystem *system,
773 struct trace_seq *s); 772 struct trace_seq *s);
774extern int filter_add_subsystem_pred(struct event_subsystem *system,
775 struct filter_pred *pred);
776 773
777static inline int 774static inline int
778filter_check_discard(struct ftrace_event_call *call, void *rec, 775filter_check_discard(struct ftrace_event_call *call, void *rec,
@@ -787,6 +784,47 @@ filter_check_discard(struct ftrace_event_call *call, void *rec,
787 return 0; 784 return 0;
788} 785}
789 786
787#define DEFINE_COMPARISON_PRED(type) \
788static int filter_pred_##type(struct filter_pred *pred, void *event, \
789 int val1, int val2) \
790{ \
791 type *addr = (type *)(event + pred->offset); \
792 type val = (type)pred->val; \
793 int match = 0; \
794 \
795 switch (pred->op) { \
796 case OP_LT: \
797 match = (*addr < val); \
798 break; \
799 case OP_LE: \
800 match = (*addr <= val); \
801 break; \
802 case OP_GT: \
803 match = (*addr > val); \
804 break; \
805 case OP_GE: \
806 match = (*addr >= val); \
807 break; \
808 default: \
809 break; \
810 } \
811 \
812 return match; \
813}
814
815#define DEFINE_EQUALITY_PRED(size) \
816static int filter_pred_##size(struct filter_pred *pred, void *event, \
817 int val1, int val2) \
818{ \
819 u##size *addr = (u##size *)(event + pred->offset); \
820 u##size val = (u##size)pred->val; \
821 int match; \
822 \
823 match = (val == *addr) ^ pred->not; \
824 \
825 return match; \
826}
827
790extern struct list_head ftrace_events; 828extern struct list_head ftrace_events;
791 829
792extern const char *__start___trace_bprintk_fmt[]; 830extern const char *__start___trace_bprintk_fmt[];