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