On Mon, Apr 13, 2020 at 3:18 PM Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> wrote: > > 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. Actually never mind this, from reading fs/seq_file.c code I've been under impression that start is only called for full restarts, but that's not true. > > > + > > + 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; > > +} > > + > > [...]