mirror of
https://github.com/torvalds/linux.git
synced 2026-05-21 13:27:57 +02:00
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:
parent
ae5d2c59ec
commit
7594dcb71f
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user