Commit 8c25c447 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'perf-tools-fixes-for-v5.14-2021-07-18' of...

Merge tag 'perf-tools-fixes-for-v5.14-2021-07-18' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

Pull perf tools fixes from Arnaldo Carvalho de Melo:

 - Skip invalid hybrid PMU on hybrid systems when the atom (little) CPUs
   are offlined.

 - Fix 'perf test' problems related to the recently added hybrid
   (BIG/little) code.

 - Split ARM's coresight (hw tracing) decode by aux records to avoid
   fatal decoding errors.

 - Fix add event failure in 'perf probe' when running 32-bit perf in a
   64-bit kernel.

 - Fix 'perf sched record' failure when CONFIG_SCHEDSTATS is not set.

 - Fix memory and refcount leaks detected by ASAn when running 'perf
   test', should be clean of warnings now.

 - Remove broken definition of __LITTLE_ENDIAN from tools'
   linux/kconfig.h, which was breaking the build in some systems.

 - Cast PTHREAD_STACK_MIN to int as it may turn into 'long
   sysconf(__SC_THREAD_STACK_MIN_VALUE), breaking the build in some
   systems.

 - Fix libperf build error with LIBPFM4=1...
parents f0eb870a b0f00855
...@@ -20,5 +20,6 @@ ...@@ -20,5 +20,6 @@
#define __ARCH_WANT_SET_GET_RLIMIT #define __ARCH_WANT_SET_GET_RLIMIT
#define __ARCH_WANT_TIME32_SYSCALLS #define __ARCH_WANT_TIME32_SYSCALLS
#define __ARCH_WANT_SYS_CLONE3 #define __ARCH_WANT_SYS_CLONE3
#define __ARCH_WANT_MEMFD_SECRET
#include <asm-generic/unistd.h> #include <asm-generic/unistd.h>
...@@ -4,12 +4,6 @@ ...@@ -4,12 +4,6 @@
/* CONFIG_CC_VERSION_TEXT (Do not delete this comment. See help in Kconfig) */ /* CONFIG_CC_VERSION_TEXT (Do not delete this comment. See help in Kconfig) */
#ifdef CONFIG_CPU_BIG_ENDIAN
#define __BIG_ENDIAN 4321
#else
#define __LITTLE_ENDIAN 1234
#endif
#define __ARG_PLACEHOLDER_1 0, #define __ARG_PLACEHOLDER_1 0,
#define __take_second_arg(__ignored, val, ...) val #define __take_second_arg(__ignored, val, ...) val
......
...@@ -873,8 +873,13 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule) ...@@ -873,8 +873,13 @@ __SYSCALL(__NR_landlock_add_rule, sys_landlock_add_rule)
#define __NR_landlock_restrict_self 446 #define __NR_landlock_restrict_self 446
__SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self) __SYSCALL(__NR_landlock_restrict_self, sys_landlock_restrict_self)
#ifdef __ARCH_WANT_MEMFD_SECRET
#define __NR_memfd_secret 447
__SYSCALL(__NR_memfd_secret, sys_memfd_secret)
#endif
#undef __NR_syscalls #undef __NR_syscalls
#define __NR_syscalls 447 #define __NR_syscalls 448
/* /*
* 32 bit systems traditionally used different * 32 bit systems traditionally used different
......
...@@ -368,6 +368,7 @@ ...@@ -368,6 +368,7 @@
444 common landlock_create_ruleset sys_landlock_create_ruleset 444 common landlock_create_ruleset sys_landlock_create_ruleset
445 common landlock_add_rule sys_landlock_add_rule 445 common landlock_add_rule sys_landlock_add_rule
446 common landlock_restrict_self sys_landlock_restrict_self 446 common landlock_restrict_self sys_landlock_restrict_self
447 common memfd_secret sys_memfd_secret
# #
# Due to a historical design error, certain syscalls are numbered differently # Due to a historical design error, certain syscalls are numbered differently
......
...@@ -361,9 +361,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename, ...@@ -361,9 +361,10 @@ static struct dso *findnew_dso(int pid, int tid, const char *filename,
dso = machine__findnew_dso_id(machine, filename, id); dso = machine__findnew_dso_id(machine, filename, id);
} }
if (dso) if (dso) {
nsinfo__put(dso->nsinfo);
dso->nsinfo = nsi; dso->nsinfo = nsi;
else } else
nsinfo__put(nsi); nsinfo__put(nsi);
thread__put(thread); thread__put(thread);
...@@ -992,8 +993,10 @@ int cmd_inject(int argc, const char **argv) ...@@ -992,8 +993,10 @@ int cmd_inject(int argc, const char **argv)
data.path = inject.input_name; data.path = inject.input_name;
inject.session = perf_session__new(&data, inject.output.is_pipe, &inject.tool); inject.session = perf_session__new(&data, inject.output.is_pipe, &inject.tool);
if (IS_ERR(inject.session)) if (IS_ERR(inject.session)) {
return PTR_ERR(inject.session); ret = PTR_ERR(inject.session);
goto out_close_output;
}
if (zstd_init(&(inject.session->zstd_data), 0) < 0) if (zstd_init(&(inject.session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed.\n"); pr_warning("Decompression initialization failed.\n");
...@@ -1035,6 +1038,8 @@ int cmd_inject(int argc, const char **argv) ...@@ -1035,6 +1038,8 @@ int cmd_inject(int argc, const char **argv)
out_delete: out_delete:
zstd_fini(&(inject.session->zstd_data)); zstd_fini(&(inject.session->zstd_data));
perf_session__delete(inject.session); perf_session__delete(inject.session);
out_close_output:
perf_data__close(&inject.output);
free(inject.itrace_synth_opts.vm_tm_corr_args); free(inject.itrace_synth_opts.vm_tm_corr_args);
return ret; return ret;
} }
...@@ -1175,6 +1175,8 @@ int cmd_report(int argc, const char **argv) ...@@ -1175,6 +1175,8 @@ int cmd_report(int argc, const char **argv)
.annotation_opts = annotation__default_options, .annotation_opts = annotation__default_options,
.skip_empty = true, .skip_empty = true,
}; };
char *sort_order_help = sort_help("sort by key(s):");
char *field_order_help = sort_help("output field(s): overhead period sample ");
const struct option options[] = { const struct option options[] = {
OPT_STRING('i', "input", &input_name, "file", OPT_STRING('i', "input", &input_name, "file",
"input file name"), "input file name"),
...@@ -1209,9 +1211,9 @@ int cmd_report(int argc, const char **argv) ...@@ -1209,9 +1211,9 @@ int cmd_report(int argc, const char **argv)
OPT_BOOLEAN(0, "header-only", &report.header_only, OPT_BOOLEAN(0, "header-only", &report.header_only,
"Show only data header."), "Show only data header."),
OPT_STRING('s', "sort", &sort_order, "key[,key2...]", OPT_STRING('s', "sort", &sort_order, "key[,key2...]",
sort_help("sort by key(s):")), sort_order_help),
OPT_STRING('F', "fields", &field_order, "key[,keys...]", OPT_STRING('F', "fields", &field_order, "key[,keys...]",
sort_help("output field(s): overhead period sample ")), field_order_help),
OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization, OPT_BOOLEAN(0, "show-cpu-utilization", &symbol_conf.show_cpu_utilization,
"Show sample percentage for different cpu modes"), "Show sample percentage for different cpu modes"),
OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization, OPT_BOOLEAN_FLAG(0, "showcpuutilization", &symbol_conf.show_cpu_utilization,
...@@ -1344,11 +1346,11 @@ int cmd_report(int argc, const char **argv) ...@@ -1344,11 +1346,11 @@ int cmd_report(int argc, const char **argv)
char sort_tmp[128]; char sort_tmp[128];
if (ret < 0) if (ret < 0)
return ret; goto exit;
ret = perf_config(report__config, &report); ret = perf_config(report__config, &report);
if (ret) if (ret)
return ret; goto exit;
argc = parse_options(argc, argv, options, report_usage, 0); argc = parse_options(argc, argv, options, report_usage, 0);
if (argc) { if (argc) {
...@@ -1362,8 +1364,10 @@ int cmd_report(int argc, const char **argv) ...@@ -1362,8 +1364,10 @@ int cmd_report(int argc, const char **argv)
report.symbol_filter_str = argv[0]; report.symbol_filter_str = argv[0];
} }
if (annotate_check_args(&report.annotation_opts) < 0) if (annotate_check_args(&report.annotation_opts) < 0) {
return -EINVAL; ret = -EINVAL;
goto exit;
}
if (report.mmaps_mode) if (report.mmaps_mode)
report.tasks_mode = true; report.tasks_mode = true;
...@@ -1377,12 +1381,14 @@ int cmd_report(int argc, const char **argv) ...@@ -1377,12 +1381,14 @@ int cmd_report(int argc, const char **argv)
if (symbol_conf.vmlinux_name && if (symbol_conf.vmlinux_name &&
access(symbol_conf.vmlinux_name, R_OK)) { access(symbol_conf.vmlinux_name, R_OK)) {
pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name); pr_err("Invalid file: %s\n", symbol_conf.vmlinux_name);
return -EINVAL; ret = -EINVAL;
goto exit;
} }
if (symbol_conf.kallsyms_name && if (symbol_conf.kallsyms_name &&
access(symbol_conf.kallsyms_name, R_OK)) { access(symbol_conf.kallsyms_name, R_OK)) {
pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name); pr_err("Invalid file: %s\n", symbol_conf.kallsyms_name);
return -EINVAL; ret = -EINVAL;
goto exit;
} }
if (report.inverted_callchain) if (report.inverted_callchain)
...@@ -1406,12 +1412,14 @@ int cmd_report(int argc, const char **argv) ...@@ -1406,12 +1412,14 @@ int cmd_report(int argc, const char **argv)
repeat: repeat:
session = perf_session__new(&data, false, &report.tool); session = perf_session__new(&data, false, &report.tool);
if (IS_ERR(session)) if (IS_ERR(session)) {
return PTR_ERR(session); ret = PTR_ERR(session);
goto exit;
}
ret = evswitch__init(&report.evswitch, session->evlist, stderr); ret = evswitch__init(&report.evswitch, session->evlist, stderr);
if (ret) if (ret)
return ret; goto exit;
if (zstd_init(&(session->zstd_data), 0) < 0) if (zstd_init(&(session->zstd_data), 0) < 0)
pr_warning("Decompression initialization failed. Reported data may be incomplete.\n"); pr_warning("Decompression initialization failed. Reported data may be incomplete.\n");
...@@ -1646,5 +1654,8 @@ int cmd_report(int argc, const char **argv) ...@@ -1646,5 +1654,8 @@ int cmd_report(int argc, const char **argv)
zstd_fini(&(session->zstd_data)); zstd_fini(&(session->zstd_data));
perf_session__delete(session); perf_session__delete(session);
exit:
free(sort_order_help);
free(field_order_help);
return ret; return ret;
} }
...@@ -670,7 +670,7 @@ static void create_tasks(struct perf_sched *sched) ...@@ -670,7 +670,7 @@ static void create_tasks(struct perf_sched *sched)
err = pthread_attr_init(&attr); err = pthread_attr_init(&attr);
BUG_ON(err); BUG_ON(err);
err = pthread_attr_setstacksize(&attr, err = pthread_attr_setstacksize(&attr,
(size_t) max(16 * 1024, PTHREAD_STACK_MIN)); (size_t) max(16 * 1024, (int)PTHREAD_STACK_MIN));
BUG_ON(err); BUG_ON(err);
err = pthread_mutex_lock(&sched->start_work_mutex); err = pthread_mutex_lock(&sched->start_work_mutex);
BUG_ON(err); BUG_ON(err);
...@@ -3335,6 +3335,16 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options ...@@ -3335,6 +3335,16 @@ static void setup_sorting(struct perf_sched *sched, const struct option *options
sort_dimension__add("pid", &sched->cmp_pid); sort_dimension__add("pid", &sched->cmp_pid);
} }
static bool schedstat_events_exposed(void)
{
/*
* Select "sched:sched_stat_wait" event to check
* whether schedstat tracepoints are exposed.
*/
return IS_ERR(trace_event__tp_format("sched", "sched_stat_wait")) ?
false : true;
}
static int __cmd_record(int argc, const char **argv) static int __cmd_record(int argc, const char **argv)
{ {
unsigned int rec_argc, i, j; unsigned int rec_argc, i, j;
...@@ -3346,21 +3356,33 @@ static int __cmd_record(int argc, const char **argv) ...@@ -3346,21 +3356,33 @@ static int __cmd_record(int argc, const char **argv)
"-m", "1024", "-m", "1024",
"-c", "1", "-c", "1",
"-e", "sched:sched_switch", "-e", "sched:sched_switch",
"-e", "sched:sched_stat_wait",
"-e", "sched:sched_stat_sleep",
"-e", "sched:sched_stat_iowait",
"-e", "sched:sched_stat_runtime", "-e", "sched:sched_stat_runtime",
"-e", "sched:sched_process_fork", "-e", "sched:sched_process_fork",
"-e", "sched:sched_wakeup_new", "-e", "sched:sched_wakeup_new",
"-e", "sched:sched_migrate_task", "-e", "sched:sched_migrate_task",
}; };
/*
* The tracepoints trace_sched_stat_{wait, sleep, iowait}
* are not exposed to user if CONFIG_SCHEDSTATS is not set,
* to prevent "perf sched record" execution failure, determine
* whether to record schedstat events according to actual situation.
*/
const char * const schedstat_args[] = {
"-e", "sched:sched_stat_wait",
"-e", "sched:sched_stat_sleep",
"-e", "sched:sched_stat_iowait",
};
unsigned int schedstat_argc = schedstat_events_exposed() ?
ARRAY_SIZE(schedstat_args) : 0;
struct tep_event *waking_event; struct tep_event *waking_event;
/* /*
* +2 for either "-e", "sched:sched_wakeup" or * +2 for either "-e", "sched:sched_wakeup" or
* "-e", "sched:sched_waking" * "-e", "sched:sched_waking"
*/ */
rec_argc = ARRAY_SIZE(record_args) + 2 + argc - 1; rec_argc = ARRAY_SIZE(record_args) + 2 + schedstat_argc + argc - 1;
rec_argv = calloc(rec_argc + 1, sizeof(char *)); rec_argv = calloc(rec_argc + 1, sizeof(char *));
if (rec_argv == NULL) if (rec_argv == NULL)
...@@ -3376,6 +3398,9 @@ static int __cmd_record(int argc, const char **argv) ...@@ -3376,6 +3398,9 @@ static int __cmd_record(int argc, const char **argv)
else else
rec_argv[i++] = strdup("sched:sched_wakeup"); rec_argv[i++] = strdup("sched:sched_wakeup");
for (j = 0; j < schedstat_argc; j++)
rec_argv[i++] = strdup(schedstat_args[j]);
for (j = 1; j < (unsigned int)argc; j++, i++) for (j = 1; j < (unsigned int)argc; j++, i++)
rec_argv[i] = argv[j]; rec_argv[i] = argv[j];
......
...@@ -2601,6 +2601,12 @@ static void perf_script__exit_per_event_dump_stats(struct perf_script *script) ...@@ -2601,6 +2601,12 @@ static void perf_script__exit_per_event_dump_stats(struct perf_script *script)
} }
} }
static void perf_script__exit(struct perf_script *script)
{
perf_thread_map__put(script->threads);
perf_cpu_map__put(script->cpus);
}
static int __cmd_script(struct perf_script *script) static int __cmd_script(struct perf_script *script)
{ {
int ret; int ret;
...@@ -4143,8 +4149,10 @@ int cmd_script(int argc, const char **argv) ...@@ -4143,8 +4149,10 @@ int cmd_script(int argc, const char **argv)
zfree(&script.ptime_range); zfree(&script.ptime_range);
} }
zstd_fini(&(session->zstd_data));
evlist__free_stats(session->evlist); evlist__free_stats(session->evlist);
perf_session__delete(session); perf_session__delete(session);
perf_script__exit(&script);
if (script_started) if (script_started)
cleanup_scripting(); cleanup_scripting();
......
...@@ -2445,9 +2445,6 @@ int cmd_stat(int argc, const char **argv) ...@@ -2445,9 +2445,6 @@ int cmd_stat(int argc, const char **argv)
evlist__check_cpu_maps(evsel_list); evlist__check_cpu_maps(evsel_list);
if (perf_pmu__has_hybrid())
stat_config.no_merge = true;
/* /*
* Initialize thread_map with comm names, * Initialize thread_map with comm names,
* so we could print it out on output. * so we could print it out on output.
......
...@@ -2266,6 +2266,14 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam ...@@ -2266,6 +2266,14 @@ static void *syscall__augmented_args(struct syscall *sc, struct perf_sample *sam
return augmented_args; return augmented_args;
} }
static void syscall__exit(struct syscall *sc)
{
if (!sc)
return;
free(sc->arg_fmt);
}
static int trace__sys_enter(struct trace *trace, struct evsel *evsel, static int trace__sys_enter(struct trace *trace, struct evsel *evsel,
union perf_event *event __maybe_unused, union perf_event *event __maybe_unused,
struct perf_sample *sample) struct perf_sample *sample)
...@@ -3095,6 +3103,21 @@ static struct evsel *evsel__new_pgfault(u64 config) ...@@ -3095,6 +3103,21 @@ static struct evsel *evsel__new_pgfault(u64 config)
return evsel; return evsel;
} }
static void evlist__free_syscall_tp_fields(struct evlist *evlist)
{
struct evsel *evsel;
evlist__for_each_entry(evlist, evsel) {
struct evsel_trace *et = evsel->priv;
if (!et || !evsel->tp_format || strcmp(evsel->tp_format->system, "syscalls"))
continue;
free(et->fmt);
free(et);
}
}
static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample) static void trace__handle_event(struct trace *trace, union perf_event *event, struct perf_sample *sample)
{ {
const u32 type = event->header.type; const u32 type = event->header.type;
...@@ -4130,7 +4153,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv) ...@@ -4130,7 +4153,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
out_delete_evlist: out_delete_evlist:
trace__symbols__exit(trace); trace__symbols__exit(trace);
evlist__free_syscall_tp_fields(evlist);
evlist__delete(evlist); evlist__delete(evlist);
cgroup__put(trace->cgroup); cgroup__put(trace->cgroup);
trace->evlist = NULL; trace->evlist = NULL;
...@@ -4636,6 +4659,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str, ...@@ -4636,6 +4659,9 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
err = parse_events_option(&o, lists[0], 0); err = parse_events_option(&o, lists[0], 0);
} }
out: out:
free(strace_groups_dir);
free(lists[0]);
free(lists[1]);
if (sep) if (sep)
*sep = ','; *sep = ',';
...@@ -4701,6 +4727,21 @@ static int trace__config(const char *var, const char *value, void *arg) ...@@ -4701,6 +4727,21 @@ static int trace__config(const char *var, const char *value, void *arg)
return err; return err;
} }
static void trace__exit(struct trace *trace)
{
int i;
strlist__delete(trace->ev_qualifier);
free(trace->ev_qualifier_ids.entries);
if (trace->syscalls.table) {
for (i = 0; i <= trace->sctbl->syscalls.max_id; i++)
syscall__exit(&trace->syscalls.table[i]);
free(trace->syscalls.table);
}
syscalltbl__delete(trace->sctbl);
zfree(&trace->perfconfig_events);
}
int cmd_trace(int argc, const char **argv) int cmd_trace(int argc, const char **argv)
{ {
const char *trace_usage[] = { const char *trace_usage[] = {
...@@ -5135,6 +5176,6 @@ int cmd_trace(int argc, const char **argv) ...@@ -5135,6 +5176,6 @@ int cmd_trace(int argc, const char **argv)
if (output_name != NULL) if (output_name != NULL)
fclose(trace.output); fclose(trace.output);
out: out:
zfree(&trace.perfconfig_events); trace__exit(&trace);
return err; return err;
} }
// SPDX-License-Identifier: GPL-2.0 // SPDX-License-Identifier: GPL-2.0
#include <errno.h> #include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
...@@ -276,6 +277,7 @@ static int __test__bpf(int idx) ...@@ -276,6 +277,7 @@ static int __test__bpf(int idx)
} }
out: out:
free(obj_buf);
bpf__clear(); bpf__clear();
return ret; return ret;
} }
......
...@@ -88,6 +88,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu ...@@ -88,6 +88,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
struct evsel *evsel; struct evsel *evsel;
struct event_name tmp; struct event_name tmp;
struct evlist *evlist = evlist__new_default(); struct evlist *evlist = evlist__new_default();
char *unit = strdup("KRAVA");
TEST_ASSERT_VAL("failed to get evlist", evlist); TEST_ASSERT_VAL("failed to get evlist", evlist);
...@@ -98,7 +99,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu ...@@ -98,7 +99,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123); perf_evlist__id_add(&evlist->core, &evsel->core, 0, 0, 123);
evsel->unit = strdup("KRAVA"); evsel->unit = unit;
TEST_ASSERT_VAL("failed to synthesize attr update unit", TEST_ASSERT_VAL("failed to synthesize attr update unit",
!perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit)); !perf_event__synthesize_event_update_unit(NULL, evsel, process_event_unit));
...@@ -118,6 +119,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu ...@@ -118,6 +119,7 @@ int test__event_update(struct test *test __maybe_unused, int subtest __maybe_unu
TEST_ASSERT_VAL("failed to synthesize attr update cpus", TEST_ASSERT_VAL("failed to synthesize attr update cpus",
!perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus)); !perf_event__synthesize_event_update_cpus(&tmp.tool, evsel, process_event_cpus));
perf_cpu_map__put(evsel->core.own_cpus); free(unit);
evlist__delete(evlist);
return 0; return 0;
} }
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "tests.h" #include "tests.h"
#include "debug.h" #include "debug.h"
#include "pmu.h" #include "pmu.h"
#include "pmu-hybrid.h"
#include <errno.h> #include <errno.h>
#include <linux/kernel.h> #include <linux/kernel.h>
...@@ -102,7 +103,7 @@ int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int ...@@ -102,7 +103,7 @@ int test__perf_evsel__roundtrip_name_test(struct test *test __maybe_unused, int
{ {
int err = 0, ret = 0; int err = 0, ret = 0;
if (perf_pmu__has_hybrid()) if (perf_pmu__has_hybrid() && perf_pmu__hybrid_mounted("cpu_atom"))
return perf_evsel__name_array_test(evsel__hw_names, 2); return perf_evsel__name_array_test(evsel__hw_names, 2);
err = perf_evsel__name_array_test(evsel__hw_names, 1); err = perf_evsel__name_array_test(evsel__hw_names, 1);
......
...@@ -116,5 +116,7 @@ int test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unus ...@@ -116,5 +116,7 @@ int test__maps__merge_in(struct test *t __maybe_unused, int subtest __maybe_unus
ret = check_maps(merged3, ARRAY_SIZE(merged3), &maps); ret = check_maps(merged3, ARRAY_SIZE(merged3), &maps);
TEST_ASSERT_VAL("merge check failed", !ret); TEST_ASSERT_VAL("merge check failed", !ret);
maps__exit(&maps);
return TEST_OK; return TEST_OK;
} }