perf sched: Fix memory leaks in 'perf sched map'

[ Upstream commit dc3a80c988 ]

It maintains per-cpu pointers for the current thread but it doesn't
release the refcounts.

Fixes: 5e89527869 ("perf sched: Move curr_thread initialization to perf_sched__map()")
Reviewed-by: Ian Rogers <irogers@google.com>
Tested-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250703014942.1369397-4-namhyung@kernel.org
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
Namhyung Kim 2025-07-02 18:49:37 -07:00 committed by Greg Kroah-Hartman
parent 4b3ab5f363
commit 31a549b3a2

View File

@ -1639,6 +1639,7 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,
const char *color = PERF_COLOR_NORMAL; const char *color = PERF_COLOR_NORMAL;
char stimestamp[32]; char stimestamp[32];
const char *str; const char *str;
int ret = -1;
BUG_ON(this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0); BUG_ON(this_cpu.cpu >= MAX_CPUS || this_cpu.cpu < 0);
@ -1669,17 +1670,20 @@ static int map_switch_event(struct perf_sched *sched, struct evsel *evsel,
sched_in = map__findnew_thread(sched, machine, -1, next_pid); sched_in = map__findnew_thread(sched, machine, -1, next_pid);
sched_out = map__findnew_thread(sched, machine, -1, prev_pid); sched_out = map__findnew_thread(sched, machine, -1, prev_pid);
if (sched_in == NULL || sched_out == NULL) if (sched_in == NULL || sched_out == NULL)
return -1; goto out;
tr = thread__get_runtime(sched_in); tr = thread__get_runtime(sched_in);
if (tr == NULL) { if (tr == NULL)
thread__put(sched_in); goto out;
return -1;
} thread__put(sched->curr_thread[this_cpu.cpu]);
thread__put(sched->curr_out_thread[this_cpu.cpu]);
sched->curr_thread[this_cpu.cpu] = thread__get(sched_in); sched->curr_thread[this_cpu.cpu] = thread__get(sched_in);
sched->curr_out_thread[this_cpu.cpu] = thread__get(sched_out); sched->curr_out_thread[this_cpu.cpu] = thread__get(sched_out);
ret = 0;
str = thread__comm_str(sched_in); str = thread__comm_str(sched_in);
new_shortname = 0; new_shortname = 0;
if (!tr->shortname[0]) { if (!tr->shortname[0]) {
@ -1774,12 +1778,10 @@ sched_out:
color_fprintf(stdout, color, "\n"); color_fprintf(stdout, color, "\n");
out: out:
if (sched->map.task_name) thread__put(sched_out);
thread__put(sched_out);
thread__put(sched_in); thread__put(sched_in);
return 0; return ret;
} }
static int process_sched_switch_event(const struct perf_tool *tool, static int process_sched_switch_event(const struct perf_tool *tool,
@ -3546,10 +3548,10 @@ static int perf_sched__map(struct perf_sched *sched)
sched->curr_out_thread = calloc(MAX_CPUS, sizeof(*(sched->curr_out_thread))); sched->curr_out_thread = calloc(MAX_CPUS, sizeof(*(sched->curr_out_thread)));
if (!sched->curr_out_thread) if (!sched->curr_out_thread)
return rc; goto out_free_curr_thread;
if (setup_cpus_switch_event(sched)) if (setup_cpus_switch_event(sched))
goto out_free_curr_thread; goto out_free_curr_out_thread;
if (setup_map_cpus(sched)) if (setup_map_cpus(sched))
goto out_free_cpus_switch_event; goto out_free_cpus_switch_event;
@ -3580,7 +3582,14 @@ out_put_map_cpus:
out_free_cpus_switch_event: out_free_cpus_switch_event:
free_cpus_switch_event(sched); free_cpus_switch_event(sched);
out_free_curr_out_thread:
for (int i = 0; i < MAX_CPUS; i++)
thread__put(sched->curr_out_thread[i]);
zfree(&sched->curr_out_thread);
out_free_curr_thread: out_free_curr_thread:
for (int i = 0; i < MAX_CPUS; i++)
thread__put(sched->curr_thread[i]);
zfree(&sched->curr_thread); zfree(&sched->curr_thread);
return rc; return rc;
} }