2017-10-31 16:36 UTC+0900 ~ Prashant Bhole <bhole_prashant...@lab.ntt.co.jp>
> Added support to show filenames of pinned objects.
>
> For example:
>
> root@test# ./bpftool prog
> 3: tracepoint  name tracepoint__irq  tag f677a7dd722299a3
>     loaded_at Oct 26/11:39  uid 0
>     xlated 160B  not jited  memlock 4096B  map_ids 4
>     pinned /sys/fs/bpf/softirq_prog
>
> 4: tracepoint  name tracepoint__irq  tag ea5dc530d00b92b6
>     loaded_at Oct 26/11:39  uid 0
>     xlated 392B  not jited  memlock 4096B  map_ids 4,6
>
> root@test# ./bpftool --json --pretty prog
> [{
>         "id": 3,
>         "type": "tracepoint",
>         "name": "tracepoint__irq",
>         "tag": "f677a7dd722299a3",
>         "loaded_at": "Oct 26/11:39",
>         "uid": 0,
>         "bytes_xlated": 160,
>         "jited": false,
>         "bytes_memlock": 4096,
>         "map_ids": [4
>         ]
> ,
>         "pinned": ["/sys/fs/bpf/softirq_prog"
>         ]
>     },{
>         "id": 4,
>         "type": "tracepoint",
>         "name": "tracepoint__irq",
>         "tag": "ea5dc530d00b92b6",
>         "loaded_at": "Oct 26/11:39",
>         "uid": 0,
>         "bytes_xlated": 392,
>         "jited": false,
>         "bytes_memlock": 4096,
>         "map_ids": [4,6
>         ]
> ,
>         "pinned": []
>     }
> ]
>
> root@test# ./bpftool map
> 4: hash  name start  flags 0x0
>     key 4B  value 16B  max_entries 10240  memlock 1003520B
>     pinned /sys/fs/bpf/softirq_map1
> 5: hash  name iptr  flags 0x0
>     key 4B  value 8B  max_entries 10240  memlock 921600B
>
> root@test# ./bpftool --json --pretty map
> [{
>         "id": 4,
>         "type": "hash",
>         "name": "start",
>         "flags": 0,
>         "bytes_key": 4,
>         "bytes_value": 16,
>         "max_entries": 10240,
>         "bytes_memlock": 1003520,
>         "pinned": ["/sys/fs/bpf/softirq_map1"
>         ]
>     },{
>         "id": 5,
>         "type": "hash",
>         "name": "iptr",
>         "flags": 0,
>         "bytes_key": 4,
>         "bytes_value": 8,
>         "max_entries": 10240,
>         "bytes_memlock": 921600,
>         "pinned": []
>     }
> ]
>
> Signed-off-by: Prashant Bhole <bhole_prashant...@lab.ntt.co.jp>
> ---
>  tools/bpf/bpftool/common.c | 70 
> ++++++++++++++++++++++++++++++++++++++++++++++
>  tools/bpf/bpftool/main.c   |  8 ++++++
>  tools/bpf/bpftool/main.h   | 15 ++++++++++
>  tools/bpf/bpftool/map.c    | 22 ++++++++++++++-
>  tools/bpf/bpftool/prog.c   | 23 +++++++++++++++
>  5 files changed, 137 insertions(+), 1 deletion(-)
>
> diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
> index 4556947..6b6247c 100644
> --- a/tools/bpf/bpftool/common.c
> +++ b/tools/bpf/bpftool/common.c
> @@ -45,6 +45,7 @@
>  #include <sys/mount.h>
>  #include <sys/types.h>
>  #include <sys/vfs.h>
> +#include <fts.h>
>  
>  #include <bpf.h>
>  
> @@ -290,3 +291,72 @@ void print_hex_data_json(uint8_t *data, size_t len)
>               jsonw_printf(json_wtr, "\"0x%02hhx\"", data[i]);
>       jsonw_end_array(json_wtr);
>  }
> +
> +int build_pinned_obj_table(struct pinned_obj_table *tab, enum bpf_obj_type 
> type)

Nit: line over 80 characters, please wrap.

> +{
> +     char *path[] = {"/sys/fs/bpf/", NULL};

This will not work for progs/maps pinned elsewhere on the system. Might
be worth mentioning in the documentation?

> +     FTS *ftsp = NULL;
> +     FTSENT *ftse = NULL;
> +     enum bpf_obj_type objtype;
> +     struct bpf_prog_info pinned_info = {};
> +     __u32 len = sizeof(pinned_info);
> +     int fd, err;
> +     struct pinned_obj *obj_node;

Please use reversed-Christmas tree style.

> +
> +     if (!is_bpffs(path[0]))
> +             return -1;
> +
> +     ftsp = fts_open(path, 0, NULL);
> +     if (!ftsp)
> +             return -1;
> +
> +     while ((ftse = fts_read(ftsp)) != NULL) {
> +             if (!(ftse->fts_info & FTS_F))
> +                     continue;
> +             fd = open_obj_pinned(ftse->fts_path);
> +             if (fd < 0)
> +                     continue;
> +
> +             objtype = get_fd_type(fd);
> +             if (objtype != type) {
> +                     close(fd);
> +                     continue;
> +             }
> +             memset(&pinned_info, 0, sizeof(pinned_info));
> +             err = bpf_obj_get_info_by_fd(fd, &pinned_info, &len);
> +             if (err) {
> +                     close(fd);
> +                     continue;
> +             }
> +
> +             obj_node = malloc(sizeof(*obj_node));
> +             if (!obj_node)
> +                     return -1;

Maybe fd and ftsp should be closed before returning?

> +
> +             memset(obj_node, 0, sizeof(*obj_node));
> +             obj_node->id = pinned_info.id;
> +             obj_node->path = strdup(ftse->fts_path);
> +             hash_add(tab->table, &obj_node->hash, obj_node->id);
> +
> +             close(fd);
> +     }
> +
> +     fts_close(ftsp);
> +     return 0;
> +}
> +
> +void delete_pinned_obj_table(struct pinned_obj_table *tab)
> +{
> +     struct pinned_obj *obj;
> +     struct hlist_node *tmp;
> +     unsigned int bkt;
> +
> +     if (hash_empty(tab->table))
> +             return;
> +
> +     hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
> +             hash_del(&obj->hash);
> +             free(obj->path);
> +             free(obj);
> +     }
> +}
> diff --git a/tools/bpf/bpftool/main.c b/tools/bpf/bpftool/main.c
> index 78d9afb..6ad53f1 100644
> --- a/tools/bpf/bpftool/main.c
> +++ b/tools/bpf/bpftool/main.c
> @@ -54,6 +54,8 @@
>  json_writer_t *json_wtr;
>  bool pretty_output;
>  bool json_output;
> +struct pinned_obj_table prog_table;
> +struct pinned_obj_table map_table;
>  
>  void usage(void)
>  {
> @@ -272,6 +274,9 @@ int main(int argc, char **argv)
>       json_output = false;
>       bin_name = argv[0];
>  
> +     hash_init(prog_table.table);
> +     hash_init(map_table.table);
> +
>       while ((opt = getopt_long(argc, argv, "Vhpj",
>                                 options, NULL)) >= 0) {
>               switch (opt) {
> @@ -311,5 +316,8 @@ int main(int argc, char **argv)
>       if (json_output)
>               jsonw_destroy(&json_wtr);
>  
> +     delete_pinned_obj_table(&prog_table);
> +     delete_pinned_obj_table(&map_table);
> +
>       return ret;
>  }
> diff --git a/tools/bpf/bpftool/main.h b/tools/bpf/bpftool/main.h
> index 4b56850..3abaa17 100644
> --- a/tools/bpf/bpftool/main.h
> +++ b/tools/bpf/bpftool/main.h
> @@ -42,6 +42,7 @@
>  #include <stdio.h>
>  #include <linux/bpf.h>
>  #include <linux/kernel.h>
> +#include <linux/hashtable.h>
>  
>  #include "json_writer.h"
>  
> @@ -70,11 +71,25 @@ enum bpf_obj_type {
>  
>  extern json_writer_t *json_wtr;
>  extern bool json_output;
> +extern struct pinned_obj_table prog_table;
> +extern struct pinned_obj_table map_table;
>  
>  bool is_prefix(const char *pfx, const char *str);
>  void fprint_hex(FILE *f, void *arg, unsigned int n, const char *sep);
>  void usage(void) __attribute__((noreturn));
>  
> +struct pinned_obj_table {
> +     DECLARE_HASHTABLE(table, 16);
> +};
> +
> +struct pinned_obj {
> +     __u32 id;
> +     char *path;
> +     struct hlist_node hash;
> +};

Nit: add a blank line here?

> +int build_pinned_obj_table(struct pinned_obj_table *table, enum bpf_obj_type 
> type);

Please wrap this line as well.

> +void delete_pinned_obj_table(struct pinned_obj_table *tab);
> +
>  struct cmd {
>       const char *cmd;
>       int (*func)(int argc, char **argv);
> diff --git a/tools/bpf/bpftool/map.c b/tools/bpf/bpftool/map.c
> index e978ab2..fbe236e 100644
> --- a/tools/bpf/bpftool/map.c
> +++ b/tools/bpf/bpftool/map.c
> @@ -436,6 +436,18 @@ static int show_map_close_json(int fd, struct 
> bpf_map_info *info)
>               jsonw_int_field(json_wtr, "bytes_memlock", atoi(memlock));
>       free(memlock);
>  
> +     if (!hash_empty(map_table.table)) {
> +             struct pinned_obj *obj;
> +
> +             jsonw_name(json_wtr, "pinned");
> +             jsonw_start_array(json_wtr);
> +             hash_for_each_possible(map_table.table, obj, hash, info->id) {
> +                     if (obj->id == info->id)
> +                             jsonw_string(json_wtr, obj->path);
> +             }
> +             jsonw_end_array(json_wtr);
> +     }
> +
>       jsonw_end_object(json_wtr);
>  
>       return 0;
> @@ -466,7 +478,13 @@ static int show_map_close_plain(int fd, struct 
> bpf_map_info *info)
>       free(memlock);
>  
>       printf("\n");
> -
> +     if (!hash_empty(map_table.table)) {
> +             struct pinned_obj *obj;

Nit: add a blank line after declarations.

> +             hash_for_each_possible(map_table.table, obj, hash, info->id) {
> +                     if (obj->id == info->id)
> +                             printf("\tpinned %s\n", obj->path);
> +             }
> +     }
>       return 0;
>  }
>  
> @@ -478,6 +496,8 @@ static int do_show(int argc, char **argv)
>       int err;
>       int fd;
>  
> +     build_pinned_obj_table(&map_table, BPF_OBJ_MAP);
> +
>       if (argc == 2) {
>               fd = map_parse_fd_and_info(&argc, &argv, &info, &len);
>               if (fd < 0)
> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> index 250f80f..cd29eae 100644
> --- a/tools/bpf/bpftool/prog.c
> +++ b/tools/bpf/bpftool/prog.c
> @@ -207,6 +207,7 @@ static void show_prog_maps(int fd, u32 num_maps)
>                       printf("%u%s", map_ids[i],
>                              i == info.nr_map_ids - 1 ? "" : ",");
>       }
> +     printf("\n");

This printf() should not be here, because it would add a new line even
if there is no pinned path to add, and regardless of plain / JSON output
selection. It is responsible for the line breaks before the commas you
have in your commit log example.

>  }
>  
>  static void print_prog_json(struct bpf_prog_info *info, int fd)
> @@ -256,6 +257,18 @@ static void print_prog_json(struct bpf_prog_info *info, 
> int fd)
>       if (info->nr_map_ids)
>               show_prog_maps(fd, info->nr_map_ids);
>  
> +     if (!hash_empty(prog_table.table)) {
> +             struct pinned_obj *obj;
> +
> +             jsonw_name(json_wtr, "pinned");
> +             jsonw_start_array(json_wtr);
> +             hash_for_each_possible(prog_table.table, obj, hash, info->id) {
> +                     if (obj->id == info->id)
> +                             jsonw_string(json_wtr, obj->path);
> +             }
> +             jsonw_end_array(json_wtr);
> +     }
> +
>       jsonw_end_object(json_wtr);
>  }
>  
> @@ -300,6 +313,14 @@ static void print_prog_plain(struct bpf_prog_info *info, 
> int fd)
>       if (info->nr_map_ids)
>               show_prog_maps(fd, info->nr_map_ids);
>  
> +     if (!hash_empty(prog_table.table)) {
> +             struct pinned_obj *obj;

Nit: add a blank line after declarations.
Here might be a better place for the printf("\n");?

> +             hash_for_each_possible(prog_table.table, obj, hash, info->id) {
> +                     if (obj->id == info->id)
> +                             printf("\tpinned %s\n", obj->path);
> +             }
> +     }
> +
>       printf("\n");
>  }
>  
> @@ -329,6 +350,8 @@ static int do_show(int argc, char **argv)
>       int err;
>       int fd;
>  
> +     build_pinned_obj_table(&prog_table, BPF_OBJ_PROG);
> +
>       if (argc == 2) {
>               fd = prog_parse_fd(&argc, &argv);
>               if (fd < 0)

Quentin


Reply via email to