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 /* return 1 if event matches, 0 otherwise (discard) */
86 int filter_match_preds(struct ftrace_event_call
*call
, void *rec
)
88 int i
, matched
, and_failed
= 0;
89 struct filter_pred
*pred
;
91 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
93 pred
= call
->preds
[i
];
94 if (and_failed
&& !pred
->or)
96 matched
= pred
->fn(pred
, rec
);
97 if (!matched
&& !pred
->or) {
100 } else if (matched
&& pred
->or)
112 void filter_print_preds(struct filter_pred
**preds
, struct trace_seq
*s
)
115 struct filter_pred
*pred
;
119 trace_seq_printf(s
, "none\n");
123 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
126 field_name
= pred
->field_name
;
128 trace_seq_printf(s
, pred
->or ? "|| " : "&& ");
129 trace_seq_printf(s
, "%s ", field_name
);
130 trace_seq_printf(s
, pred
->not ? "!= " : "== ");
132 trace_seq_printf(s
, "%s\n", pred
->str_val
);
134 trace_seq_printf(s
, "%llu\n", pred
->val
);
140 static struct ftrace_event_field
*
141 find_event_field(struct ftrace_event_call
*call
, char *name
)
143 struct ftrace_event_field
*field
;
145 list_for_each_entry(field
, &call
->fields
, link
) {
146 if (!strcmp(field
->name
, name
))
153 void filter_free_pred(struct filter_pred
*pred
)
158 kfree(pred
->field_name
);
159 kfree(pred
->str_val
);
163 void filter_free_preds(struct ftrace_event_call
*call
)
168 for (i
= 0; i
< MAX_FILTER_PRED
; i
++)
169 filter_free_pred(call
->preds
[i
]);
175 void filter_free_subsystem_preds(struct event_subsystem
*system
)
177 struct ftrace_event_call
*call
= __start_ftrace_events
;
181 for (i
= 0; i
< MAX_FILTER_PRED
; i
++)
182 filter_free_pred(system
->preds
[i
]);
183 kfree(system
->preds
);
184 system
->preds
= NULL
;
187 events_for_each(call
) {
188 if (!call
->name
|| !call
->regfunc
)
191 if (!strcmp(call
->system
, system
->name
))
192 filter_free_preds(call
);
196 static int __filter_add_pred(struct ftrace_event_call
*call
,
197 struct filter_pred
*pred
)
201 if (call
->preds
&& !pred
->compound
)
202 filter_free_preds(call
);
205 call
->preds
= kzalloc(MAX_FILTER_PRED
* sizeof(pred
),
211 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
212 if (!call
->preds
[i
]) {
213 call
->preds
[i
] = pred
;
221 static int is_string_field(const char *type
)
223 if (strchr(type
, '[') && strstr(type
, "char"))
229 int filter_add_pred(struct ftrace_event_call
*call
, struct filter_pred
*pred
)
231 struct ftrace_event_field
*field
;
233 field
= find_event_field(call
, pred
->field_name
);
237 pred
->offset
= field
->offset
;
239 if (is_string_field(field
->type
)) {
240 pred
->fn
= filter_pred_string
;
241 pred
->str_len
= field
->size
;
242 return __filter_add_pred(call
, pred
);
245 switch (field
->size
) {
247 pred
->fn
= filter_pred_64
;
250 pred
->fn
= filter_pred_32
;
253 pred
->fn
= filter_pred_16
;
256 pred
->fn
= filter_pred_8
;
262 return __filter_add_pred(call
, pred
);
265 static struct filter_pred
*copy_pred(struct filter_pred
*pred
)
267 struct filter_pred
*new_pred
= kmalloc(sizeof(*pred
), GFP_KERNEL
);
271 memcpy(new_pred
, pred
, sizeof(*pred
));
273 if (pred
->field_name
) {
274 new_pred
->field_name
= kstrdup(pred
->field_name
, GFP_KERNEL
);
275 if (!new_pred
->field_name
) {
282 new_pred
->str_val
= kstrdup(pred
->str_val
, GFP_KERNEL
);
283 if (!new_pred
->str_val
) {
284 filter_free_pred(new_pred
);
292 int filter_add_subsystem_pred(struct event_subsystem
*system
,
293 struct filter_pred
*pred
)
295 struct ftrace_event_call
*call
= __start_ftrace_events
;
296 struct filter_pred
*event_pred
;
299 if (system
->preds
&& !pred
->compound
)
300 filter_free_subsystem_preds(system
);
302 if (!system
->preds
) {
303 system
->preds
= kzalloc(MAX_FILTER_PRED
* sizeof(pred
),
309 for (i
= 0; i
< MAX_FILTER_PRED
; i
++) {
310 if (!system
->preds
[i
]) {
311 system
->preds
[i
] = pred
;
316 if (i
== MAX_FILTER_PRED
)
319 events_for_each(call
) {
322 if (!call
->name
|| !call
->regfunc
)
325 if (strcmp(call
->system
, system
->name
))
328 if (!find_event_field(call
, pred
->field_name
))
331 event_pred
= copy_pred(pred
);
335 err
= filter_add_pred(call
, event_pred
);
337 filter_free_pred(event_pred
);
345 system
->preds
[i
] = NULL
;
349 int filter_parse(char **pbuf
, struct filter_pred
*pred
)
351 char *tmp
, *tok
, *val_str
= NULL
;
354 /* field ==/!= number, or/and field ==/!= number, number */
355 while ((tok
= strsep(pbuf
, " \n"))) {
357 if (!strcmp(tok
, "0")) {
360 } else if (!strcmp(tok
, "&&")) {
363 } else if (!strcmp(tok
, "||")) {
367 pred
->field_name
= tok
;
372 if (!pred
->field_name
)
373 pred
->field_name
= tok
;
374 else if (!strcmp(tok
, "!="))
376 else if (!strcmp(tok
, "=="))
379 pred
->field_name
= NULL
;
386 if (pred
->compound
) {
387 if (!strcmp(tok
, "!="))
389 else if (!strcmp(tok
, "=="))
392 pred
->field_name
= NULL
;
408 pred
->field_name
= kstrdup(pred
->field_name
, GFP_KERNEL
);
409 if (!pred
->field_name
)
412 pred
->val
= simple_strtoull(val_str
, &tmp
, 10);
413 if (tmp
== val_str
) {
414 pred
->str_val
= kstrdup(val_str
, GFP_KERNEL
);
This page took 0.051498 seconds and 5 git commands to generate.