|
@@ -45,6 +45,7 @@ enum filter_op_ids
|
|
|
OP_GT,
|
|
|
OP_GE,
|
|
|
OP_BAND,
|
|
|
+ OP_NOT,
|
|
|
OP_NONE,
|
|
|
OP_OPEN_PAREN,
|
|
|
};
|
|
@@ -67,6 +68,7 @@ static struct filter_op filter_ops[] = {
|
|
|
{ OP_GT, ">", 5 },
|
|
|
{ OP_GE, ">=", 5 },
|
|
|
{ OP_BAND, "&", 6 },
|
|
|
+ { OP_NOT, "!", 6 },
|
|
|
{ OP_NONE, "OP_NONE", 0 },
|
|
|
{ OP_OPEN_PAREN, "(", 0 },
|
|
|
};
|
|
@@ -85,6 +87,7 @@ enum {
|
|
|
FILT_ERR_MISSING_FIELD,
|
|
|
FILT_ERR_INVALID_FILTER,
|
|
|
FILT_ERR_IP_FIELD_ONLY,
|
|
|
+ FILT_ERR_ILLEGAL_NOT_OP,
|
|
|
};
|
|
|
|
|
|
static char *err_text[] = {
|
|
@@ -101,6 +104,7 @@ static char *err_text[] = {
|
|
|
"Missing field name and/or value",
|
|
|
"Meaningless filter expression",
|
|
|
"Only 'ip' field is supported for function trace",
|
|
|
+ "Illegal use of '!'",
|
|
|
};
|
|
|
|
|
|
struct opstack_op {
|
|
@@ -139,6 +143,7 @@ struct pred_stack {
|
|
|
int index;
|
|
|
};
|
|
|
|
|
|
+/* If not of not match is equal to not of not, then it is a match */
|
|
|
#define DEFINE_COMPARISON_PRED(type) \
|
|
|
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; \
|
|
|
} \
|
|
|
\
|
|
|
- return match; \
|
|
|
+ return !!match == !pred->not; \
|
|
|
}
|
|
|
|
|
|
#define DEFINE_EQUALITY_PRED(size) \
|
|
@@ -1028,7 +1033,7 @@ static int init_pred(struct filter_parse_state *ps,
|
|
|
}
|
|
|
|
|
|
if (pred->op == OP_NE)
|
|
|
- pred->not = 1;
|
|
|
+ pred->not ^= 1;
|
|
|
|
|
|
pred->fn = fn;
|
|
|
return 0;
|
|
@@ -1590,6 +1595,17 @@ static int replace_preds(struct ftrace_event_call *call,
|
|
|
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)) {
|
|
|
parse_error(ps, FILT_ERR_TOO_MANY_PREDS, 0);
|
|
|
err = -ENOSPC;
|