2 * trace_events_filter - generic event filtering
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 * Copyright (C) 2009 Tom Zanussi <tzanussi@gmail.com>
21 #include <linux/debugfs.h>
22 #include <linux/uaccess.h>
23 #include <linux/module.h>
24 #include <linux/ctype.h>
28 static int filter_pred_64(struct filter_pred *pred, void *event)
30 u64 *addr = (u64 *)(event + pred->offset);
31 u64 val = (u64)pred->val;
34 match = (val == *addr) ^ pred->not;
39 static int filter_pred_32(struct filter_pred *pred, void *event)
41 u32 *addr = (u32 *)(event + pred->offset);
42 u32 val = (u32)pred->val;
45 match = (val == *addr) ^ pred->not;
50 static int filter_pred_16(struct filter_pred *pred, void *event)
52 u16 *addr = (u16 *)(event + pred->offset);
53 u16 val = (u16)pred->val;
56 match = (val == *addr) ^ pred->not;
61 static int filter_pred_8(struct filter_pred *pred, void *event)
63 u8 *addr = (u8 *)(event + pred->offset);
64 u8 val = (u8)pred->val;
67 match = (val == *addr) ^ pred->not;
72 static int filter_pred_string(struct filter_pred *pred, void *event)
74 char *addr = (char *)(event + pred->offset);
77 cmp = strncmp(addr, pred->str_val, pred->str_len);
79 match = (!cmp) ^ pred->not;
84 /* return 1 if event matches, 0 otherwise (discard) */
85 int filter_match_preds(struct ftrace_event_call *call, void *rec)
87 int i, matched, and_failed = 0;
88 struct filter_pred *pred;
90 for (i = 0; i < MAX_FILTER_PRED; i++) {
92 pred = call->preds[i];
93 if (and_failed && !pred->or)
95 matched = pred->fn(pred, rec);
96 if (!matched && !pred->or) {
99 } else if (matched && pred->or)
111 int filter_print_preds(struct filter_pred **preds, char *buf)
113 ssize_t this_len = 0;
115 struct filter_pred *pred;
119 this_len += sprintf(buf + this_len, "none\n");
123 for (i = 0; i < MAX_FILTER_PRED; i++) {
126 field_name = pred->field_name;
128 this_len += sprintf(buf + this_len,
129 pred->or ? "|| " : "&& ");
130 this_len += sprintf(buf + this_len,
132 this_len += sprintf(buf + this_len,
133 pred->not ? "!= " : "== ");
135 this_len += sprintf(buf + this_len,
136 "%s\n", pred->str_val);
138 this_len += sprintf(buf + this_len,
139 "%llu\n", pred->val);
147 static struct ftrace_event_field *
148 find_event_field(struct ftrace_event_call *call, char *name)
150 struct ftrace_event_field *field;
151 struct list_head *entry, *tmp;
153 list_for_each_safe(entry, tmp, &call->fields) {
154 field = list_entry(entry, struct ftrace_event_field, link);
155 if (!strcmp(field->name, name))
162 void filter_free_pred(struct filter_pred *pred)
167 kfree(pred->field_name);
168 kfree(pred->str_val);
172 void filter_free_preds(struct ftrace_event_call *call)
177 for (i = 0; i < MAX_FILTER_PRED; i++)
178 filter_free_pred(call->preds[i]);
184 static int __filter_add_pred(struct ftrace_event_call *call,
185 struct filter_pred *pred)
189 if (call->preds && !pred->compound)
190 filter_free_preds(call);
193 call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
199 for (i = 0; i < MAX_FILTER_PRED; i++) {
200 if (!call->preds[i]) {
201 call->preds[i] = pred;
209 static int is_string_field(const char *type)
211 if (strchr(type, '[') && strstr(type, "char"))
217 int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
219 struct ftrace_event_field *field;
221 field = find_event_field(call, pred->field_name);
225 pred->offset = field->offset;
227 if (is_string_field(field->type)) {
228 pred->fn = filter_pred_string;
229 pred->str_len = field->size;
230 return __filter_add_pred(call, pred);
233 switch (field->size) {
235 pred->fn = filter_pred_64;
238 pred->fn = filter_pred_32;
241 pred->fn = filter_pred_16;
244 pred->fn = filter_pred_8;
250 return __filter_add_pred(call, pred);
253 int filter_parse(char **pbuf, struct filter_pred *pred)
255 char *tmp, *tok, *val_str = NULL;
258 /* field ==/!= number, or/and field ==/!= number, number */
259 while ((tok = strsep(pbuf, " \n"))) {
261 if (!strcmp(tok, "0")) {
264 } else if (!strcmp(tok, "&&")) {
267 } else if (!strcmp(tok, "||")) {
271 pred->field_name = tok;
276 if (!pred->field_name)
277 pred->field_name = tok;
278 else if (!strcmp(tok, "!="))
280 else if (!strcmp(tok, "=="))
283 pred->field_name = NULL;
290 if (pred->compound) {
291 if (!strcmp(tok, "!="))
293 else if (!strcmp(tok, "=="))
296 pred->field_name = NULL;
312 pred->field_name = kstrdup(pred->field_name, GFP_KERNEL);
313 if (!pred->field_name)
316 pred->val = simple_strtoull(val_str, &tmp, 10);
317 if (tmp == val_str) {
318 pred->str_val = kstrdup(val_str, GFP_KERNEL);