Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add tests for BPF_F_PRESERVE_ELEMS

Add tests for perf event array with and without BPF_F_PRESERVE_ELEMS.

Add a perf event to array via fd mfd. Without BPF_F_PRESERVE_ELEMS, the
perf event is removed when mfd is closed. With BPF_F_PRESERVE_ELEMS, the
perf event is removed when the map is freed.

Signed-off-by: Song Liu <songliubraving@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20200930224927.1936644-3-songliubraving@fb.com

authored by

Song Liu and committed by
Alexei Starovoitov
d6b42068 792caccc

+104
+66
tools/testing/selftests/bpf/prog_tests/pe_preserve_elems.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* Copyright (c) 2019 Facebook */ 3 + #include <test_progs.h> 4 + #include <linux/bpf.h> 5 + #include "test_pe_preserve_elems.skel.h" 6 + 7 + static int duration; 8 + 9 + static void test_one_map(struct bpf_map *map, struct bpf_program *prog, 10 + bool has_share_pe) 11 + { 12 + int err, key = 0, pfd = -1, mfd = bpf_map__fd(map); 13 + DECLARE_LIBBPF_OPTS(bpf_test_run_opts, opts); 14 + struct perf_event_attr attr = { 15 + .size = sizeof(struct perf_event_attr), 16 + .type = PERF_TYPE_SOFTWARE, 17 + .config = PERF_COUNT_SW_CPU_CLOCK, 18 + }; 19 + 20 + pfd = syscall(__NR_perf_event_open, &attr, 0 /* pid */, 21 + -1 /* cpu 0 */, -1 /* group id */, 0 /* flags */); 22 + if (CHECK(pfd < 0, "perf_event_open", "failed\n")) 23 + return; 24 + 25 + err = bpf_map_update_elem(mfd, &key, &pfd, BPF_ANY); 26 + close(pfd); 27 + if (CHECK(err < 0, "bpf_map_update_elem", "failed\n")) 28 + return; 29 + 30 + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); 31 + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) 32 + return; 33 + if (CHECK(opts.retval != 0, "bpf_perf_event_read_value", 34 + "failed with %d\n", opts.retval)) 35 + return; 36 + 37 + /* closing mfd, prog still holds a reference on map */ 38 + close(mfd); 39 + 40 + err = bpf_prog_test_run_opts(bpf_program__fd(prog), &opts); 41 + if (CHECK(err < 0, "bpf_prog_test_run_opts", "failed\n")) 42 + return; 43 + 44 + if (has_share_pe) { 45 + CHECK(opts.retval != 0, "bpf_perf_event_read_value", 46 + "failed with %d\n", opts.retval); 47 + } else { 48 + CHECK(opts.retval != -ENOENT, "bpf_perf_event_read_value", 49 + "should have failed with %d, but got %d\n", -ENOENT, 50 + opts.retval); 51 + } 52 + } 53 + 54 + void test_pe_preserve_elems(void) 55 + { 56 + struct test_pe_preserve_elems *skel; 57 + 58 + skel = test_pe_preserve_elems__open_and_load(); 59 + if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) 60 + return; 61 + 62 + test_one_map(skel->maps.array_1, skel->progs.read_array_1, false); 63 + test_one_map(skel->maps.array_2, skel->progs.read_array_2, true); 64 + 65 + test_pe_preserve_elems__destroy(skel); 66 + }
+38
tools/testing/selftests/bpf/progs/test_pe_preserve_elems.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + // Copyright (c) 2020 Facebook 3 + #include <linux/bpf.h> 4 + #include <bpf/bpf_helpers.h> 5 + #include <bpf/bpf_tracing.h> 6 + 7 + struct { 8 + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 9 + __uint(max_entries, 1); 10 + __uint(key_size, sizeof(int)); 11 + __uint(value_size, sizeof(int)); 12 + } array_1 SEC(".maps"); 13 + 14 + struct { 15 + __uint(type, BPF_MAP_TYPE_PERF_EVENT_ARRAY); 16 + __uint(max_entries, 1); 17 + __uint(key_size, sizeof(int)); 18 + __uint(value_size, sizeof(int)); 19 + __uint(map_flags, BPF_F_PRESERVE_ELEMS); 20 + } array_2 SEC(".maps"); 21 + 22 + SEC("raw_tp/sched_switch") 23 + int BPF_PROG(read_array_1) 24 + { 25 + struct bpf_perf_event_value val; 26 + 27 + return bpf_perf_event_read_value(&array_1, 0, &val, sizeof(val)); 28 + } 29 + 30 + SEC("raw_tp/task_rename") 31 + int BPF_PROG(read_array_2) 32 + { 33 + struct bpf_perf_event_value val; 34 + 35 + return bpf_perf_event_read_value(&array_2, 0, &val, sizeof(val)); 36 + } 37 + 38 + char LICENSE[] SEC("license") = "GPL";