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: Jiri Olsa <jolsa@kernel.org> Tested-by: Arnaldo 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: Arnaldo Carvalho de Melo <acme@redhat.com>
This commit is contained in:
Родитель
cecf3a2e18
Коммит
e64b020ba1
|
@ -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;
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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,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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче