1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (c) 2024 Benjamin Tissoires
5 #include "bpf_experimental.h"
6 #include <bpf/bpf_helpers.h>
8 #include "../test_kmods/bpf_testmod_kfunc.h"
10 char _license[] SEC("license") = "GPL";
14 struct bpf_timer timer; /* unused */
15 struct bpf_spin_lock lock; /* unused */
20 __uint(type, BPF_MAP_TYPE_HASH);
21 __uint(max_entries, 1000);
23 __type(value, struct hmap_elem);
27 __uint(type, BPF_MAP_TYPE_HASH);
28 __uint(map_flags, BPF_F_NO_PREALLOC);
29 __uint(max_entries, 1000);
31 __type(value, struct hmap_elem);
32 } hmap_malloc SEC(".maps");
40 __uint(type, BPF_MAP_TYPE_ARRAY);
41 __uint(max_entries, 2);
43 __type(value, struct elem);
47 __uint(type, BPF_MAP_TYPE_LRU_HASH);
48 __uint(max_entries, 4);
50 __type(value, struct elem);
56 static int test_elem_callback(void *map, int *key,
57 int (callback_fn)(void *map, int *key, void *value))
59 struct elem init = {}, *val;
62 if ((ok & (1 << *key) ||
63 (ok_sleepable & (1 << *key))))
67 bpf_map_update_elem(map, key, &init, 0))
70 val = bpf_map_lookup_elem(map, key);
74 val->ok_offset = *key;
77 if (bpf_wq_init(wq, map, 0) != 0)
80 if (bpf_wq_set_callback(wq, callback_fn, 0))
83 if (bpf_wq_start(wq, 0))
89 static int test_hmap_elem_callback(void *map, int *key,
90 int (callback_fn)(void *map, int *key, void *value))
92 struct hmap_elem init = {}, *val;
95 if ((ok & (1 << *key) ||
96 (ok_sleepable & (1 << *key))))
99 if (bpf_map_update_elem(map, key, &init, 0))
102 val = bpf_map_lookup_elem(map, key);
107 if (bpf_wq_init(wq, map, 0) != 0)
110 if (bpf_wq_set_callback(wq, callback_fn, 0))
113 if (bpf_wq_start(wq, 0))
119 /* callback for non sleepable workqueue */
120 static int wq_callback(void *map, int *key, void *value)
122 bpf_kfunc_common_test();
127 /* callback for sleepable workqueue */
128 static int wq_cb_sleepable(void *map, int *key, void *value)
130 struct elem *data = (struct elem *)value;
131 int offset = data->ok_offset;
136 bpf_kfunc_call_test_sleepable();
137 ok_sleepable |= (1 << offset);
142 /* test that workqueues can be used from an array */
144 long test_call_array_sleepable(void *ctx)
148 return test_elem_callback(&array, &key, wq_cb_sleepable);
152 /* Same test than above but from a sleepable context. */
154 long test_syscall_array_sleepable(void *ctx)
158 return test_elem_callback(&array, &key, wq_cb_sleepable);
162 /* test that workqueues can be used from a hashmap */
164 long test_call_hash_sleepable(void *ctx)
168 return test_hmap_elem_callback(&hmap, &key, wq_callback);
172 /* test that workqueues can be used from a hashmap with NO_PREALLOC. */
174 long test_call_hash_malloc_sleepable(void *ctx)
178 return test_hmap_elem_callback(&hmap_malloc, &key, wq_callback);
182 /* test that workqueues can be used from a LRU map */
184 long test_call_lru_sleepable(void *ctx)
188 return test_elem_callback(&lru, &key, wq_callback);