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 9 struct 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 19 static 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 40 static 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 49 struct bpf_iter__dmabuf { 50 __bpf_md_ptr(struct bpf_iter_meta *, meta); 51 __bpf_md_ptr(struct dma_buf *, dmabuf); 52 }; 53 54 static 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 71 static int dmabuf_iter_seq_show(struct seq_file *seq, void *v) 72 { 73 return __dmabuf_seq_show(seq, v, false); 74 } 75 76 static 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 87 static 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 94 static 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 100 static 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 108 static 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 116 static 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 123 static 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 135 DEFINE_BPF_ITER_FUNC(dmabuf, struct bpf_iter_meta *meta, struct dma_buf *dmabuf) 136 BTF_ID_LIST_SINGLE(bpf_dmabuf_btf_id, struct, dma_buf) 137 138 static 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 144 late_initcall(dmabuf_iter_init); 145 146 struct 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 */ 155 struct 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(); 193