1 // SPDX-License-Identifier: GPL-2.0-only 2 /* Copyright (c) 2020 Facebook */ 3 #include <linux/bpf.h> 4 #include <linux/fs.h> 5 #include <linux/filter.h> 6 #include <linux/kernel.h> 7 #include <linux/btf_ids.h> 8 9 struct bpf_iter_seq_map_info { 10 u32 mid; 11 }; 12 13 static void *bpf_map_seq_start(struct seq_file *seq, loff_t *pos) 14 { 15 struct bpf_iter_seq_map_info *info = seq->private; 16 struct bpf_map *map; 17 18 map = bpf_map_get_curr_or_next(&info->mid); 19 if (!map) 20 return NULL; 21 22 ++*pos; 23 return map; 24 } 25 26 static void *bpf_map_seq_next(struct seq_file *seq, void *v, loff_t *pos) 27 { 28 struct bpf_iter_seq_map_info *info = seq->private; 29 struct bpf_map *map; 30 31 ++*pos; 32 ++info->mid; 33 bpf_map_put((struct bpf_map *)v); 34 map = bpf_map_get_curr_or_next(&info->mid); 35 if (!map) 36 return NULL; 37 38 return map; 39 } 40 41 struct bpf_iter__bpf_map { 42 __bpf_md_ptr(struct bpf_iter_meta *, meta); 43 __bpf_md_ptr(struct bpf_map *, map); 44 }; 45 46 DEFINE_BPF_ITER_FUNC(bpf_map, struct bpf_iter_meta *meta, struct bpf_map *map) 47 48 static int __bpf_map_seq_show(struct seq_file *seq, void *v, bool in_stop) 49 { 50 struct bpf_iter__bpf_map ctx; 51 struct bpf_iter_meta meta; 52 struct bpf_prog *prog; 53 int ret = 0; 54 55 ctx.meta = &meta; 56 ctx.map = v; 57 meta.seq = seq; 58 prog = bpf_iter_get_info(&meta, in_stop); 59 if (prog) 60 ret = bpf_iter_run_prog(prog, &ctx); 61 62 return ret; 63 } 64 65 static int bpf_map_seq_show(struct seq_file *seq, void *v) 66 { 67 return __bpf_map_seq_show(seq, v, false); 68 } 69 70 static void bpf_map_seq_stop(struct seq_file *seq, void *v) 71 { 72 if (!v) 73 (void)__bpf_map_seq_show(seq, v, true); 74 else 75 bpf_map_put((struct bpf_map *)v); 76 } 77 78 static const struct seq_operations bpf_map_seq_ops = { 79 .start = bpf_map_seq_start, 80 .next = bpf_map_seq_next, 81 .stop = bpf_map_seq_stop, 82 .show = bpf_map_seq_show, 83 }; 84 85 BTF_ID_LIST(btf_bpf_map_id) 86 BTF_ID(struct, bpf_map) 87 88 static struct bpf_iter_reg bpf_map_reg_info = { 89 .target = "bpf_map", 90 .seq_ops = &bpf_map_seq_ops, 91 .init_seq_private = NULL, 92 .fini_seq_private = NULL, 93 .seq_priv_size = sizeof(struct bpf_iter_seq_map_info), 94 .ctx_arg_info_size = 1, 95 .ctx_arg_info = { 96 { offsetof(struct bpf_iter__bpf_map, map), 97 PTR_TO_BTF_ID_OR_NULL }, 98 }, 99 }; 100 101 static int __init bpf_map_iter_init(void) 102 { 103 bpf_map_reg_info.ctx_arg_info[0].btf_id = *btf_bpf_map_id; 104 return bpf_iter_reg_target(&bpf_map_reg_info); 105 } 106 107 late_initcall(bpf_map_iter_init); 108