File Index
Files and directories
Sign in
FILE

dmabuf_iter.c

File preview with syntax highlighting.

linux-6.19.14/kernel/bpf/dmabuf_iter.c C
  1// SPDX-License-Identifier: GPL-2.0-only
  2/* Copyright (c) 2025 Google LLC */
  3#include <linux/bpf.h>
  4#include <linux/btf_ids.h>
  5#include <linux/dma-buf.h>
  6#include <linux/kernel.h>
  7#include <linux/seq_file.h>
  8
  9struct dmabuf_iter_priv {
 10	/*
 11	 * If this pointer is non-NULL, the buffer's refcount is elevated to
 12	 * prevent destruction between stop/start. If reading is not resumed and
 13	 * start is never called again, then dmabuf_iter_seq_fini drops the
 14	 * reference when the iterator is released.
 15	 */
 16	struct dma_buf *dmabuf;
 17};
 18
 19static void *dmabuf_iter_seq_start(struct seq_file *seq, loff_t *pos)
 20{
 21	struct dmabuf_iter_priv *p = seq->private;
 22
 23	if (*pos) {
 24		struct dma_buf *dmabuf = p->dmabuf;
 25
 26		if (!dmabuf)
 27			return NULL;
 28
 29		/*
 30		 * Always resume from where we stopped, regardless of the value
 31		 * of pos.
 32		 */
 33		p->dmabuf = NULL;
 34		return dmabuf;
 35	}
 36
 37	return dma_buf_iter_begin();
 38}
 39
 40static void *dmabuf_iter_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 41{
 42	struct dma_buf *dmabuf = v;
 43
 44	++*pos;
 45
 46	return dma_buf_iter_next(dmabuf);
 47}
 48
 49struct bpf_iter__dmabuf {
 50	__bpf_md_ptr(struct bpf_iter_meta *, meta);
 51	__bpf_md_ptr(struct dma_buf *, dmabuf);
 52};
 53
 54static int __dmabuf_seq_show(struct seq_file *seq, void *v, bool in_stop)
 55{
 56	struct bpf_iter_meta meta = {
 57		.seq = seq,
 58	};
 59	struct bpf_iter__dmabuf ctx = {
 60		.meta = &meta,
 61		.dmabuf = v,
 62	};
 63	struct bpf_prog *prog = bpf_iter_get_info(&meta, in_stop);
 64
 65	if (prog)
 66		return bpf_iter_run_prog(prog, &ctx);
 67
 68	return 0;
 69}
 70
 71static int dmabuf_iter_seq_show(struct seq_file *seq, void *v)
 72{
 73	return __dmabuf_seq_show(seq, v, false);
 74}
 75
 76static void dmabuf_iter_seq_stop(struct seq_file *seq, void *v)
 77{
 78	struct dma_buf *dmabuf = v;
 79
 80	if (dmabuf) {
 81		struct dmabuf_iter_priv *p = seq->private;
 82
 83		p->dmabuf = dmabuf;
 84	}
 85}
 86
 87static const struct seq_operations dmabuf_iter_seq_ops = {
 88	.start	= dmabuf_iter_seq_start,
 89	.next	= dmabuf_iter_seq_next,
 90	.stop	= dmabuf_iter_seq_stop,
 91	.show	= dmabuf_iter_seq_show,
 92};
 93
 94static void bpf_iter_dmabuf_show_fdinfo(const struct bpf_iter_aux_info *aux,
 95					struct seq_file *seq)
 96{
 97	seq_puts(seq, "dmabuf iter\n");
 98}
 99
100static int dmabuf_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux)
101{
102	struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
103
104	p->dmabuf = NULL;
105	return 0;
106}
107
108static void dmabuf_iter_seq_fini(void *priv)
109{
110	struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
111
112	if (p->dmabuf)
113		dma_buf_put(p->dmabuf);
114}
115
116static const struct bpf_iter_seq_info dmabuf_iter_seq_info = {
117	.seq_ops		= &dmabuf_iter_seq_ops,
118	.init_seq_private	= dmabuf_iter_seq_init,
119	.fini_seq_private	= dmabuf_iter_seq_fini,
120	.seq_priv_size		= sizeof(struct dmabuf_iter_priv),
121};
122
123static struct bpf_iter_reg bpf_dmabuf_reg_info = {
124	.target			= "dmabuf",
125	.feature                = BPF_ITER_RESCHED,
126	.show_fdinfo		= bpf_iter_dmabuf_show_fdinfo,
127	.ctx_arg_info_size	= 1,
128	.ctx_arg_info		= {
129		{ offsetof(struct bpf_iter__dmabuf, dmabuf),
130		  PTR_TO_BTF_ID_OR_NULL },
131	},
132	.seq_info		= &dmabuf_iter_seq_info,
133};
134
135DEFINE_BPF_ITER_FUNC(dmabuf, struct bpf_iter_meta *meta, struct dma_buf *dmabuf)
136BTF_ID_LIST_SINGLE(bpf_dmabuf_btf_id, struct, dma_buf)
137
138static int __init dmabuf_iter_init(void)
139{
140	bpf_dmabuf_reg_info.ctx_arg_info[0].btf_id = bpf_dmabuf_btf_id[0];
141	return bpf_iter_reg_target(&bpf_dmabuf_reg_info);
142}
143
144late_initcall(dmabuf_iter_init);
145
146struct bpf_iter_dmabuf {
147	/*
148	 * opaque iterator state; having __u64 here allows to preserve correct
149	 * alignment requirements in vmlinux.h, generated from BTF
150	 */
151	__u64 __opaque[1];
152} __aligned(8);
153
154/* Non-opaque version of bpf_iter_dmabuf */
155struct bpf_iter_dmabuf_kern {
156	struct dma_buf *dmabuf;
157} __aligned(8);
158
159__bpf_kfunc_start_defs();
160
161__bpf_kfunc int bpf_iter_dmabuf_new(struct bpf_iter_dmabuf *it)
162{
163	struct bpf_iter_dmabuf_kern *kit = (void *)it;
164
165	BUILD_BUG_ON(sizeof(*kit) > sizeof(*it));
166	BUILD_BUG_ON(__alignof__(*kit) != __alignof__(*it));
167
168	kit->dmabuf = NULL;
169	return 0;
170}
171
172__bpf_kfunc struct dma_buf *bpf_iter_dmabuf_next(struct bpf_iter_dmabuf *it)
173{
174	struct bpf_iter_dmabuf_kern *kit = (void *)it;
175
176	if (kit->dmabuf)
177		kit->dmabuf = dma_buf_iter_next(kit->dmabuf);
178	else
179		kit->dmabuf = dma_buf_iter_begin();
180
181	return kit->dmabuf;
182}
183
184__bpf_kfunc void bpf_iter_dmabuf_destroy(struct bpf_iter_dmabuf *it)
185{
186	struct bpf_iter_dmabuf_kern *kit = (void *)it;
187
188	if (kit->dmabuf)
189		dma_buf_put(kit->dmabuf);
190}
191
192__bpf_kfunc_end_defs();
~/ Read-only file preview.