Skip to content

Commit d561e17

Browse files
captain5050acmel
authored andcommitted
perf hist: Avoid 'struct hist_entry_iter' mem_info memory leak
'struct mem_info' is reference counted while 'struct branch_info' and he_cache (struct hist_entry **) are not. Break apart the priv field in 'struct hist_entry_iter' so that we can know which values are owned by the iter and do the appropriate free or put. Move hide_unresolved to marginally shrink the size of the now grown struct. Signed-off-by: Ian Rogers <[email protected]> Cc: Adrian Hunter <[email protected]> Cc: Alexander Shishkin <[email protected]> Cc: Andi Kleen <[email protected]> Cc: Athira Rajeev <[email protected]> Cc: Ben Gainey <[email protected]> Cc: Ingo Molnar <[email protected]> Cc: James Clark <[email protected]> Cc: Jiri Olsa <[email protected]> Cc: K Prateek Nayak <[email protected]> Cc: Kajol Jain <[email protected]> Cc: Kan Liang <[email protected]> Cc: Li Dong <[email protected]> Cc: Mark Rutland <[email protected]> Cc: Namhyung Kim <[email protected]> Cc: Oliver Upton <[email protected]> Cc: Paran Lee <[email protected]> Cc: Peter Zijlstra <[email protected]> Cc: Ravi Bangoria <[email protected]> Cc: Sun Haiyong <[email protected]> Cc: Tim Chen <[email protected]> Cc: Yanteng Si <[email protected]> Cc: Yicong Yang <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
1 parent 1a8c2e0 commit d561e17

File tree

2 files changed

+19
-28
lines changed

2 files changed

+19
-28
lines changed

tools/perf/util/hist.c

Lines changed: 14 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -476,13 +476,6 @@ static int hist_entry__init(struct hist_entry *he,
476476
he->branch_info->to.ms.map = map__get(he->branch_info->to.ms.map);
477477
}
478478

479-
if (he->mem_info) {
480-
mem_info__iaddr(he->mem_info)->ms.map =
481-
map__get(mem_info__iaddr(he->mem_info)->ms.map);
482-
mem_info__daddr(he->mem_info)->ms.map =
483-
map__get(mem_info__daddr(he->mem_info)->ms.map);
484-
}
485-
486479
if (hist_entry__has_callchains(he) && symbol_conf.use_callchain)
487480
callchain_init(he->callchain);
488481

@@ -574,7 +567,6 @@ static struct hist_entry *hist_entry__new(struct hist_entry *template,
574567
he = NULL;
575568
}
576569
}
577-
578570
return he;
579571
}
580572

@@ -747,7 +739,7 @@ __hists__add_entry(struct hists *hists,
747739
.filtered = symbol__parent_filter(sym_parent) | al->filtered,
748740
.hists = hists,
749741
.branch_info = bi,
750-
.mem_info = mi,
742+
.mem_info = mem_info__get(mi),
751743
.kvm_info = ki,
752744
.block_info = block_info,
753745
.transaction = sample->transaction,
@@ -836,15 +828,15 @@ iter_prepare_mem_entry(struct hist_entry_iter *iter, struct addr_location *al)
836828
if (mi == NULL)
837829
return -ENOMEM;
838830

839-
iter->priv = mi;
831+
iter->mi = mi;
840832
return 0;
841833
}
842834

843835
static int
844836
iter_add_single_mem_entry(struct hist_entry_iter *iter, struct addr_location *al)
845837
{
846838
u64 cost;
847-
struct mem_info *mi = iter->priv;
839+
struct mem_info *mi = iter->mi;
848840
struct hists *hists = evsel__hists(iter->evsel);
849841
struct perf_sample *sample = iter->sample;
850842
struct hist_entry *he;
@@ -891,12 +883,7 @@ iter_finish_mem_entry(struct hist_entry_iter *iter,
891883
err = hist_entry__append_callchain(he, iter->sample);
892884

893885
out:
894-
/*
895-
* We don't need to free iter->priv (mem_info) here since the mem info
896-
* was either already freed in hists__findnew_entry() or passed to a
897-
* new hist entry by hist_entry__new().
898-
*/
899-
iter->priv = NULL;
886+
mem_info__zput(iter->mi);
900887

901888
iter->he = NULL;
902889
return err;
@@ -915,7 +902,7 @@ iter_prepare_branch_entry(struct hist_entry_iter *iter, struct addr_location *al
915902
iter->curr = 0;
916903
iter->total = sample->branch_stack->nr;
917904

918-
iter->priv = bi;
905+
iter->bi = bi;
919906
return 0;
920907
}
921908

@@ -929,7 +916,7 @@ iter_add_single_branch_entry(struct hist_entry_iter *iter __maybe_unused,
929916
static int
930917
iter_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *al)
931918
{
932-
struct branch_info *bi = iter->priv;
919+
struct branch_info *bi = iter->bi;
933920
int i = iter->curr;
934921

935922
if (bi == NULL)
@@ -958,7 +945,7 @@ iter_add_next_branch_entry(struct hist_entry_iter *iter, struct addr_location *a
958945
int i = iter->curr;
959946
int err = 0;
960947

961-
bi = iter->priv;
948+
bi = iter->bi;
962949

963950
if (iter->hide_unresolved && !(bi[i].from.ms.sym && bi[i].to.ms.sym))
964951
goto out;
@@ -987,7 +974,7 @@ static int
987974
iter_finish_branch_entry(struct hist_entry_iter *iter,
988975
struct addr_location *al __maybe_unused)
989976
{
990-
zfree(&iter->priv);
977+
zfree(&iter->bi);
991978
iter->he = NULL;
992979

993980
return iter->curr >= iter->total ? 0 : -1;
@@ -1055,7 +1042,7 @@ iter_prepare_cumulative_entry(struct hist_entry_iter *iter,
10551042
if (he_cache == NULL)
10561043
return -ENOMEM;
10571044

1058-
iter->priv = he_cache;
1045+
iter->he_cache = he_cache;
10591046
iter->curr = 0;
10601047

10611048
return 0;
@@ -1068,7 +1055,7 @@ iter_add_single_cumulative_entry(struct hist_entry_iter *iter,
10681055
struct evsel *evsel = iter->evsel;
10691056
struct hists *hists = evsel__hists(evsel);
10701057
struct perf_sample *sample = iter->sample;
1071-
struct hist_entry **he_cache = iter->priv;
1058+
struct hist_entry **he_cache = iter->he_cache;
10721059
struct hist_entry *he;
10731060
int err = 0;
10741061

@@ -1126,7 +1113,7 @@ iter_add_next_cumulative_entry(struct hist_entry_iter *iter,
11261113
{
11271114
struct evsel *evsel = iter->evsel;
11281115
struct perf_sample *sample = iter->sample;
1129-
struct hist_entry **he_cache = iter->priv;
1116+
struct hist_entry **he_cache = iter->he_cache;
11301117
struct hist_entry *he;
11311118
struct hist_entry he_tmp = {
11321119
.hists = evsel__hists(evsel),
@@ -1192,7 +1179,9 @@ static int
11921179
iter_finish_cumulative_entry(struct hist_entry_iter *iter,
11931180
struct addr_location *al __maybe_unused)
11941181
{
1195-
zfree(&iter->priv);
1182+
mem_info__zput(iter->mi);
1183+
zfree(&iter->bi);
1184+
zfree(&iter->he_cache);
11961185
iter->he = NULL;
11971186

11981187
return 0;

tools/perf/util/hist.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,18 +132,20 @@ struct hist_entry_iter {
132132
int total;
133133
int curr;
134134

135-
bool hide_unresolved;
136-
137135
struct evsel *evsel;
138136
struct perf_sample *sample;
139137
struct hist_entry *he;
140138
struct symbol *parent;
141-
void *priv;
139+
140+
struct mem_info *mi;
141+
struct branch_info *bi;
142+
struct hist_entry **he_cache;
142143

143144
const struct hist_iter_ops *ops;
144145
/* user-defined callback function (optional) */
145146
int (*add_entry_cb)(struct hist_entry_iter *iter,
146147
struct addr_location *al, bool single, void *arg);
148+
bool hide_unresolved;
147149
};
148150

149151
extern const struct hist_iter_ops hist_iter_normal;

0 commit comments

Comments
 (0)