From: Stephane Eranian <eranian@xxxxxxxxxx> [ Upstream commit db49a71798a38f3ddf3f3462703328dca39b1ac7 ] (This is a patch has been sitting in the Intel CQM/CMT driver series for a while, despite not depend on it. Sending it now independently since the series is being discarded.) When an event is in error state, read() returns 0 instead of sizeof() buffer. In certain modes, such as interval printing, ignoring the 0 return value may cause bogus count deltas to be computed and thus invalid results printed. This patch fixes this problem by modifying read_counters() to mark the event as not scaled (scaled = -1) to force the printout routine to show <NOT COUNTED>. Signed-off-by: Stephane Eranian <eranian@xxxxxxxxxx> Reviewed-by: David Carrillo-Cisneros <davidcc@xxxxxxxxxx> Acked-by: Jiri Olsa <jolsa@xxxxxxxxxx> Cc: Adrian Hunter <adrian.hunter@xxxxxxxxx> Cc: Alexander Shishkin <alexander.shishkin@xxxxxxxxxxxxxxx> Cc: Andi Kleen <ak@xxxxxxxxxxxxxxx> Cc: Mathieu Poirier <mathieu.poirier@xxxxxxxxxx> Cc: Paul Turner <pjt@xxxxxxxxxx> Cc: Peter Zijlstra <peterz@xxxxxxxxxxxxx> Cc: Wang Nan <wangnan0@xxxxxxxxxx> Link: http://lkml.kernel.org/r/20170412182301.44406-1-davidcc@xxxxxxxxxx Signed-off-by: Arnaldo Carvalho de Melo <acme@xxxxxxxxxx> Signed-off-by: Sasha Levin <alexander.levin@xxxxxxxxxxxxx> --- tools/perf/builtin-stat.c | 12 +++++++++--- tools/perf/util/evsel.c | 4 ++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c index c241167c76c9..5b60ec669e73 100644 --- a/tools/perf/builtin-stat.c +++ b/tools/perf/builtin-stat.c @@ -311,8 +311,12 @@ static int read_counter(struct perf_evsel *counter) struct perf_counts_values *count; count = perf_counts(counter->counts, cpu, thread); - if (perf_evsel__read(counter, cpu, thread, count)) + if (perf_evsel__read(counter, cpu, thread, count)) { + counter->counts->scaled = -1; + perf_counts(counter->counts, cpu, thread)->ena = 0; + perf_counts(counter->counts, cpu, thread)->run = 0; return -1; + } if (STAT_RECORD) { if (perf_evsel__write_stat_event(counter, cpu, thread, count)) { @@ -337,12 +341,14 @@ static int read_counter(struct perf_evsel *counter) static void read_counters(void) { struct perf_evsel *counter; + int ret; evlist__for_each_entry(evsel_list, counter) { - if (read_counter(counter)) + ret = read_counter(counter); + if (ret) pr_debug("failed to read counter %s\n", counter->name); - if (perf_stat_process_counter(&stat_config, counter)) + if (ret == 0 && perf_stat_process_counter(&stat_config, counter)) pr_warning("failed to process counter %s\n", counter->name); } } diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c index 539724c7d30b..bce80f866dd0 100644 --- a/tools/perf/util/evsel.c +++ b/tools/perf/util/evsel.c @@ -1221,7 +1221,7 @@ int perf_evsel__read(struct perf_evsel *evsel, int cpu, int thread, if (FD(evsel, cpu, thread) < 0) return -EINVAL; - if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) < 0) + if (readn(FD(evsel, cpu, thread), count, sizeof(*count)) <= 0) return -errno; return 0; @@ -1239,7 +1239,7 @@ int __perf_evsel__read_on_cpu(struct perf_evsel *evsel, if (evsel->counts == NULL && perf_evsel__alloc_counts(evsel, cpu + 1, thread + 1) < 0) return -ENOMEM; - if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) < 0) + if (readn(FD(evsel, cpu, thread), &count, nv * sizeof(u64)) <= 0) return -errno; perf_evsel__compute_deltas(evsel, cpu, thread, &count); -- 2.14.1