1 // SPDX-License-Identifier: GPL-2.0
2 #include <test_progs.h>
3 #include "bpf_ma_ttrace.skel.h"
4
5 #define NR_ELEMS 4096
6
7 /*
8 * The first free_bulk() starts RCU tasks trace GP. The rest of the elements are
9 * deleted while it's in flight. They should be freed without further alloc or
10 * free from this map.
11 */
test_bpf_ma_ttrace(void)12 void test_bpf_ma_ttrace(void)
13 {
14 LIBBPF_OPTS(bpf_test_run_opts, opts);
15 struct bpf_ma_ttrace *skel;
16 __u32 cnt = NR_ELEMS;
17 long *vals = NULL;
18 int *keys = NULL;
19 int i, err, fd, nr_cpus;
20
21 skel = bpf_ma_ttrace__open_and_load();
22 if (!ASSERT_OK_PTR(skel, "open_and_load"))
23 return;
24 nr_cpus = libbpf_num_possible_cpus();
25 if (!ASSERT_GT(nr_cpus, 0, "nr_cpus"))
26 goto out;
27 skel->bss->nr_cpus = nr_cpus;
28
29 keys = calloc(NR_ELEMS, sizeof(*keys));
30 vals = calloc(NR_ELEMS, sizeof(*vals));
31 if (!ASSERT_OK_PTR(keys, "keys") || !ASSERT_OK_PTR(vals, "vals"))
32 goto out;
33 for (i = 0; i < NR_ELEMS; i++)
34 keys[i] = i;
35
36 fd = bpf_map__fd(skel->maps.htab);
37 err = bpf_map_update_batch(fd, keys, vals, &cnt, NULL);
38 if (!ASSERT_OK(err, "update_batch") || !ASSERT_EQ(cnt, NR_ELEMS, "update_cnt"))
39 goto out;
40 err = bpf_map_delete_batch(fd, keys, &cnt, NULL);
41 if (!ASSERT_OK(err, "delete_batch") || !ASSERT_EQ(cnt, NR_ELEMS, "delete_cnt"))
42 goto out;
43
44 /* Wait for all __free_rcu() callbacks to finish */
45 for (i = 0; i < 300; i++) {
46 err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.check_ttrace), &opts);
47 if (!ASSERT_OK(err, "test_run") || !ASSERT_OK(opts.retval, "retval"))
48 goto out;
49 if (!skel->bss->in_progress)
50 break;
51 usleep(100000);
52 }
53 ASSERT_EQ(skel->bss->nr_caches, nr_cpus, "nr_caches");
54 ASSERT_EQ(skel->bss->in_progress, 0, "in_progress");
55 ASSERT_EQ(skel->bss->not_freed, 0, "not_freed");
56 out:
57 free(keys);
58 free(vals);
59 bpf_ma_ttrace__destroy(skel);
60 }
61