Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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.org


Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent f1cbf78d
Loading
Loading
Loading
Loading
+1 −16
Original line number Original line Diff line number Diff line
@@ -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];

	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);
	snprintf(buf, buflen, "%s", msg);
		break;

	default:
		/* cannot reach here */
		break;
	}


	return 0;
	return 0;
}
}
+6 −1
Original line number Original line Diff line number Diff line
@@ -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 {
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);


+54 −44
Original line number Original line Diff line number Diff line
@@ -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)


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)
}
}


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 {


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,


/* 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,


/* 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,


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,


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,


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,
	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,
	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,
	/* 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)
	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,
	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;