Commit 7594dcb7 authored by T.J. Mercier's avatar T.J. Mercier Committed by Alexei Starovoitov
Browse files

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: default avatarT.J. Mercier <tjmercier@google.com>
Acked-by: default avatarChristian König <christian.koenig@amd.com>
Acked-by: default avatarSong Liu <song@kernel.org>
Link: https://lore.kernel.org/r/20250522230429.941193-6-tjmercier@google.com


Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
parent ae5d2c59
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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
+41 −0
Original line number Diff line number Diff line
@@ -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);
}
+48 −0
Original line number Diff line number Diff line
@@ -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;
}