99 lines · c
1// SPDX-License-Identifier: GPL-2.02/* Copyright (C) 2023. Huawei Technologies Co., Ltd */3#include <test_progs.h>4 5#include "normal_map_btf.skel.h"6#include "map_in_map_btf.skel.h"7 8static void do_test_normal_map_btf(void)9{10 struct normal_map_btf *skel;11 int i, err, new_fd = -1;12 int map_fd_arr[64];13 14 skel = normal_map_btf__open_and_load();15 if (!ASSERT_OK_PTR(skel, "open_load"))16 return;17 18 err = normal_map_btf__attach(skel);19 if (!ASSERT_OK(err, "attach"))20 goto out;21 22 skel->bss->pid = getpid();23 usleep(1);24 ASSERT_TRUE(skel->bss->done, "done");25 26 /* Use percpu_array to slow bpf_map_free_deferred() down.27 * The memory allocation may fail, so doesn't check the returned fd.28 */29 for (i = 0; i < ARRAY_SIZE(map_fd_arr); i++)30 map_fd_arr[i] = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, NULL, 4, 4, 256, NULL);31 32 /* Close array fd later */33 new_fd = dup(bpf_map__fd(skel->maps.array));34out:35 normal_map_btf__destroy(skel);36 if (new_fd < 0)37 return;38 /* Use kern_sync_rcu() to wait for the start of the free of the bpf39 * program and use an assumed delay to wait for the release of the map40 * btf which is held by other maps (e.g, bss). After that, array map41 * holds the last reference of map btf.42 */43 kern_sync_rcu();44 usleep(4000);45 /* Spawn multiple kworkers to delay the invocation of46 * bpf_map_free_deferred() for array map.47 */48 for (i = 0; i < ARRAY_SIZE(map_fd_arr); i++) {49 if (map_fd_arr[i] < 0)50 continue;51 close(map_fd_arr[i]);52 }53 close(new_fd);54}55 56static void do_test_map_in_map_btf(void)57{58 int err, zero = 0, new_fd = -1;59 struct map_in_map_btf *skel;60 61 skel = map_in_map_btf__open_and_load();62 if (!ASSERT_OK_PTR(skel, "open_load"))63 return;64 65 err = map_in_map_btf__attach(skel);66 if (!ASSERT_OK(err, "attach"))67 goto out;68 69 skel->bss->pid = getpid();70 usleep(1);71 ASSERT_TRUE(skel->bss->done, "done");72 73 /* Close inner_array fd later */74 new_fd = dup(bpf_map__fd(skel->maps.inner_array));75 /* Defer the free of inner_array */76 err = bpf_map__delete_elem(skel->maps.outer_array, &zero, sizeof(zero), 0);77 ASSERT_OK(err, "delete inner map");78out:79 map_in_map_btf__destroy(skel);80 if (new_fd < 0)81 return;82 /* Use kern_sync_rcu() to wait for the start of the free of the bpf83 * program and use an assumed delay to wait for the free of the outer84 * map and the release of map btf. After that, inner map holds the last85 * reference of map btf.86 */87 kern_sync_rcu();88 usleep(10000);89 close(new_fd);90}91 92void test_map_btf(void)93{94 if (test__start_subtest("array_btf"))95 do_test_normal_map_btf();96 if (test__start_subtest("inner_array_btf"))97 do_test_map_in_map_btf();98}99