aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/trace
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-05-02 20:48:52 -0400
committerIngo Molnar <mingo@elte.hu>2009-05-07 04:05:57 -0400
commite8808c1019b048a43686dbd25c188a035842c2e2 (patch)
tree350eefee96e540ee855a6aefc64a17af25486234 /kernel/trace
parent8ae79a138e88aceeeb07077bff2883245fb7c218 (diff)
tracing/filters: support for filters of dynamic sized arrays
Currently the filtering infrastructure supports well the numeric types and fixed sized array types. But the recently added __string() field uses a specific indirect offset mechanism which requires a specific predicate. Until now it wasn't supported. This patch adds this support and implies very few changes, only a new predicate is needed, the management of this specific field can be done through the usual string helpers in the filtering infrastructure. [ Impact: support all kinds of strings in the tracing filters ] Cc: Tom Zanussi <tzanussi@gmail.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Li Zefan <lizf@cn.fujitsu.com> Cc: Zhaolei <zhaolei@cn.fujitsu.com> Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Diffstat (limited to 'kernel/trace')
-rw-r--r--kernel/trace/trace_events_filter.c44
1 files changed, 41 insertions, 3 deletions
diff --git a/kernel/trace/trace_events_filter.c b/kernel/trace/trace_events_filter.c
index 7ac691085276..01c76eb3e168 100644
--- a/kernel/trace/trace_events_filter.c
+++ b/kernel/trace/trace_events_filter.c
@@ -151,6 +151,7 @@ static int filter_pred_or(struct filter_pred *pred __attribute((unused)),
151 return val1 || val2; 151 return val1 || val2;
152} 152}
153 153
154/* Filter predicate for fixed sized arrays of characters */
154static int filter_pred_string(struct filter_pred *pred, void *event, 155static int filter_pred_string(struct filter_pred *pred, void *event,
155 int val1, int val2) 156 int val1, int val2)
156{ 157{
@@ -164,6 +165,30 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
164 return match; 165 return match;
165} 166}
166 167
168/*
169 * Filter predicate for dynamic sized arrays of characters.
170 * These are implemented through a list of strings at the end
171 * of the entry.
172 * Also each of these strings have a field in the entry which
173 * contains its offset from the beginning of the entry.
174 * We have then first to get this field, dereference it
175 * and add it to the address of the entry, and at last we have
176 * the address of the string.
177 */
178static int filter_pred_strloc(struct filter_pred *pred, void *event,
179 int val1, int val2)
180{
181 int str_loc = *(int *)(event + pred->offset);
182 char *addr = (char *)(event + str_loc);
183 int cmp, match;
184
185 cmp = strncmp(addr, pred->str_val, pred->str_len);
186
187 match = (!cmp) ^ pred->not;
188
189 return match;
190}
191
167static int filter_pred_none(struct filter_pred *pred, void *event, 192static int filter_pred_none(struct filter_pred *pred, void *event,
168 int val1, int val2) 193 int val1, int val2)
169{ 194{
@@ -446,10 +471,18 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
446 return 0; 471 return 0;
447} 472}
448 473
474enum {
475 FILTER_STATIC_STRING = 1,
476 FILTER_DYN_STRING
477};
478
449static int is_string_field(const char *type) 479static int is_string_field(const char *type)
450{ 480{
451 if (strchr(type, '[') && strstr(type, "char")) 481 if (strchr(type, '[') && strstr(type, "char"))
452 return 1; 482 return FILTER_STATIC_STRING;
483
484 if (!strcmp(type, "__str_loc"))
485 return FILTER_DYN_STRING;
453 486
454 return 0; 487 return 0;
455} 488}
@@ -512,6 +545,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
512 struct ftrace_event_field *field; 545 struct ftrace_event_field *field;
513 filter_pred_fn_t fn; 546 filter_pred_fn_t fn;
514 unsigned long long val; 547 unsigned long long val;
548 int string_type;
515 549
516 pred->fn = filter_pred_none; 550 pred->fn = filter_pred_none;
517 551
@@ -536,8 +570,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
536 return -EINVAL; 570 return -EINVAL;
537 } 571 }
538 572
539 if (is_string_field(field->type)) { 573 string_type = is_string_field(field->type);
540 fn = filter_pred_string; 574 if (string_type) {
575 if (string_type == FILTER_STATIC_STRING)
576 fn = filter_pred_string;
577 else
578 fn = filter_pred_strloc;
541 pred->str_len = field->size; 579 pred->str_len = field->size;
542 if (pred->op == OP_NE) 580 if (pred->op == OP_NE)
543 pred->not = 1; 581 pred->not = 1;