On Thu, Jan 20, 2022 at 9:30 AM Kenny Yu <kennyyu@xxxxxx> wrote: > > This adds a test for bpf iterator programs to make use of sleepable > bpf helpers. > > Signed-off-by: Kenny Yu <kennyyu@xxxxxx> > --- > .../selftests/bpf/prog_tests/bpf_iter.c | 19 ++++++++ > .../selftests/bpf/progs/bpf_iter_task.c | 47 +++++++++++++++++++ > 2 files changed, 66 insertions(+) > > diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c > index b84f859b1267..f6fb4f95513d 100644 > --- a/tools/testing/selftests/bpf/prog_tests/bpf_iter.c > +++ b/tools/testing/selftests/bpf/prog_tests/bpf_iter.c > @@ -138,6 +138,23 @@ static void test_task(void) > bpf_iter_task__destroy(skel); > } > > +static void test_task_sleepable(void) > +{ > + struct bpf_iter_task *skel; > + > + skel = bpf_iter_task__open_and_load(); > + if (CHECK(!skel, "bpf_iter_task__open_and_load", > + "skeleton open_and_load failed\n")) Please use ASSERT_OK_PTR() instead. > + return; > + > + do_dummy_read(skel->progs.dump_task_sleepable); > + > + ASSERT_GT(skel->bss->num_success_access_process_vm, 0, > + "num_success_access_process_vm"); > + > + bpf_iter_task__destroy(skel); > +} > + > static void test_task_stack(void) > { > struct bpf_iter_task_stack *skel; > @@ -1252,6 +1269,8 @@ void test_bpf_iter(void) > test_bpf_map(); > if (test__start_subtest("task")) > test_task(); > + if (test__start_subtest("task_sleepable")) > + test_task_sleepable(); > if (test__start_subtest("task_stack")) > test_task_stack(); > if (test__start_subtest("task_file")) > diff --git a/tools/testing/selftests/bpf/progs/bpf_iter_task.c b/tools/testing/selftests/bpf/progs/bpf_iter_task.c > index c86b93f33b32..3fa735af96f7 100644 > --- a/tools/testing/selftests/bpf/progs/bpf_iter_task.c > +++ b/tools/testing/selftests/bpf/progs/bpf_iter_task.c > @@ -2,6 +2,7 @@ > /* Copyright (c) 2020 Facebook */ > #include "bpf_iter.h" > #include <bpf/bpf_helpers.h> > +#include <bpf/bpf_tracing.h> > > char _license[] SEC("license") = "GPL"; > > @@ -23,3 +24,49 @@ int dump_task(struct bpf_iter__task *ctx) > BPF_SEQ_PRINTF(seq, "%8d %8d\n", task->tgid, task->pid); > return 0; > } > + > +int num_success_access_process_vm = 0; > + > +SEC("iter.s/task") > +int dump_task_sleepable(struct bpf_iter__task *ctx) > +{ > + struct seq_file *seq = ctx->meta->seq; > + struct task_struct *task = ctx->task; > + static const char info[] = " === END ==="; > + struct pt_regs *regs; > + void *ptr; > + uint32_t user_data = 0; > + int numread; > + > + if (task == (void *)0) { > + BPF_SEQ_PRINTF(seq, "%s\n", info); > + return 0; > + } > + > + regs = (struct pt_regs *)bpf_task_pt_regs(task); > + if (regs == (void *)0) { > + BPF_SEQ_PRINTF(seq, "%s\n", info); > + return 0; > + } > + ptr = (void *)PT_REGS_IP(regs); > + > + /* Try to read the contents of the task's instruction pointer from the > + * remote task's address space. > + */ > + numread = bpf_access_process_vm(&user_data, > + sizeof(uint32_t), > + ptr, > + task, > + 0); nit: keep it on one line (up to 100 characters is ok) > + if (numread != sizeof(uint32_t)) { > + BPF_SEQ_PRINTF(seq, "%s\n", info); > + return 0; > + } > + ++num_success_access_process_vm; > + > + if (ctx->meta->seq_num == 0) > + BPF_SEQ_PRINTF(seq, " tgid gid data\n"); > + > + BPF_SEQ_PRINTF(seq, "%8d %8d %8d\n", task->tgid, task->pid, user_data); > + return 0; > +} > -- > 2.30.2 >