Skip to content

Commit a910e46

Browse files
captain5050acmel
authored andcommitted
perf parse: Report initial event parsing error
Record the first event parsing error and report. Implementing feedback from Jiri Olsa: https://lkml.org/lkml/2019/10/28/680 An example error is: $ tools/perf/perf stat -e c/c/ WARNING: multiple event parsing errors event syntax error: 'c/c/' \___ unknown term valid terms: event,filter_rem,filter_opc0,edge,filter_isoc,filter_tid,filter_loc,filter_nc,inv,umask,filter_opc1,tid_en,thresh,filter_all_op,filter_not_nm,filter_state,filter_nm,config,config1,config2,name,period,percore Initial error: event syntax error: 'c/c/' \___ Cannot find PMU `c'. Missing kernel support? Run 'perf list' for a list of valid events Usage: perf stat [<options>] [<command>] -e, --event <event> event selector. use 'perf list' to list available events Signed-off-by: Ian Rogers <[email protected]> Tested-by: Arnaldo Carvalho de Melo <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Allison Randal <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Anju T Sudhakar <[email protected]> Cc: Christian Borntraeger <[email protected]> Cc: Davidlohr Bueso <[email protected]> Cc: Jin Yao <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Stephane Eranian <[email protected]> Cc: Thomas Gleixner <[email protected]> Cc: Thomas Richter <[email protected]> Link: http://lore.kernel.org/lkml/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent cb40273 commit a910e46

File tree

7 files changed

+80
-29
lines changed

7 files changed

+80
-29
lines changed

tools/perf/arch/powerpc/util/kvm-stat.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,10 +113,10 @@ static int is_tracepoint_available(const char *str, struct evlist *evlist)
113113
struct parse_events_error err;
114114
int ret;
115115

116-
err.str = NULL;
116+
bzero(&err, sizeof(err));
117117
ret = parse_events(evlist, str, &err);
118118
if (err.str)
119-
pr_err("%s : %s\n", str, err.str);
119+
parse_events_print_error(&err, "tracepoint");
120120
return ret;
121121
}
122122

tools/perf/builtin-stat.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1307,6 +1307,7 @@ static int add_default_attributes(void)
13071307
if (stat_config.null_run)
13081308
return 0;
13091309

1310+
bzero(&errinfo, sizeof(errinfo));
13101311
if (transaction_run) {
13111312
/* Handle -T as -M transaction. Once platform specific metrics
13121313
* support has been added to the json files, all archictures
@@ -1364,6 +1365,7 @@ static int add_default_attributes(void)
13641365
return -1;
13651366
}
13661367
if (err) {
1368+
parse_events_print_error(&errinfo, smi_cost_attrs);
13671369
fprintf(stderr, "Cannot set up SMI cost events\n");
13681370
return -1;
13691371
}

tools/perf/builtin-trace.c

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3016,11 +3016,18 @@ static bool evlist__add_vfs_getname(struct evlist *evlist)
30163016
{
30173017
bool found = false;
30183018
struct evsel *evsel, *tmp;
3019-
struct parse_events_error err = { .idx = 0, };
3020-
int ret = parse_events(evlist, "probe:vfs_getname*", &err);
3019+
struct parse_events_error err;
3020+
int ret;
30213021

3022-
if (ret)
3022+
bzero(&err, sizeof(err));
3023+
ret = parse_events(evlist, "probe:vfs_getname*", &err);
3024+
if (ret) {
3025+
free(err.str);
3026+
free(err.help);
3027+
free(err.first_str);
3028+
free(err.first_help);
30233029
return false;
3030+
}
30243031

30253032
evlist__for_each_entry_safe(evlist, evsel, tmp) {
30263033
if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname"))
@@ -4832,8 +4839,9 @@ int cmd_trace(int argc, const char **argv)
48324839
* wrong in more detail.
48334840
*/
48344841
if (trace.perfconfig_events != NULL) {
4835-
struct parse_events_error parse_err = { .idx = 0, };
4842+
struct parse_events_error parse_err;
48364843

4844+
bzero(&parse_err, sizeof(parse_err));
48374845
err = parse_events(trace.evlist, trace.perfconfig_events, &parse_err);
48384846
if (err) {
48394847
parse_events_print_error(&parse_err, trace.perfconfig_events);

tools/perf/tests/parse-events.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1768,10 +1768,11 @@ static struct terms_test test__terms[] = {
17681768

17691769
static int test_event(struct evlist_test *e)
17701770
{
1771-
struct parse_events_error err = { .idx = 0, };
1771+
struct parse_events_error err;
17721772
struct evlist *evlist;
17731773
int ret;
17741774

1775+
bzero(&err, sizeof(err));
17751776
if (e->valid && !e->valid()) {
17761777
pr_debug("... SKIP");
17771778
return 0;

tools/perf/util/metricgroup.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ int metricgroup__parse_groups(const struct option *opt,
523523
if (ret)
524524
return ret;
525525
pr_debug("adding %s\n", extra_events.buf);
526-
memset(&parse_error, 0, sizeof(struct parse_events_error));
526+
bzero(&parse_error, sizeof(parse_error));
527527
ret = parse_events(perf_evlist, extra_events.buf, &parse_error);
528528
if (ret) {
529529
parse_events_print_error(&parse_error, extra_events.buf);

tools/perf/util/parse-events.c

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -189,12 +189,29 @@ void parse_events__handle_error(struct parse_events_error *err, int idx,
189189
free(help);
190190
return;
191191
}
192-
WARN_ONCE(err->str, "WARNING: multiple event parsing errors\n");
193-
err->idx = idx;
194-
free(err->str);
195-
err->str = str;
196-
free(err->help);
197-
err->help = help;
192+
switch (err->num_errors) {
193+
case 0:
194+
err->idx = idx;
195+
err->str = str;
196+
err->help = help;
197+
break;
198+
case 1:
199+
err->first_idx = err->idx;
200+
err->idx = idx;
201+
err->first_str = err->str;
202+
err->str = str;
203+
err->first_help = err->help;
204+
err->help = help;
205+
break;
206+
default:
207+
WARN_ONCE(1, "WARNING: multiple event parsing errors\n");
208+
free(err->str);
209+
err->str = str;
210+
free(err->help);
211+
err->help = help;
212+
break;
213+
}
214+
err->num_errors++;
198215
}
199216

200217
struct tracepoint_path *tracepoint_id_to_path(u64 config)
@@ -1349,7 +1366,7 @@ int parse_events_add_pmu(struct parse_events_state *parse_state,
13491366
if (asprintf(&err_str,
13501367
"Cannot find PMU `%s'. Missing kernel support?",
13511368
name) >= 0)
1352-
parse_events__handle_error(err, -1, err_str, NULL);
1369+
parse_events__handle_error(err, 0, err_str, NULL);
13531370
return -EINVAL;
13541371
}
13551372

@@ -2007,15 +2024,14 @@ static int get_term_width(void)
20072024
return ws.ws_col > MAX_WIDTH ? MAX_WIDTH : ws.ws_col;
20082025
}
20092026

2010-
void parse_events_print_error(struct parse_events_error *err,
2011-
const char *event)
2027+
static void __parse_events_print_error(int err_idx, const char *err_str,
2028+
const char *err_help, const char *event)
20122029
{
20132030
const char *str = "invalid or unsupported event: ";
20142031
char _buf[MAX_WIDTH];
20152032
char *buf = (char *) event;
20162033
int idx = 0;
2017-
2018-
if (err->str) {
2034+
if (err_str) {
20192035
/* -2 for extra '' in the final fprintf */
20202036
int width = get_term_width() - 2;
20212037
int len_event = strlen(event);
@@ -2038,8 +2054,8 @@ void parse_events_print_error(struct parse_events_error *err,
20382054
buf = _buf;
20392055

20402056
/* We're cutting from the beginning. */
2041-
if (err->idx > max_err_idx)
2042-
cut = err->idx - max_err_idx;
2057+
if (err_idx > max_err_idx)
2058+
cut = err_idx - max_err_idx;
20432059

20442060
strncpy(buf, event + cut, max_len);
20452061

@@ -2052,16 +2068,33 @@ void parse_events_print_error(struct parse_events_error *err,
20522068
buf[max_len] = 0;
20532069
}
20542070

2055-
idx = len_str + err->idx - cut;
2071+
idx = len_str + err_idx - cut;
20562072
}
20572073

20582074
fprintf(stderr, "%s'%s'\n", str, buf);
20592075
if (idx) {
2060-
fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err->str);
2061-
if (err->help)
2062-
fprintf(stderr, "\n%s\n", err->help);
2063-
zfree(&err->str);
2064-
zfree(&err->help);
2076+
fprintf(stderr, "%*s\\___ %s\n", idx + 1, "", err_str);
2077+
if (err_help)
2078+
fprintf(stderr, "\n%s\n", err_help);
2079+
}
2080+
}
2081+
2082+
void parse_events_print_error(struct parse_events_error *err,
2083+
const char *event)
2084+
{
2085+
if (!err->num_errors)
2086+
return;
2087+
2088+
__parse_events_print_error(err->idx, err->str, err->help, event);
2089+
zfree(&err->str);
2090+
zfree(&err->help);
2091+
2092+
if (err->num_errors > 1) {
2093+
fputs("\nInitial error:\n", stderr);
2094+
__parse_events_print_error(err->first_idx, err->first_str,
2095+
err->first_help, event);
2096+
zfree(&err->first_str);
2097+
zfree(&err->first_help);
20652098
}
20662099
}
20672100

@@ -2071,8 +2104,11 @@ int parse_events_option(const struct option *opt, const char *str,
20712104
int unset __maybe_unused)
20722105
{
20732106
struct evlist *evlist = *(struct evlist **)opt->value;
2074-
struct parse_events_error err = { .idx = 0, };
2075-
int ret = parse_events(evlist, str, &err);
2107+
struct parse_events_error err;
2108+
int ret;
2109+
2110+
bzero(&err, sizeof(err));
2111+
ret = parse_events(evlist, str, &err);
20762112

20772113
if (ret) {
20782114
parse_events_print_error(&err, str);

tools/perf/util/parse-events.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,9 +110,13 @@ struct parse_events_term {
110110
};
111111

112112
struct parse_events_error {
113+
int num_errors; /* number of errors encountered */
113114
int idx; /* index in the parsed string */
114115
char *str; /* string to display at the index */
115116
char *help; /* optional help string */
117+
int first_idx;/* as above, but for the first encountered error */
118+
char *first_str;
119+
char *first_help;
116120
};
117121

118122
struct parse_events_state {

0 commit comments

Comments
 (0)