Commit 41e12e58 authored by Namhyung Kim's avatar Namhyung Kim Committed by Arnaldo Carvalho de Melo

tools lib traceevent: Refactor pevent_filter_match() to get rid of die()

The test_filter() function is for testing given filter is matched to a
given record.  However it doesn't handle error cases properly so add a
new argument err to save error info during the test and also pass it to
internal test functions.

The return value of pevent_filter_match() also converted to pevent_errno
to indicate an exact error case.
Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Namhyung Kim <namhyung.kim@lge.com>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1386833777-3790-13-git-send-email-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent 69c770a6
...@@ -357,6 +357,8 @@ enum pevent_flag { ...@@ -357,6 +357,8 @@ enum pevent_flag {
_PE(READ_PRINT_FAILED, "failed to read event print fmt"), \ _PE(READ_PRINT_FAILED, "failed to read event print fmt"), \
_PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\ _PE(OLD_FTRACE_ARG_FAILED,"failed to allocate field name for ftrace"),\
_PE(INVALID_ARG_TYPE, "invalid argument type"), \ _PE(INVALID_ARG_TYPE, "invalid argument type"), \
_PE(INVALID_EXP_TYPE, "invalid expression type"), \
_PE(INVALID_OP_TYPE, "invalid operator type"), \
_PE(INVALID_EVENT_NAME, "invalid event name"), \ _PE(INVALID_EVENT_NAME, "invalid event name"), \
_PE(EVENT_NOT_FOUND, "no event found"), \ _PE(EVENT_NOT_FOUND, "no event found"), \
_PE(SYNTAX_ERROR, "syntax error"), \ _PE(SYNTAX_ERROR, "syntax error"), \
...@@ -373,12 +375,16 @@ enum pevent_flag { ...@@ -373,12 +375,16 @@ enum pevent_flag {
_PE(INVALID_PAREN, "open parenthesis cannot come here"), \ _PE(INVALID_PAREN, "open parenthesis cannot come here"), \
_PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \ _PE(UNBALANCED_PAREN, "unbalanced number of parenthesis"), \
_PE(UNKNOWN_TOKEN, "unknown token"), \ _PE(UNKNOWN_TOKEN, "unknown token"), \
_PE(FILTER_NOT_FOUND, "no filter found") _PE(FILTER_NOT_FOUND, "no filter found"), \
_PE(NOT_A_NUMBER, "must have number field"), \
_PE(NO_FILTER, "no filters exists"), \
_PE(FILTER_MISS, "record does not match to filter")
#undef _PE #undef _PE
#define _PE(__code, __str) PEVENT_ERRNO__ ## __code #define _PE(__code, __str) PEVENT_ERRNO__ ## __code
enum pevent_errno { enum pevent_errno {
PEVENT_ERRNO__SUCCESS = 0, PEVENT_ERRNO__SUCCESS = 0,
PEVENT_ERRNO__FILTER_MATCH = PEVENT_ERRNO__SUCCESS,
/* /*
* Choose an arbitrary negative big number not to clash with standard * Choose an arbitrary negative big number not to clash with standard
...@@ -853,10 +859,11 @@ struct event_filter { ...@@ -853,10 +859,11 @@ struct event_filter {
struct event_filter *pevent_filter_alloc(struct pevent *pevent); struct event_filter *pevent_filter_alloc(struct pevent *pevent);
#define FILTER_NONE -2 /* for backward compatibility */
#define FILTER_NOEXIST -1 #define FILTER_NONE PEVENT_ERRNO__FILTER_NOT_FOUND
#define FILTER_MISS 0 #define FILTER_NOEXIST PEVENT_ERRNO__NO_FILTER
#define FILTER_MATCH 1 #define FILTER_MISS PEVENT_ERRNO__FILTER_MISS
#define FILTER_MATCH PEVENT_ERRNO__FILTER_MATCH
enum filter_trivial_type { enum filter_trivial_type {
FILTER_TRIVIAL_FALSE, FILTER_TRIVIAL_FALSE,
...@@ -868,7 +875,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, ...@@ -868,7 +875,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
const char *filter_str); const char *filter_str);
int pevent_filter_match(struct event_filter *filter, enum pevent_errno pevent_filter_match(struct event_filter *filter,
struct pevent_record *record); struct pevent_record *record);
int pevent_event_filtered(struct event_filter *filter, int pevent_event_filtered(struct event_filter *filter,
......
...@@ -1678,8 +1678,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter, ...@@ -1678,8 +1678,8 @@ int pevent_filter_event_has_trivial(struct event_filter *filter,
} }
} }
static int test_filter(struct event_format *event, static int test_filter(struct event_format *event, struct filter_arg *arg,
struct filter_arg *arg, struct pevent_record *record); struct pevent_record *record, enum pevent_errno *err);
static const char * static const char *
get_comm(struct event_format *event, struct pevent_record *record) get_comm(struct event_format *event, struct pevent_record *record)
...@@ -1725,15 +1725,24 @@ get_value(struct event_format *event, ...@@ -1725,15 +1725,24 @@ get_value(struct event_format *event,
} }
static unsigned long long static unsigned long long
get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record); get_arg_value(struct event_format *event, struct filter_arg *arg,
struct pevent_record *record, enum pevent_errno *err);
static unsigned long long static unsigned long long
get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) get_exp_value(struct event_format *event, struct filter_arg *arg,
struct pevent_record *record, enum pevent_errno *err)
{ {
unsigned long long lval, rval; unsigned long long lval, rval;
lval = get_arg_value(event, arg->exp.left, record); lval = get_arg_value(event, arg->exp.left, record, err);
rval = get_arg_value(event, arg->exp.right, record); rval = get_arg_value(event, arg->exp.right, record, err);
if (*err) {
/*
* There was an error, no need to process anymore.
*/
return 0;
}
switch (arg->exp.type) { switch (arg->exp.type) {
case FILTER_EXP_ADD: case FILTER_EXP_ADD:
...@@ -1768,39 +1777,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_ ...@@ -1768,39 +1777,51 @@ get_exp_value(struct event_format *event, struct filter_arg *arg, struct pevent_
case FILTER_EXP_NOT: case FILTER_EXP_NOT:
default: default:
die("error in exp"); if (!*err)
*err = PEVENT_ERRNO__INVALID_EXP_TYPE;
} }
return 0; return 0;
} }
static unsigned long long static unsigned long long
get_arg_value(struct event_format *event, struct filter_arg *arg, struct pevent_record *record) get_arg_value(struct event_format *event, struct filter_arg *arg,
struct pevent_record *record, enum pevent_errno *err)
{ {
switch (arg->type) { switch (arg->type) {
case FILTER_ARG_FIELD: case FILTER_ARG_FIELD:
return get_value(event, arg->field.field, record); return get_value(event, arg->field.field, record);
case FILTER_ARG_VALUE: case FILTER_ARG_VALUE:
if (arg->value.type != FILTER_NUMBER) if (arg->value.type != FILTER_NUMBER) {
die("must have number field!"); if (!*err)
*err = PEVENT_ERRNO__NOT_A_NUMBER;
}
return arg->value.val; return arg->value.val;
case FILTER_ARG_EXP: case FILTER_ARG_EXP:
return get_exp_value(event, arg, record); return get_exp_value(event, arg, record, err);
default: default:
die("oops in filter"); if (!*err)
*err = PEVENT_ERRNO__INVALID_ARG_TYPE;
} }
return 0; return 0;
} }
static int test_num(struct event_format *event, static int test_num(struct event_format *event, struct filter_arg *arg,
struct filter_arg *arg, struct pevent_record *record) struct pevent_record *record, enum pevent_errno *err)
{ {
unsigned long long lval, rval; unsigned long long lval, rval;
lval = get_arg_value(event, arg->num.left, record); lval = get_arg_value(event, arg->num.left, record, err);
rval = get_arg_value(event, arg->num.right, record); rval = get_arg_value(event, arg->num.right, record, err);
if (*err) {
/*
* There was an error, no need to process anymore.
*/
return 0;
}
switch (arg->num.type) { switch (arg->num.type) {
case FILTER_CMP_EQ: case FILTER_CMP_EQ:
...@@ -1822,7 +1843,8 @@ static int test_num(struct event_format *event, ...@@ -1822,7 +1843,8 @@ static int test_num(struct event_format *event,
return lval <= rval; return lval <= rval;
default: default:
/* ?? */ if (!*err)
*err = PEVENT_ERRNO__ILLEGAL_INTEGER_CMP;
return 0; return 0;
} }
} }
...@@ -1869,8 +1891,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r ...@@ -1869,8 +1891,8 @@ static const char *get_field_str(struct filter_arg *arg, struct pevent_record *r
return val; return val;
} }
static int test_str(struct event_format *event, static int test_str(struct event_format *event, struct filter_arg *arg,
struct filter_arg *arg, struct pevent_record *record) struct pevent_record *record, enum pevent_errno *err)
{ {
const char *val; const char *val;
...@@ -1894,48 +1916,57 @@ static int test_str(struct event_format *event, ...@@ -1894,48 +1916,57 @@ static int test_str(struct event_format *event,
return regexec(&arg->str.reg, val, 0, NULL, 0); return regexec(&arg->str.reg, val, 0, NULL, 0);
default: default:
/* ?? */ if (!*err)
*err = PEVENT_ERRNO__ILLEGAL_STRING_CMP;
return 0; return 0;
} }
} }
static int test_op(struct event_format *event, static int test_op(struct event_format *event, struct filter_arg *arg,
struct filter_arg *arg, struct pevent_record *record) struct pevent_record *record, enum pevent_errno *err)
{ {
switch (arg->op.type) { switch (arg->op.type) {
case FILTER_OP_AND: case FILTER_OP_AND:
return test_filter(event, arg->op.left, record) && return test_filter(event, arg->op.left, record, err) &&
test_filter(event, arg->op.right, record); test_filter(event, arg->op.right, record, err);
case FILTER_OP_OR: case FILTER_OP_OR:
return test_filter(event, arg->op.left, record) || return test_filter(event, arg->op.left, record, err) ||
test_filter(event, arg->op.right, record); test_filter(event, arg->op.right, record, err);
case FILTER_OP_NOT: case FILTER_OP_NOT:
return !test_filter(event, arg->op.right, record); return !test_filter(event, arg->op.right, record, err);
default: default:
/* ?? */ if (!*err)
*err = PEVENT_ERRNO__INVALID_OP_TYPE;
return 0; return 0;
} }
} }
static int test_filter(struct event_format *event, static int test_filter(struct event_format *event, struct filter_arg *arg,
struct filter_arg *arg, struct pevent_record *record) struct pevent_record *record, enum pevent_errno *err)
{ {
if (*err) {
/*
* There was an error, no need to process anymore.
*/
return 0;
}
switch (arg->type) { switch (arg->type) {
case FILTER_ARG_BOOLEAN: case FILTER_ARG_BOOLEAN:
/* easy case */ /* easy case */
return arg->boolean.value; return arg->boolean.value;
case FILTER_ARG_OP: case FILTER_ARG_OP:
return test_op(event, arg, record); return test_op(event, arg, record, err);
case FILTER_ARG_NUM: case FILTER_ARG_NUM:
return test_num(event, arg, record); return test_num(event, arg, record, err);
case FILTER_ARG_STR: case FILTER_ARG_STR:
return test_str(event, arg, record); return test_str(event, arg, record, err);
case FILTER_ARG_EXP: case FILTER_ARG_EXP:
case FILTER_ARG_VALUE: case FILTER_ARG_VALUE:
...@@ -1944,11 +1975,11 @@ static int test_filter(struct event_format *event, ...@@ -1944,11 +1975,11 @@ static int test_filter(struct event_format *event,
* Expressions, fields and values evaluate * Expressions, fields and values evaluate
* to true if they return non zero * to true if they return non zero
*/ */
return !!get_arg_value(event, arg, record); return !!get_arg_value(event, arg, record, err);
default: default:
die("oops!"); if (!*err)
/* ?? */ *err = PEVENT_ERRNO__INVALID_ARG_TYPE;
return 0; return 0;
} }
} }
...@@ -1961,8 +1992,7 @@ static int test_filter(struct event_format *event, ...@@ -1961,8 +1992,7 @@ static int test_filter(struct event_format *event,
* Returns 1 if filter found for @event_id * Returns 1 if filter found for @event_id
* otherwise 0; * otherwise 0;
*/ */
int pevent_event_filtered(struct event_filter *filter, int pevent_event_filtered(struct event_filter *filter, int event_id)
int event_id)
{ {
struct filter_type *filter_type; struct filter_type *filter_type;
...@@ -1979,31 +2009,36 @@ int pevent_event_filtered(struct event_filter *filter, ...@@ -1979,31 +2009,36 @@ int pevent_event_filtered(struct event_filter *filter,
* @filter: filter struct with filter information * @filter: filter struct with filter information
* @record: the record to test against the filter * @record: the record to test against the filter
* *
* Returns: * Returns: match result or error code (prefixed with PEVENT_ERRNO__)
* 1 - filter found for event and @record matches * FILTER_MATCH - filter found for event and @record matches
* 0 - filter found for event and @record does not match * FILTER_MISS - filter found for event and @record does not match
* -1 - no filter found for @record's event * FILTER_NOT_FOUND - no filter found for @record's event
* -2 - if no filters exist * NO_FILTER - if no filters exist
* otherwise - error occurred during test
*/ */
int pevent_filter_match(struct event_filter *filter, enum pevent_errno pevent_filter_match(struct event_filter *filter,
struct pevent_record *record) struct pevent_record *record)
{ {
struct pevent *pevent = filter->pevent; struct pevent *pevent = filter->pevent;
struct filter_type *filter_type; struct filter_type *filter_type;
int event_id; int event_id;
int ret;
enum pevent_errno err = 0;
if (!filter->filters) if (!filter->filters)
return FILTER_NONE; return PEVENT_ERRNO__NO_FILTER;
event_id = pevent_data_type(pevent, record); event_id = pevent_data_type(pevent, record);
filter_type = find_filter_type(filter, event_id); filter_type = find_filter_type(filter, event_id);
if (!filter_type) if (!filter_type)
return FILTER_NOEXIST; return PEVENT_ERRNO__FILTER_NOT_FOUND;
ret = test_filter(filter_type->event, filter_type->filter, record, &err);
if (err)
return err;
return test_filter(filter_type->event, filter_type->filter, record) ? return ret ? PEVENT_ERRNO__FILTER_MATCH : PEVENT_ERRNO__FILTER_MISS;
FILTER_MATCH : FILTER_MISS;
} }
static char *op_to_str(struct event_filter *filter, struct filter_arg *arg) static char *op_to_str(struct event_filter *filter, struct filter_arg *arg)
......
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