Skip to content

Commit

Permalink
tracing/filters: support for filters of dynamic sized arrays
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Frederic Weisbecker authored and Ingo Molnar committed May 7, 2009
1 parent 8ae79a1 commit e8808c1
Showing 1 changed file with 41 additions and 3 deletions.
44 changes: 41 additions & 3 deletions kernel/trace/trace_events_filter.c
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ static int filter_pred_or(struct filter_pred *pred __attribute((unused)),
return val1 || val2;
}

/* Filter predicate for fixed sized arrays of characters */
static int filter_pred_string(struct filter_pred *pred, void *event,
int val1, int val2)
{
Expand All @@ -164,6 +165,30 @@ static int filter_pred_string(struct filter_pred *pred, void *event,
return match;
}

/*
* Filter predicate for dynamic sized arrays of characters.
* These are implemented through a list of strings at the end
* of the entry.
* Also each of these strings have a field in the entry which
* contains its offset from the beginning of the entry.
* We have then first to get this field, dereference it
* and add it to the address of the entry, and at last we have
* the address of the string.
*/
static int filter_pred_strloc(struct filter_pred *pred, void *event,
int val1, int val2)
{
int str_loc = *(int *)(event + pred->offset);
char *addr = (char *)(event + str_loc);
int cmp, match;

cmp = strncmp(addr, pred->str_val, pred->str_len);

match = (!cmp) ^ pred->not;

return match;
}

static int filter_pred_none(struct filter_pred *pred, void *event,
int val1, int val2)
{
Expand Down Expand Up @@ -446,10 +471,18 @@ static int filter_add_pred_fn(struct filter_parse_state *ps,
return 0;
}

enum {
FILTER_STATIC_STRING = 1,
FILTER_DYN_STRING
};

static int is_string_field(const char *type)
{
if (strchr(type, '[') && strstr(type, "char"))
return 1;
return FILTER_STATIC_STRING;

if (!strcmp(type, "__str_loc"))
return FILTER_DYN_STRING;

return 0;
}
Expand Down Expand Up @@ -512,6 +545,7 @@ static int filter_add_pred(struct filter_parse_state *ps,
struct ftrace_event_field *field;
filter_pred_fn_t fn;
unsigned long long val;
int string_type;

pred->fn = filter_pred_none;

Expand All @@ -536,8 +570,12 @@ static int filter_add_pred(struct filter_parse_state *ps,
return -EINVAL;
}

if (is_string_field(field->type)) {
fn = filter_pred_string;
string_type = is_string_field(field->type);
if (string_type) {
if (string_type == FILTER_STATIC_STRING)
fn = filter_pred_string;
else
fn = filter_pred_strloc;
pred->str_len = field->size;
if (pred->op == OP_NE)
pred->not = 1;
Expand Down

0 comments on commit e8808c1

Please sign in to comment.