selftests/bpf: Add test for open coded dmabuf_iter

Use the same test buffers as the traditional iterator and a new BPF map
to verify the test buffers can be found with the open coded dmabuf
iterator.

Signed-off-by: T.J. Mercier <tjmercier@google.com>
Acked-by: Christian König <christian.koenig@amd.com>
Acked-by: Song Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20250522230429.941193-6-tjmercier@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
T.J. Mercier 2025-05-22 23:04:29 +00:00 committed by Alexei Starovoitov
parent ae5d2c59ec
commit 7594dcb71f
3 changed files with 94 additions and 0 deletions

View File

@ -591,4 +591,9 @@ extern int bpf_iter_kmem_cache_new(struct bpf_iter_kmem_cache *it) __weak __ksym
extern struct kmem_cache *bpf_iter_kmem_cache_next(struct bpf_iter_kmem_cache *it) __weak __ksym;
extern void bpf_iter_kmem_cache_destroy(struct bpf_iter_kmem_cache *it) __weak __ksym;
struct bpf_iter_dmabuf;
extern int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *it) __weak __ksym;
extern struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it) __weak __ksym;
extern void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it) __weak __ksym;
#endif

View File

@ -219,14 +219,52 @@ static void subtest_dmabuf_iter_check_default_iter(struct dmabuf_iter *skel)
close(iter_fd);
}
static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd)
{
LIBBPF_OPTS(bpf_test_run_opts, topts);
char key[DMA_BUF_NAME_LEN];
int err, fd;
bool found;
/* No need to attach it, just run it directly */
fd = bpf_program__fd(skel->progs.iter_dmabuf_for_each);
err = bpf_prog_test_run_opts(fd, &topts);
if (!ASSERT_OK(err, "test_run_opts err"))
return;
if (!ASSERT_OK(topts.retval, "test_run_opts retval"))
return;
if (!ASSERT_OK(bpf_map_get_next_key(map_fd, NULL, key), "get next key"))
return;
do {
ASSERT_OK(bpf_map_lookup_elem(map_fd, key, &found), "lookup");
ASSERT_TRUE(found, "found test buffer");
} while (bpf_map_get_next_key(map_fd, key, key));
}
void test_dmabuf_iter(void)
{
struct dmabuf_iter *skel = NULL;
int map_fd;
const bool f = false;
skel = dmabuf_iter__open_and_load();
if (!ASSERT_OK_PTR(skel, "dmabuf_iter__open_and_load"))
return;
map_fd = bpf_map__fd(skel->maps.testbuf_hash);
if (!ASSERT_OK_FD(map_fd, "map_fd"))
goto destroy_skel;
if (!ASSERT_OK(bpf_map_update_elem(map_fd, udmabuf_test_buffer_name, &f, BPF_ANY),
"insert udmabuf"))
goto destroy_skel;
if (!ASSERT_OK(bpf_map_update_elem(map_fd, sysheap_test_buffer_name, &f, BPF_ANY),
"insert sysheap buffer"))
goto destroy_skel;
if (!ASSERT_OK(create_test_buffers(), "create_test_buffers"))
goto destroy;
@ -237,8 +275,11 @@ void test_dmabuf_iter(void)
subtest_dmabuf_iter_check_no_infinite_reads(skel);
if (test__start_subtest("default_iter"))
subtest_dmabuf_iter_check_default_iter(skel);
if (test__start_subtest("open_coded"))
subtest_dmabuf_iter_check_open_coded(skel, map_fd);
destroy:
destroy_test_buffers();
destroy_skel:
dmabuf_iter__destroy(skel);
}

View File

@ -9,6 +9,13 @@
char _license[] SEC("license") = "GPL";
struct {
__uint(type, BPF_MAP_TYPE_HASH);
__uint(key_size, DMA_BUF_NAME_LEN);
__type(value, bool);
__uint(max_entries, 5);
} testbuf_hash SEC(".maps");
/*
* Fields output by this iterator are delimited by newlines. Convert any
* newlines in user-provided printed strings to spaces.
@ -51,3 +58,44 @@ int dmabuf_collector(struct bpf_iter__dmabuf *ctx)
BPF_SEQ_PRINTF(seq, "%lu\n%llu\n%s\n%s\n", inode, size, name, exporter);
return 0;
}
SEC("syscall")
int iter_dmabuf_for_each(const void *ctx)
{
struct dma_buf *d;
bpf_for_each(dmabuf, d) {
char name[DMA_BUF_NAME_LEN];
const char *pname;
bool *found;
long len;
int i;
if (bpf_core_read(&pname, sizeof(pname), &d->name))
return 1;
/* Buffers are not required to be named */
if (!pname)
continue;
len = bpf_probe_read_kernel_str(name, sizeof(name), pname);
if (len < 0)
return 1;
/*
* The entire name buffer is used as a map key.
* Zeroize any uninitialized trailing bytes after the NUL.
*/
bpf_for(i, len, DMA_BUF_NAME_LEN)
name[i] = 0;
found = bpf_map_lookup_elem(&testbuf_hash, name);
if (found) {
bool t = true;
bpf_map_update_elem(&testbuf_hash, name, &t, BPF_EXIST);
}
}
return 0;
}