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>
27 #include "trace_output.h"
29 static int filter_pred_64(struct filter_pred *pred, void *event)
31 u64 *addr = (u64 *)(event + pred->offset);
32 u64 val = (u64)pred->val;
35 match = (val == *addr) ^ pred->not;
40 static int filter_pred_32(struct filter_pred *pred, void *event)
42 u32 *addr = (u32 *)(event + pred->offset);
43 u32 val = (u32)pred->val;
46 match = (val == *addr) ^ pred->not;
51 static int filter_pred_16(struct filter_pred *pred, void *event)
53 u16 *addr = (u16 *)(event + pred->offset);
54 u16 val = (u16)pred->val;
57 match = (val == *addr) ^ pred->not;
62 static int filter_pred_8(struct filter_pred *pred, void *event)
64 u8 *addr = (u8 *)(event + pred->offset);
65 u8 val = (u8)pred->val;
68 match = (val == *addr) ^ pred->not;
73 static int filter_pred_string(struct filter_pred *pred, void *event)
75 char *addr = (char *)(event + pred->offset);
78 cmp = strncmp(addr, pred->str_val, pred->str_len);
80 match = (!cmp) ^ pred->not;
85 static int filter_pred_none(struct filter_pred *pred, void *event)
90 /* return 1 if event matches, 0 otherwise (discard) */
91 int filter_match_preds(struct ftrace_event_call *call, void *rec)
93 int i, matched, and_failed = 0;
94 struct filter_pred *pred;
96 for (i = 0; i < call->n_preds; i++) {
97 pred = call->preds[i];
98 if (and_failed && !pred->or)
100 matched = pred->fn(pred, rec);
101 if (!matched && !pred->or) {
104 } else if (matched && pred->or)
113 EXPORT_SYMBOL_GPL(filter_match_preds);
115 void filter_print_preds(struct filter_pred **preds, int n_preds,
119 struct filter_pred *pred;
123 trace_seq_printf(s, "none\n");
127 for (i = 0; i < n_preds; i++) {
129 field_name = pred->field_name;
131 trace_seq_printf(s, pred->or ? "|| " : "&& ");
132 trace_seq_printf(s, "%s ", field_name);
133 trace_seq_printf(s, pred->not ? "!= " : "== ");
135 trace_seq_printf(s, "%s\n", pred->str_val);
137 trace_seq_printf(s, "%llu\n", pred->val);
141 static struct ftrace_event_field *
142 find_event_field(struct ftrace_event_call *call, char *name)
144 struct ftrace_event_field *field;
146 list_for_each_entry(field, &call->fields, link) {
147 if (!strcmp(field->name, name))
154 void filter_free_pred(struct filter_pred *pred)
159 kfree(pred->field_name);
163 static void filter_clear_pred(struct filter_pred *pred)
165 kfree(pred->field_name);
166 pred->field_name = NULL;
170 static int filter_set_pred(struct filter_pred *dest,
171 struct filter_pred *src,
175 dest->field_name = kstrdup(src->field_name, GFP_KERNEL);
176 if (!dest->field_name)
183 void filter_disable_preds(struct ftrace_event_call *call)
189 for (i = 0; i < MAX_FILTER_PRED; i++)
190 call->preds[i]->fn = filter_pred_none;
193 int init_preds(struct ftrace_event_call *call)
195 struct filter_pred *pred;
200 call->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred), GFP_KERNEL);
204 for (i = 0; i < MAX_FILTER_PRED; i++) {
205 pred = kzalloc(sizeof(*pred), GFP_KERNEL);
208 pred->fn = filter_pred_none;
209 call->preds[i] = pred;
215 for (i = 0; i < MAX_FILTER_PRED; i++) {
217 filter_free_pred(call->preds[i]);
224 EXPORT_SYMBOL_GPL(init_preds);
226 void filter_free_subsystem_preds(struct event_subsystem *system)
228 struct ftrace_event_call *call;
231 if (system->n_preds) {
232 for (i = 0; i < system->n_preds; i++)
233 filter_free_pred(system->preds[i]);
234 kfree(system->preds);
235 system->preds = NULL;
239 list_for_each_entry(call, &ftrace_events, list) {
240 if (!call->define_fields)
243 if (!strcmp(call->system, system->name))
244 filter_disable_preds(call);
248 static int __filter_add_pred(struct ftrace_event_call *call,
249 struct filter_pred *pred,
254 if (call->n_preds && !pred->compound)
255 filter_disable_preds(call);
257 if (call->n_preds == MAX_FILTER_PRED)
261 filter_clear_pred(call->preds[idx]);
262 err = filter_set_pred(call->preds[idx], pred, fn);
271 static int is_string_field(const char *type)
273 if (strchr(type, '[') && strstr(type, "char"))
279 int filter_add_pred(struct ftrace_event_call *call, struct filter_pred *pred)
281 struct ftrace_event_field *field;
284 field = find_event_field(call, pred->field_name);
288 pred->fn = filter_pred_none;
289 pred->offset = field->offset;
291 if (is_string_field(field->type)) {
294 fn = filter_pred_string;
295 pred->str_len = field->size;
296 return __filter_add_pred(call, pred, fn);
302 switch (field->size) {
319 return __filter_add_pred(call, pred, fn);
322 int filter_add_subsystem_pred(struct event_subsystem *system,
323 struct filter_pred *pred)
325 struct ftrace_event_call *call;
327 if (system->n_preds && !pred->compound)
328 filter_free_subsystem_preds(system);
330 if (!system->n_preds) {
331 system->preds = kzalloc(MAX_FILTER_PRED * sizeof(pred),
337 if (system->n_preds == MAX_FILTER_PRED)
340 system->preds[system->n_preds] = pred;
342 list_for_each_entry(call, &ftrace_events, list) {
345 if (!call->define_fields)
348 if (strcmp(call->system, system->name))
351 if (!find_event_field(call, pred->field_name))
354 err = filter_add_pred(call, pred);
355 if (err == -ENOMEM) {
356 system->preds[system->n_preds] = NULL;
366 int filter_parse(char **pbuf, struct filter_pred *pred)
368 char *tmp, *tok, *val_str = NULL;
371 /* field ==/!= number, or/and field ==/!= number, number */
372 while ((tok = strsep(pbuf, " \n"))) {
374 if (!strcmp(tok, "0")) {
377 } else if (!strcmp(tok, "&&")) {
380 } else if (!strcmp(tok, "||")) {
384 pred->field_name = tok;
389 if (!pred->field_name)
390 pred->field_name = tok;
391 else if (!strcmp(tok, "!="))
393 else if (!strcmp(tok, "=="))
396 pred->field_name = NULL;
403 if (pred->compound) {
404 if (!strcmp(tok, "!="))
406 else if (!strcmp(tok, "=="))
409 pred->field_name = NULL;
425 if (!val_str || !strlen(val_str)
426 || strlen(val_str) >= MAX_FILTER_STR_VAL) {
427 pred->field_name = NULL;
431 pred->field_name = kstrdup(pred->field_name, GFP_KERNEL);
432 if (!pred->field_name)
436 pred->val = simple_strtoull(val_str, &tmp, 0);
437 if (tmp == val_str) {
438 strncpy(pred->str_val, val_str, MAX_FILTER_STR_VAL);
439 pred->str_len = strlen(val_str);
440 pred->str_val[pred->str_len] = '\0';
441 } else if (*tmp != '\0')