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

Commit e64b020b authored by Jiri Olsa's avatar Jiri Olsa Committed by Arnaldo Carvalho de Melo
Browse files

perf tools: Add term support for parse_events_error



Allowing event's term processing to report back error, like:

  $ perf record -e 'cpu/even=0x1/' ls
  event syntax error: 'cpu/even=0x1/'
                           \___ unknown term

  valid terms: pc,any,inv,edge,cmask,event,in_tx,ldlat,umask,in_tx_cp,offcore_rsp,config,config1,config2,name,period,branch_type

Signed-off-by: default avatarJiri Olsa <jolsa@kernel.org>
Tested-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Link: http://lkml.kernel.org/r/1429729824-13932-7-git-send-email-jolsa@kernel.org


[ Renamed 'error' variables to 'err', not to clash with util.h error() ]
Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent cecf3a2e
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -152,7 +152,8 @@ int test__pmu(void)
		if (ret)
			break;

		ret = perf_pmu__config_terms(&formats, &attr, terms, false);
		ret = perf_pmu__config_terms(&formats, &attr, terms,
					     false, NULL);
		if (ret)
			break;

+1 −1
Original line number Diff line number Diff line
@@ -675,7 +675,7 @@ int parse_events_add_pmu(struct parse_events_evlist *data,
	if (config_attr(&attr, head_config))
		return -EINVAL;

	if (perf_pmu__config(pmu, &attr, head_config))
	if (perf_pmu__config(pmu, &attr, head_config, data->error))
		return -EINVAL;

	evsel = __add_event(list, &data->idx, &attr,
+4 −0
Original line number Diff line number Diff line
@@ -174,6 +174,10 @@ modifier_bp [rwx]{1,3}
}

<config>{
	/*
	 * Please update formats_error_string any time
	 * new static term is added.
	 */
config			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG); }
config1			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG1); }
config2			{ return term(yyscanner, PARSE_EVENTS__TERM_TYPE_CONFIG2); }
+51 −6
Original line number Diff line number Diff line
@@ -579,6 +579,38 @@ static int pmu_resolve_param_term(struct parse_events_term *term,
	return -1;
}

static char *formats_error_string(struct list_head *formats)
{
	struct perf_pmu_format *format;
	char *err, *str;
	static const char *static_terms = "config,config1,config2,name,period,branch_type\n";
	unsigned i = 0;

	if (!asprintf(&str, "valid terms:"))
		return NULL;

	/* sysfs exported terms */
	list_for_each_entry(format, formats, list) {
		char c = i++ ? ',' : ' ';

		err = str;
		if (!asprintf(&str, "%s%c%s", err, c, format->name))
			goto fail;
		free(err);
	}

	/* static terms */
	err = str;
	if (!asprintf(&str, "%s,%s", err, static_terms))
		goto fail;

	free(err);
	return str;
fail:
	free(err);
	return NULL;
}

/*
 * Setup one of config[12] attr members based on the
 * user input data - term parameter.
@@ -587,7 +619,7 @@ static int pmu_config_term(struct list_head *formats,
			   struct perf_event_attr *attr,
			   struct parse_events_term *term,
			   struct list_head *head_terms,
			   bool zero)
			   bool zero, struct parse_events_error *err)
{
	struct perf_pmu_format *format;
	__u64 *vp;
@@ -611,6 +643,11 @@ static int pmu_config_term(struct list_head *formats,
	if (!format) {
		if (verbose)
			printf("Invalid event/parameter '%s'\n", term->config);
		if (err) {
			err->idx  = term->err_term;
			err->str  = strdup("unknown term");
			err->help = formats_error_string(formats);
		}
		return -EINVAL;
	}

@@ -636,9 +673,14 @@ static int pmu_config_term(struct list_head *formats,
		val = term->val.num;
	else if (term->type_val == PARSE_EVENTS__TERM_TYPE_STR) {
		if (strcmp(term->val.str, "?")) {
			if (verbose)
			if (verbose) {
				pr_info("Invalid sysfs entry %s=%s\n",
						term->config, term->val.str);
			}
			if (err) {
				err->idx = term->err_val;
				err->str = strdup("expected numeric value");
			}
			return -EINVAL;
		}

@@ -654,12 +696,13 @@ static int pmu_config_term(struct list_head *formats,
int perf_pmu__config_terms(struct list_head *formats,
			   struct perf_event_attr *attr,
			   struct list_head *head_terms,
			   bool zero)
			   bool zero, struct parse_events_error *err)
{
	struct parse_events_term *term;

	list_for_each_entry(term, head_terms, list) {
		if (pmu_config_term(formats, attr, term, head_terms, zero))
		if (pmu_config_term(formats, attr, term, head_terms,
				    zero, err))
			return -EINVAL;
	}

@@ -672,12 +715,14 @@ int perf_pmu__config_terms(struct list_head *formats,
 * 2) pmu format definitions - specified by pmu parameter
 */
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
		     struct list_head *head_terms)
		     struct list_head *head_terms,
		     struct parse_events_error *err)
{
	bool zero = !!pmu->default_config;

	attr->type = pmu->type;
	return perf_pmu__config_terms(&pmu->format, attr, head_terms, zero);
	return perf_pmu__config_terms(&pmu->format, attr, head_terms,
				      zero, err);
}

static struct perf_pmu_alias *pmu_find_alias(struct perf_pmu *pmu,
+4 −2
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
#include <linux/bitmap.h>
#include <linux/perf_event.h>
#include <stdbool.h>
#include "parse-events.h"

enum {
	PERF_PMU_FORMAT_VALUE_CONFIG,
@@ -47,11 +48,12 @@ struct perf_pmu_alias {

struct perf_pmu *perf_pmu__find(const char *name);
int perf_pmu__config(struct perf_pmu *pmu, struct perf_event_attr *attr,
		     struct list_head *head_terms);
		     struct list_head *head_terms,
		     struct parse_events_error *error);
int perf_pmu__config_terms(struct list_head *formats,
			   struct perf_event_attr *attr,
			   struct list_head *head_terms,
			   bool zero);
			   bool zero, struct parse_events_error *error);
int perf_pmu__check_alias(struct perf_pmu *pmu, struct list_head *head_terms,
			  struct perf_pmu_info *info);
struct list_head *perf_pmu__alias(struct perf_pmu *pmu,