On Wed, Apr 8, 2020 at 4:26 PM Yonghong Song <yhs@xxxxxx> wrote: > > This patch added bpf_map target. Traversing all bpf_maps > through map_idr. A reference is held for the map during > the show() to ensure safety and correctness for field accesses. > > Signed-off-by: Yonghong Song <yhs@xxxxxx> > --- > kernel/bpf/syscall.c | 104 +++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 104 insertions(+) > > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c > index b5e4f18cc633..62a872a406ca 100644 > --- a/kernel/bpf/syscall.c > +++ b/kernel/bpf/syscall.c > @@ -3797,3 +3797,107 @@ SYSCALL_DEFINE3(bpf, int, cmd, union bpf_attr __user *, uattr, unsigned int, siz > > return err; > } > + > +struct bpfdump_seq_map_info { > + struct bpf_map *map; > + u32 id; > +}; > + > +static struct bpf_map *bpf_map_seq_get_next(u32 *id) > +{ > + struct bpf_map *map; > + > + spin_lock_bh(&map_idr_lock); > + map = idr_get_next(&map_idr, id); > + if (map) > + map = __bpf_map_inc_not_zero(map, false); > + spin_unlock_bh(&map_idr_lock); > + > + return map; > +} > + > +static void *bpf_map_seq_start(struct seq_file *seq, loff_t *pos) > +{ > + struct bpfdump_seq_map_info *info = seq->private; > + struct bpf_map *map; > + u32 id = info->id + 1; shouldn't it always start from id=0? This seems buggy and should break on seq_file restart. > + > + map = bpf_map_seq_get_next(&id); > + if (!map) bpf_map_seq_get_next will return error code, not NULL, if bpf_map refcount couldn't be incremented. So this must be IS_ERR(map). > + return NULL; > + > + ++*pos; > + info->map = map; > + info->id = id; > + return map; > +} > + > +static void *bpf_map_seq_next(struct seq_file *seq, void *v, loff_t *pos) > +{ > + struct bpfdump_seq_map_info *info = seq->private; > + struct bpf_map *map; > + u32 id = info->id + 1; > + > + ++*pos; > + map = bpf_map_seq_get_next(&id); > + if (!map) same here, IS_ERR(map) > + return NULL; > + > + __bpf_map_put(info->map, true); > + info->map = map; > + info->id = id; > + return map; > +} > + [...]