Commit e12c09cf authored by Steven Rostedt (Red Hat)'s avatar Steven Rostedt (Red Hat) Committed by Steven Rostedt

tracing: Add NOT to filtering logic

Ted noticed that he could not filter on an event for a bit being cleared.
That's because the filtering logic only tests event fields with a limited
number of comparisons which, for bit logic, only include "&", which can
test if a bit is set, but there's no good way to see if a bit is clear.

This adds a way to do: !(field & 2048)

Which returns true if the bit is not set, and false otherwise.

Note, currently !(field1 == 10 && field2 == 15) is not supported.
That is, the 'not' only works for direct comparisons, not for the
AND and OR logic.

Link: http://lkml.kernel.org/r/20141202021912.GA29096@thunk.org
Link: http://lkml.kernel.org/r/20141202120430.71979060@gandalf.local.homeAcked-by: default avatarAlexei Starovoitov <ast@plumgrid.com>
Suggested-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Signed-off-by: default avatarSteven Rostedt <rostedt@goodmis.org>
parent 6a06bdbf
...@@ -45,6 +45,7 @@ enum filter_op_ids ...@@ -45,6 +45,7 @@ enum filter_op_ids
OP_GT, OP_GT,
OP_GE, OP_GE,
OP_BAND, OP_BAND,
OP_NOT,
OP_NONE, OP_NONE,
OP_OPEN_PAREN, OP_OPEN_PAREN,
}; };
...@@ -67,6 +68,7 @@ static struct filter_op filter_ops[] = { ...@@ -67,6 +68,7 @@ static struct filter_op filter_ops[] = {
{ OP_GT, ">", 5 }, { OP_GT, ">", 5 },
{ OP_GE, ">=", 5 }, { OP_GE, ">=", 5 },
{ OP_BAND, "&", 6 }, { OP_BAND, "&", 6 },
{ OP_NOT, "!", 6 },
{ OP_NONE, "OP_NONE", 0 }, { OP_NONE, "OP_NONE", 0 },
{ OP_OPEN_PAREN, "(", 0 }, { OP_OPEN_PAREN, "(", 0 },
}; };
...@@ -85,6 +87,7 @@ enum { ...@@ -85,6 +87,7 @@ enum {
FILT_ERR_MISSING_FIELD, FILT_ERR_MISSING_FIELD,
FILT_ERR_INVALID_FILTER, FILT_ERR_INVALID_FILTER,
FILT_ERR_IP_FIELD_ONLY, FILT_ERR_IP_FIELD_ONLY,
FILT_ERR_ILLEGAL_NOT_OP,
}; };
static char *err_text[] = { static char *err_text[] = {
...@@ -101,6 +104,7 @@ static char *err_text[] = { ...@@ -101,6 +104,7 @@ static char *err_text[] = {
"Missing field name and/or value", "Missing field name and/or value",
"Meaningless filter expression", "Meaningless filter expression",
"Only 'ip' field is supported for function trace", "Only 'ip' field is supported for function trace",
"Illegal use of '!'",
}; };
struct opstack_op { struct opstack_op {
...@@ -139,6 +143,7 @@ struct pred_stack { ...@@ -139,6 +143,7 @@ struct pred_stack {
int index; int index;
}; };
/* If not of not match is equal to not of not, then it is a match */
#define DEFINE_COMPARISON_PRED(type) \ #define DEFINE_COMPARISON_PRED(type) \
static int filter_pred_##type(struct filter_pred *pred, void *event) \ static int filter_pred_##type(struct filter_pred *pred, void *event) \
{ \ { \
...@@ -166,7 +171,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event) \ ...@@ -166,7 +171,7 @@ static int filter_pred_##type(struct filter_pred *pred, void *event) \
break; \ break; \
} \ } \
\ \
return match; \ return !!match == !pred->not; \
} }
#define DEFINE_EQUALITY_PRED(size) \ #define DEFINE_EQUALITY_PRED(size) \
...@@ -1028,7 +1033,7 @@ static int init_pred(struct filter_parse_state *ps, ...@@ -1028,7 +1033,7 @@ static int init_pred(struct filter_parse_state *ps,
} }
if (pred->op == OP_NE) if (pred->op == OP_NE)
pred->not = 1; pred->not ^= 1;
pred->fn = fn; pred->fn = fn;
return 0; return 0;
...@@ -1590,6 +1595,17 @@ static int replace_preds(struct ftrace_event_call *call, ...@@ -1590,6 +1595,17 @@ static int replace_preds(struct ftrace_event_call *call,
continue; continue;
} }
if (elt->op == OP_NOT) {
if (!n_preds || operand1 || operand2) {
parse_error(ps, FILT_ERR_ILLEGAL_NOT_OP, 0);
err = -EINVAL;
goto fail;
}
if (!dry_run)
filter->preds[n_preds - 1].not ^= 1;
continue;
}
if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) { if (WARN_ON(n_preds++ == MAX_FILTER_PRED)) {
parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0); parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
err = -ENOSPC; err = -ENOSPC;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment