Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

perf metric: Do not free metric when failed to resolve

It's dangerous to free the original metric when it's called from
resolve_metric() as it's already in the metric_list and might have other
resources too. Instead, it'd better let them bail out and be released
properly at the later stage.

So add a check when it's called from metricgroup__add_metric() and
release it. Also make sure that mp is set properly.

Fixes: 83de0b7d535de ("perf metric: Collect referenced metrics in struct metric_ref_node")
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Acked-by: Jiri Olsa <jolsa@redhat.com>
Cc: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: Ian Rogers <irogers@google.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Stephane Eranian <eranian@google.com>
Link: http://lore.kernel.org/lkml/20200915031819.386559-10-namhyung@kernel.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>

authored by

Namhyung Kim and committed by
Arnaldo Carvalho de Melo
6f47ed6c 27adafcd

+6 -3
+6 -3
tools/perf/util/metricgroup.c
··· 672 672 m->has_constraint = metric_no_group || metricgroup__has_constraint(pe); 673 673 INIT_LIST_HEAD(&m->metric_refs); 674 674 m->metric_refs_cnt = 0; 675 - *mp = m; 676 675 677 676 parent = expr_ids__alloc(ids); 678 677 if (!parent) { ··· 684 685 free(m); 685 686 return -ENOMEM; 686 687 } 688 + *mp = m; 687 689 } else { 688 690 /* 689 691 * We got here for the referenced metric, via the ··· 719 719 * all the metric's IDs and add it to the parent context. 720 720 */ 721 721 if (expr__find_other(pe->metric_expr, NULL, &m->pctx, runtime) < 0) { 722 - expr__ctx_clear(&m->pctx); 723 - free(m); 722 + if (m->metric_refs_cnt == 0) { 723 + expr__ctx_clear(&m->pctx); 724 + free(m); 725 + *mp = NULL; 726 + } 724 727 return -EINVAL; 725 728 } 726 729