blob: a1d41b1099401cbe6ce1ef16d2008638276e373f [file]
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include "bpf_ma_ttrace.skel.h"
#define NR_ELEMS 4096
/*
* The first free_bulk() starts RCU tasks trace GP. The rest of the elements are
* deleted while it's in flight. They should be freed without further alloc or
* free from this map.
*/
void test_bpf_ma_ttrace(void)
{
LIBBPF_OPTS(bpf_test_run_opts, opts);
struct bpf_ma_ttrace *skel;
__u32 cnt = NR_ELEMS;
long *vals = NULL;
int *keys = NULL;
int i, err, fd, nr_cpus;
skel = bpf_ma_ttrace__open_and_load();
if (!ASSERT_OK_PTR(skel, "open_and_load"))
return;
nr_cpus = libbpf_num_possible_cpus();
if (!ASSERT_GT(nr_cpus, 0, "nr_cpus"))
goto out;
skel->bss->nr_cpus = nr_cpus;
keys = calloc(NR_ELEMS, sizeof(*keys));
vals = calloc(NR_ELEMS, sizeof(*vals));
if (!ASSERT_OK_PTR(keys, "keys") || !ASSERT_OK_PTR(vals, "vals"))
goto out;
for (i = 0; i < NR_ELEMS; i++)
keys[i] = i;
fd = bpf_map__fd(skel->maps.htab);
err = bpf_map_update_batch(fd, keys, vals, &cnt, NULL);
if (!ASSERT_OK(err, "update_batch") || !ASSERT_EQ(cnt, NR_ELEMS, "update_cnt"))
goto out;
err = bpf_map_delete_batch(fd, keys, &cnt, NULL);
if (!ASSERT_OK(err, "delete_batch") || !ASSERT_EQ(cnt, NR_ELEMS, "delete_cnt"))
goto out;
/* Wait for all __free_rcu() callbacks to finish */
for (i = 0; i < 300; i++) {
err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.check_ttrace), &opts);
if (!ASSERT_OK(err, "test_run") || !ASSERT_OK(opts.retval, "retval"))
goto out;
if (!skel->bss->in_progress)
break;
usleep(100000);
}
ASSERT_EQ(skel->bss->nr_caches, nr_cpus, "nr_caches");
ASSERT_EQ(skel->bss->in_progress, 0, "in_progress");
ASSERT_EQ(skel->bss->not_freed, 0, "not_freed");
out:
free(keys);
free(vals);
bpf_ma_ttrace__destroy(skel);
}