bpf: Add open coded dmabuf iterator
authorT.J. Mercier <tjmercier@google.com>
Thu, 22 May 2025 23:04:27 +0000 (23:04 +0000)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 27 May 2025 16:51:25 +0000 (09:51 -0700)
This open coded iterator allows for more flexibility when creating BPF
programs. It can support output in formats other than text. With an open
coded iterator, a single BPF program can traverse multiple kernel data
structures (now including dmabufs), allowing for more efficient analysis
of kernel data compared to multiple reads from procfs, sysfs, or
multiple traditional BPF iterator invocations.

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-4-tjmercier@google.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/dmabuf_iter.c
kernel/bpf/helpers.c

index 83ef54d78b62988d473bc52a1e759d66d55908ed..4dd7ef7c145ca7c93de06d9d06f29487f0582544 100644 (file)
@@ -100,3 +100,51 @@ static int __init dmabuf_iter_init(void)
 }
 
 late_initcall(dmabuf_iter_init);
+
+struct bpf_iter_dmabuf {
+       /*
+        * opaque iterator state; having __u64 here allows to preserve correct
+        * alignment requirements in vmlinux.h, generated from BTF
+        */
+       __u64 __opaque[1];
+} __aligned(8);
+
+/* Non-opaque version of bpf_iter_dmabuf */
+struct bpf_iter_dmabuf_kern {
+       struct dma_buf *dmabuf;
+} __aligned(8);
+
+__bpf_kfunc_start_defs();
+
+__bpf_kfunc int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *it)
+{
+       struct bpf_iter_dmabuf_kern *kit = (void *)it;
+
+       BUILD_BUG_ON(sizeof(*kit) > sizeof(*it));
+       BUILD_BUG_ON(__alignof__(*kit) != __alignof__(*it));
+
+       kit->dmabuf = NULL;
+       return 0;
+}
+
+__bpf_kfunc struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it)
+{
+       struct bpf_iter_dmabuf_kern *kit = (void *)it;
+
+       if (kit->dmabuf)
+               kit->dmabuf = dma_buf_iter_next(kit->dmabuf);
+       else
+               kit->dmabuf = dma_buf_iter_begin();
+
+       return kit->dmabuf;
+}
+
+__bpf_kfunc void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it)
+{
+       struct bpf_iter_dmabuf_kern *kit = (void *)it;
+
+       if (kit->dmabuf)
+               dma_buf_put(kit->dmabuf);
+}
+
+__bpf_kfunc_end_defs();
index c1113b74e1e2c8d714adc1439addbcb51eb0770a..bd17ed5bfc4ba39623adce5aad33dacdec83bf9a 100644 (file)
@@ -3386,6 +3386,11 @@ BTF_ID_FLAGS(func, bpf_copy_from_user_dynptr, KF_SLEEPABLE)
 BTF_ID_FLAGS(func, bpf_copy_from_user_str_dynptr, KF_SLEEPABLE)
 BTF_ID_FLAGS(func, bpf_copy_from_user_task_dynptr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
 BTF_ID_FLAGS(func, bpf_copy_from_user_task_str_dynptr, KF_SLEEPABLE | KF_TRUSTED_ARGS)
+#ifdef CONFIG_DMA_SHARED_BUFFER
+BTF_ID_FLAGS(func, bpf_iter_dmabuf_new, KF_ITER_NEW | KF_SLEEPABLE)
+BTF_ID_FLAGS(func, bpf_iter_dmabuf_next, KF_ITER_NEXT | KF_RET_NULL | KF_SLEEPABLE)
+BTF_ID_FLAGS(func, bpf_iter_dmabuf_destroy, KF_ITER_DESTROY | KF_SLEEPABLE)
+#endif
 BTF_KFUNCS_END(common_btf_ids)
 
 static const struct btf_kfunc_id_set common_kfunc_set = {