Skip to content

Commit f223bfc

Browse files
alan-maguirekernel-patches-bot
authored andcommitted
selftests/bpf: add test for bpf_seq_printf_btf helper
Add a test verifying iterating over tasks and displaying BTF representation of data succeeds. Note here that we do not display the task_struct itself, as it will overflow the PAGE_SIZE limit on seq data; instead we write task->fs (a struct fs_struct). Suggested-by: Alexei Starovoitov <[email protected]> Signed-off-by: Alan Maguire <[email protected]>
1 parent 54147d2 commit f223bfc

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

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

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include "bpf_iter_task.skel.h"
88
#include "bpf_iter_task_stack.skel.h"
99
#include "bpf_iter_task_file.skel.h"
10+
#include "bpf_iter_task_btf.skel.h"
1011
#include "bpf_iter_tcp4.skel.h"
1112
#include "bpf_iter_tcp6.skel.h"
1213
#include "bpf_iter_udp4.skel.h"
@@ -167,6 +168,69 @@ static void test_task_file(void)
167168
bpf_iter_task_file__destroy(skel);
168169
}
169170

171+
#define FSBUFSZ 8192
172+
173+
static char fsbuf[FSBUFSZ];
174+
175+
static void do_btf_read(struct bpf_program *prog)
176+
{
177+
int iter_fd = -1, len = 0, bufleft = FSBUFSZ;
178+
struct bpf_link *link;
179+
char *buf = fsbuf;
180+
181+
link = bpf_program__attach_iter(prog, NULL);
182+
if (CHECK(IS_ERR(link), "attach_iter", "attach_iter failed\n"))
183+
return;
184+
185+
iter_fd = bpf_iter_create(bpf_link__fd(link));
186+
if (CHECK(iter_fd < 0, "create_iter", "create_iter failed\n"))
187+
goto free_link;
188+
189+
do {
190+
len = read(iter_fd, buf, bufleft);
191+
if (len > 0) {
192+
buf += len;
193+
bufleft -= len;
194+
}
195+
} while (len > 0);
196+
197+
if (CHECK(len < 0, "read", "read failed: %s\n", strerror(errno)))
198+
goto free_link;
199+
200+
CHECK(strstr(fsbuf, "(struct fs_struct)") == NULL,
201+
"check for btf representation of fs_struct in iter data",
202+
"struct fs_struct not found");
203+
free_link:
204+
if (iter_fd > 0)
205+
close(iter_fd);
206+
bpf_link__destroy(link);
207+
}
208+
209+
static void test_task_btf(void)
210+
{
211+
struct bpf_iter_task_btf__bss *bss;
212+
struct bpf_iter_task_btf *skel;
213+
214+
skel = bpf_iter_task_btf__open_and_load();
215+
if (CHECK(!skel, "bpf_iter_task_btf__open_and_load",
216+
"skeleton open_and_load failed\n"))
217+
return;
218+
219+
bss = skel->bss;
220+
221+
do_btf_read(skel->progs.dump_task_fs_struct);
222+
223+
if (CHECK(bss->tasks == 0, "check if iterated over tasks",
224+
"no task iteration, did BPF program run?\n"))
225+
goto cleanup;
226+
227+
CHECK(bss->seq_err != 0, "check for unexpected err",
228+
"bpf_seq_printf_btf returned %ld", bss->seq_err);
229+
230+
cleanup:
231+
bpf_iter_task_btf__destroy(skel);
232+
}
233+
170234
static void test_tcp4(void)
171235
{
172236
struct bpf_iter_tcp4 *skel;
@@ -957,6 +1021,8 @@ void test_bpf_iter(void)
9571021
test_task_stack();
9581022
if (test__start_subtest("task_file"))
9591023
test_task_file();
1024+
if (test__start_subtest("task_btf"))
1025+
test_task_btf();
9601026
if (test__start_subtest("tcp4"))
9611027
test_tcp4();
9621028
if (test__start_subtest("tcp6"))
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
/* Copyright (c) 2020, Oracle and/or its affiliates. */
3+
#include "bpf_iter.h"
4+
#include <bpf/bpf_helpers.h>
5+
#include <bpf/bpf_tracing.h>
6+
#include <errno.h>
7+
8+
char _license[] SEC("license") = "GPL";
9+
10+
long tasks = 0;
11+
long seq_err = 0;
12+
13+
/* struct task_struct's BTF representation will overflow PAGE_SIZE so cannot
14+
* be used here; instead dump a structure associated with each task.
15+
*/
16+
SEC("iter/task")
17+
int dump_task_fs_struct(struct bpf_iter__task *ctx)
18+
{
19+
static const char fs_type[] = "struct fs_struct";
20+
struct seq_file *seq = ctx->meta->seq;
21+
struct task_struct *task = ctx->task;
22+
struct fs_struct *fs = (void *)0;
23+
static struct btf_ptr ptr = { };
24+
long ret;
25+
26+
if (task)
27+
fs = task->fs;
28+
29+
ptr.type = fs_type;
30+
ptr.ptr = fs;
31+
32+
if (ctx->meta->seq_num == 0)
33+
BPF_SEQ_PRINTF(seq, "Raw BTF fs_struct per task\n");
34+
35+
ret = bpf_seq_printf_btf(seq, &ptr, sizeof(ptr), 0);
36+
switch (ret) {
37+
case 0:
38+
tasks++;
39+
break;
40+
case -ERANGE:
41+
/* NULL task or task->fs, don't count it as an error. */
42+
break;
43+
default:
44+
seq_err = ret;
45+
break;
46+
}
47+
48+
return 0;
49+
}

0 commit comments

Comments
 (0)