Skip to content

Commit 2669dde

Browse files
kkdwvdAlexei Starovoitov
authored andcommitted
selftests/bpf: Fix map_kptr grace period wait
Commit c27cea4 ("rcu: Re-implement RCU Tasks Trace in terms of SRCU-fast") broke map_kptr selftest since it removed the function we were kprobing. Use a new kfunc that invokes call_rcu_tasks_trace and sets a program provided pointer to an integer to 1. Technically this can be unsafe if the memory being written to from the callback disappears, but this is just for usage in a test where we ensure we spin until we see the value to be set to 1, so it's ok. Reported-by: Shung-Hsi Yu <shung-hsi.yu@suse.com> Fixes: c27cea4 ("rcu: Re-implement RCU Tasks Trace in terms of SRCU-fast") Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com> Link: https://lore.kernel.org/r/20260211185747.3630539-1-memxor@gmail.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
1 parent 48f624c commit 2669dde

4 files changed

Lines changed: 39 additions & 35 deletions

File tree

tools/testing/selftests/bpf/prog_tests/map_kptr.c

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -118,15 +118,16 @@ static void test_map_kptr_success(bool test_run)
118118

119119
static int kern_sync_rcu_tasks_trace(struct rcu_tasks_trace_gp *rcu)
120120
{
121-
long gp_seq = READ_ONCE(rcu->bss->gp_seq);
122121
LIBBPF_OPTS(bpf_test_run_opts, opts);
122+
int ret;
123123

124-
if (!ASSERT_OK(bpf_prog_test_run_opts(bpf_program__fd(rcu->progs.do_call_rcu_tasks_trace),
125-
&opts), "do_call_rcu_tasks_trace"))
124+
WRITE_ONCE(rcu->bss->done, 0);
125+
ret = bpf_prog_test_run_opts(bpf_program__fd(rcu->progs.call_rcu_tasks_trace), &opts);
126+
if (!ASSERT_OK(ret, "call_rcu_tasks_trace"))
126127
return -EFAULT;
127-
if (!ASSERT_OK(opts.retval, "opts.retval == 0"))
128+
if (!ASSERT_OK(opts.retval, "call_rcu_tasks_trace retval"))
128129
return -EFAULT;
129-
while (gp_seq == READ_ONCE(rcu->bss->gp_seq))
130+
while (!READ_ONCE(rcu->bss->done))
130131
sched_yield();
131132
return 0;
132133
}
@@ -159,8 +160,6 @@ void serial_test_map_kptr(void)
159160
skel = rcu_tasks_trace_gp__open_and_load();
160161
if (!ASSERT_OK_PTR(skel, "rcu_tasks_trace_gp__open_and_load"))
161162
return;
162-
if (!ASSERT_OK(rcu_tasks_trace_gp__attach(skel), "rcu_tasks_trace_gp__attach"))
163-
goto end;
164163

165164
if (test__start_subtest("success-map")) {
166165
test_map_kptr_success(true);
@@ -180,7 +179,5 @@ void serial_test_map_kptr(void)
180179
test_map_kptr_success(true);
181180
}
182181

183-
end:
184182
rcu_tasks_trace_gp__destroy(skel);
185-
return;
186183
}
Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,14 @@
11
// SPDX-License-Identifier: GPL-2.0
22
#include <vmlinux.h>
3-
#include <bpf/bpf_tracing.h>
43
#include <bpf/bpf_helpers.h>
4+
#include "../test_kmods/bpf_testmod_kfunc.h"
55

6-
struct task_ls_map {
7-
__uint(type, BPF_MAP_TYPE_TASK_STORAGE);
8-
__uint(map_flags, BPF_F_NO_PREALLOC);
9-
__type(key, int);
10-
__type(value, int);
11-
} task_ls_map SEC(".maps");
12-
13-
long gp_seq;
6+
int done;
147

158
SEC("syscall")
16-
int do_call_rcu_tasks_trace(void *ctx)
17-
{
18-
struct task_struct *current;
19-
int *v;
20-
21-
current = bpf_get_current_task_btf();
22-
v = bpf_task_storage_get(&task_ls_map, current, NULL, BPF_LOCAL_STORAGE_GET_F_CREATE);
23-
if (!v)
24-
return 1;
25-
/* Invoke call_rcu_tasks_trace */
26-
return bpf_task_storage_delete(&task_ls_map, current);
27-
}
28-
29-
SEC("kprobe/rcu_tasks_trace_postgp")
30-
int rcu_tasks_trace_postgp(void *ctx)
9+
int call_rcu_tasks_trace(void *ctx)
3110
{
32-
__sync_add_and_fetch(&gp_seq, 1);
33-
return 0;
11+
return bpf_kfunc_call_test_call_rcu_tasks_trace(&done);
3412
}
3513

3614
char _license[] SEC("license") = "GPL";

tools/testing/selftests/bpf/test_kmods/bpf_testmod.c

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include <linux/in6.h>
1919
#include <linux/un.h>
2020
#include <linux/filter.h>
21+
#include <linux/rcupdate_trace.h>
2122
#include <net/sock.h>
2223
#include <linux/namei.h>
2324
#include "bpf_testmod.h"
@@ -885,6 +886,32 @@ __bpf_kfunc void bpf_kfunc_call_test_sleepable(void)
885886
{
886887
}
887888

889+
struct bpf_kfunc_rcu_tasks_trace_data {
890+
struct rcu_head rcu;
891+
int *done;
892+
};
893+
894+
static void bpf_kfunc_rcu_tasks_trace_cb(struct rcu_head *rhp)
895+
{
896+
struct bpf_kfunc_rcu_tasks_trace_data *data;
897+
898+
data = container_of(rhp, struct bpf_kfunc_rcu_tasks_trace_data, rcu);
899+
WRITE_ONCE(*data->done, 1);
900+
kfree(data);
901+
}
902+
903+
__bpf_kfunc int bpf_kfunc_call_test_call_rcu_tasks_trace(int *done)
904+
{
905+
struct bpf_kfunc_rcu_tasks_trace_data *data;
906+
907+
data = kmalloc(sizeof(*data), GFP_ATOMIC);
908+
if (!data)
909+
return -ENOMEM;
910+
data->done = done;
911+
call_rcu_tasks_trace(&data->rcu, bpf_kfunc_rcu_tasks_trace_cb);
912+
return 0;
913+
}
914+
888915
__bpf_kfunc int bpf_kfunc_init_sock(struct init_sock_args *args)
889916
{
890917
int proto;
@@ -1222,6 +1249,7 @@ BTF_ID_FLAGS(func, bpf_kfunc_call_test_destructive, KF_DESTRUCTIVE)
12221249
BTF_ID_FLAGS(func, bpf_kfunc_call_test_static_unused_arg)
12231250
BTF_ID_FLAGS(func, bpf_kfunc_call_test_offset)
12241251
BTF_ID_FLAGS(func, bpf_kfunc_call_test_sleepable, KF_SLEEPABLE)
1252+
BTF_ID_FLAGS(func, bpf_kfunc_call_test_call_rcu_tasks_trace)
12251253
BTF_ID_FLAGS(func, bpf_kfunc_init_sock, KF_SLEEPABLE)
12261254
BTF_ID_FLAGS(func, bpf_kfunc_close_sock, KF_SLEEPABLE)
12271255
BTF_ID_FLAGS(func, bpf_kfunc_call_kernel_connect, KF_SLEEPABLE)

tools/testing/selftests/bpf/test_kmods/bpf_testmod_kfunc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ void bpf_kfunc_call_test_mem_len_fail2(__u64 *mem, int len) __ksym;
118118

119119
void bpf_kfunc_call_test_destructive(void) __ksym;
120120
void bpf_kfunc_call_test_sleepable(void) __ksym;
121+
int bpf_kfunc_call_test_call_rcu_tasks_trace(int *done) __ksym;
121122

122123
void bpf_kfunc_call_test_offset(struct prog_test_ref_kfunc *p);
123124
struct prog_test_member *bpf_kfunc_call_memb_acquire(void);

0 commit comments

Comments
 (0)