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

tools lib traceevent: Introduce pevent_filter_strerror()

The pevent_filter_strerror() function is for receiving actual error
message from pevent_errno value.  To do that, add a static buffer to
event_filter for saving internal error message

If a failed function saved other information in the static buffer
returns the information, otherwise returns generic error message.
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: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Steven Rostedt <rostedt@goodmis.org>
Link: http://lkml.kernel.org/r/1386833777-3790-15-git-send-email-namhyung@kernel.orgSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f1cbf78d
...@@ -5230,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused, ...@@ -5230,22 +5230,7 @@ int pevent_strerror(struct pevent *pevent __maybe_unused,
idx = errnum - __PEVENT_ERRNO__START - 1; idx = errnum - __PEVENT_ERRNO__START - 1;
msg = pevent_error_str[idx]; msg = pevent_error_str[idx];
snprintf(buf, buflen, "%s", msg);
switch (errnum) {
case PEVENT_ERRNO__MEM_ALLOC_FAILED:
case PEVENT_ERRNO__PARSE_EVENT_FAILED:
case PEVENT_ERRNO__READ_ID_FAILED:
case PEVENT_ERRNO__READ_FORMAT_FAILED:
case PEVENT_ERRNO__READ_PRINT_FAILED:
case PEVENT_ERRNO__OLD_FTRACE_ARG_FAILED:
case PEVENT_ERRNO__INVALID_ARG_TYPE:
snprintf(buf, buflen, "%s", msg);
break;
default:
/* cannot reach here */
break;
}
return 0; return 0;
} }
......
...@@ -851,10 +851,13 @@ struct filter_type { ...@@ -851,10 +851,13 @@ struct filter_type {
struct filter_arg *filter; struct filter_arg *filter;
}; };
#define PEVENT_FILTER_ERROR_BUFSZ 1024
struct event_filter { struct event_filter {
struct pevent *pevent; struct pevent *pevent;
int filters; int filters;
struct filter_type *event_filters; struct filter_type *event_filters;
char error_buffer[PEVENT_FILTER_ERROR_BUFSZ];
}; };
struct event_filter *pevent_filter_alloc(struct pevent *pevent); struct event_filter *pevent_filter_alloc(struct pevent *pevent);
...@@ -874,10 +877,12 @@ enum filter_trivial_type { ...@@ -874,10 +877,12 @@ enum filter_trivial_type {
enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
const char *filter_str); const char *filter_str);
enum pevent_errno 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_filter_strerror(struct event_filter *filter, enum pevent_errno err,
char *buf, size_t buflen);
int pevent_event_filtered(struct event_filter *filter, int pevent_event_filtered(struct event_filter *filter,
int event_id); int event_id);
......
...@@ -38,55 +38,31 @@ struct event_list { ...@@ -38,55 +38,31 @@ struct event_list {
struct event_format *event; struct event_format *event;
}; };
#define MAX_ERR_STR_SIZE 256 static void show_error(char *error_buf, const char *fmt, ...)
static void show_error(char **error_str, const char *fmt, ...)
{ {
unsigned long long index; unsigned long long index;
const char *input; const char *input;
char *error;
va_list ap; va_list ap;
int len; int len;
int i; int i;
if (!error_str)
return;
input = pevent_get_input_buf(); input = pevent_get_input_buf();
index = pevent_get_input_buf_ptr(); index = pevent_get_input_buf_ptr();
len = input ? strlen(input) : 0; len = input ? strlen(input) : 0;
error = malloc(MAX_ERR_STR_SIZE + (len*2) + 3);
if (error == NULL) {
/*
* Maybe it's due to len is too long.
* Retry without the input buffer part.
*/
len = 0;
error = malloc(MAX_ERR_STR_SIZE);
if (error == NULL) {
/* no memory */
*error_str = NULL;
return;
}
}
if (len) { if (len) {
strcpy(error, input); strcpy(error_buf, input);
error[len] = '\n'; error_buf[len] = '\n';
for (i = 1; i < len && i < index; i++) for (i = 1; i < len && i < index; i++)
error[len+i] = ' '; error_buf[len+i] = ' ';
error[len + i] = '^'; error_buf[len + i] = '^';
error[len + i + 1] = '\n'; error_buf[len + i + 1] = '\n';
len += i+2; len += i+2;
} }
va_start(ap, fmt); va_start(ap, fmt);
vsnprintf(error + len, MAX_ERR_STR_SIZE, fmt, ap); vsnprintf(error_buf + len, PEVENT_FILTER_ERROR_BUFSZ - len, fmt, ap);
va_end(ap); va_end(ap);
*error_str = error;
} }
static void free_token(char *token) static void free_token(char *token)
...@@ -370,7 +346,7 @@ static void free_events(struct event_list *events) ...@@ -370,7 +346,7 @@ static void free_events(struct event_list *events)
static enum pevent_errno static enum pevent_errno
create_arg_item(struct event_format *event, const char *token, create_arg_item(struct event_format *event, const char *token,
enum event_type type, struct filter_arg **parg, char **error_str) enum event_type type, struct filter_arg **parg, char *error_str)
{ {
struct format_field *field; struct format_field *field;
struct filter_arg *arg; struct filter_arg *arg;
...@@ -474,7 +450,7 @@ create_arg_cmp(enum filter_exp_type etype) ...@@ -474,7 +450,7 @@ create_arg_cmp(enum filter_exp_type etype)
} }
static enum pevent_errno static enum pevent_errno
add_right(struct filter_arg *op, struct filter_arg *arg, char **error_str) add_right(struct filter_arg *op, struct filter_arg *arg, char *error_str)
{ {
struct filter_arg *left; struct filter_arg *left;
char *str; char *str;
...@@ -786,7 +762,7 @@ enum filter_vals { ...@@ -786,7 +762,7 @@ enum filter_vals {
static enum pevent_errno static enum pevent_errno
reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
struct filter_arg *arg, char **error_str) struct filter_arg *arg, char *error_str)
{ {
struct filter_arg *other_child; struct filter_arg *other_child;
struct filter_arg **ptr; struct filter_arg **ptr;
...@@ -838,7 +814,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child, ...@@ -838,7 +814,7 @@ reparent_op_arg(struct filter_arg *parent, struct filter_arg *old_child,
/* Returns either filter_vals (success) or pevent_errno (failfure) */ /* Returns either filter_vals (success) or pevent_errno (failfure) */
static int test_arg(struct filter_arg *parent, struct filter_arg *arg, static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
char **error_str) char *error_str)
{ {
int lval, rval; int lval, rval;
...@@ -938,7 +914,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg, ...@@ -938,7 +914,7 @@ static int test_arg(struct filter_arg *parent, struct filter_arg *arg,
/* Remove any unknown event fields */ /* Remove any unknown event fields */
static int collapse_tree(struct filter_arg *arg, static int collapse_tree(struct filter_arg *arg,
struct filter_arg **arg_collapsed, char **error_str) struct filter_arg **arg_collapsed, char *error_str)
{ {
int ret; int ret;
...@@ -973,7 +949,7 @@ static int collapse_tree(struct filter_arg *arg, ...@@ -973,7 +949,7 @@ static int collapse_tree(struct filter_arg *arg,
static enum pevent_errno static enum pevent_errno
process_filter(struct event_format *event, struct filter_arg **parg, process_filter(struct event_format *event, struct filter_arg **parg,
char **error_str, int not) char *error_str, int not)
{ {
enum event_type type; enum event_type type;
char *token = NULL; char *token = NULL;
...@@ -1211,7 +1187,7 @@ process_filter(struct event_format *event, struct filter_arg **parg, ...@@ -1211,7 +1187,7 @@ process_filter(struct event_format *event, struct filter_arg **parg,
static enum pevent_errno static enum pevent_errno
process_event(struct event_format *event, const char *filter_str, process_event(struct event_format *event, const char *filter_str,
struct filter_arg **parg, char **error_str) struct filter_arg **parg, char *error_str)
{ {
int ret; int ret;
...@@ -1236,7 +1212,7 @@ process_event(struct event_format *event, const char *filter_str, ...@@ -1236,7 +1212,7 @@ process_event(struct event_format *event, const char *filter_str,
static enum pevent_errno static enum pevent_errno
filter_event(struct event_filter *filter, struct event_format *event, filter_event(struct event_filter *filter, struct event_format *event,
const char *filter_str, char **error_str) const char *filter_str, char *error_str)
{ {
struct filter_type *filter_type; struct filter_type *filter_type;
struct filter_arg *arg; struct filter_arg *arg;
...@@ -1268,13 +1244,21 @@ filter_event(struct event_filter *filter, struct event_format *event, ...@@ -1268,13 +1244,21 @@ filter_event(struct event_filter *filter, struct event_format *event,
return 0; return 0;
} }
static void filter_init_error_buf(struct event_filter *filter)
{
/* clear buffer to reset show error */
pevent_buffer_init("", 0);
filter->error_buffer[0] = '\0';
}
/** /**
* pevent_filter_add_filter_str - add a new filter * pevent_filter_add_filter_str - add a new filter
* @filter: the event filter to add to * @filter: the event filter to add to
* @filter_str: the filter string that contains the filter * @filter_str: the filter string that contains the filter
* *
* Returns 0 if the filter was successfully added or a * Returns 0 if the filter was successfully added or a
* negative error code. * negative error code. Use pevent_filter_strerror() to see
* actual error message in case of error.
*/ */
enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
const char *filter_str) const char *filter_str)
...@@ -1291,10 +1275,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, ...@@ -1291,10 +1275,8 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */ enum pevent_errno rtn = 0; /* PEVENT_ERRNO__SUCCESS */
int len; int len;
int ret; int ret;
char *error_str = NULL;
/* clear buffer to reset show error */ filter_init_error_buf(filter);
pevent_buffer_init("", 0);
filter_start = strchr(filter_str, ':'); filter_start = strchr(filter_str, ':');
if (filter_start) if (filter_start)
...@@ -1353,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter, ...@@ -1353,7 +1335,7 @@ enum pevent_errno pevent_filter_add_filter_str(struct event_filter *filter,
/* filter starts here */ /* filter starts here */
for (event = events; event; event = event->next) { for (event = events; event; event = event->next) {
ret = filter_event(filter, event->event, filter_start, ret = filter_event(filter, event->event, filter_start,
&error_str); filter->error_buffer);
/* Failures are returned if a parse error happened */ /* Failures are returned if a parse error happened */
if (ret < 0) if (ret < 0)
rtn = ret; rtn = ret;
...@@ -1381,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type) ...@@ -1381,6 +1363,32 @@ static void free_filter_type(struct filter_type *filter_type)
free_arg(filter_type->filter); free_arg(filter_type->filter);
} }
/**
* pevent_filter_strerror - fill error message in a buffer
* @filter: the event filter contains error
* @err: the error code
* @buf: the buffer to be filled in
* @buflen: the size of the buffer
*
* Returns 0 if message was filled successfully, -1 if error
*/
int pevent_filter_strerror(struct event_filter *filter, enum pevent_errno err,
char *buf, size_t buflen)
{
if (err <= __PEVENT_ERRNO__START || err >= __PEVENT_ERRNO__END)
return -1;
if (strlen(filter->error_buffer) > 0) {
size_t len = snprintf(buf, buflen, "%s", filter->error_buffer);
if (len > buflen)
return -1;
return 0;
}
return pevent_strerror(filter->pevent, err, buf, buflen);
}
/** /**
* pevent_filter_remove_event - remove a filter for an event * pevent_filter_remove_event - remove a filter for an event
* @filter: the event filter to remove from * @filter: the event filter to remove from
...@@ -2027,6 +2035,8 @@ enum pevent_errno pevent_filter_match(struct event_filter *filter, ...@@ -2027,6 +2035,8 @@ enum pevent_errno pevent_filter_match(struct event_filter *filter,
int ret; int ret;
enum pevent_errno err = 0; enum pevent_errno err = 0;
filter_init_error_buf(filter);
if (!filter->filters) if (!filter->filters)
return PEVENT_ERRNO__NO_FILTER; return PEVENT_ERRNO__NO_FILTER;
......
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