tools: bpftool: show filenames of pinned objects
authorPrashant Bhole <bhole_prashant_q7@lab.ntt.co.jp>
Wed, 8 Nov 2017 04:55:48 +0000 (13:55 +0900)
committerDavid S. Miller <davem@davemloft.net>
Sat, 11 Nov 2017 03:35:41 +0000 (12:35 +0900)
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_q7@lab.ntt.co.jp>
Signed-off-by: David S. Miller <davem@davemloft.net>
tools/bpf/bpftool/common.c
tools/bpf/bpftool/main.c
tools/bpf/bpftool/main.h
tools/bpf/bpftool/map.c
tools/bpf/bpftool/prog.c

index 6b3d25d6a782043ce1b7fca54981e3133d134b9a..2bd3b280e6dd24292cb30dca71b9db9ef18ac804 100644 (file)
@@ -34,7 +34,9 @@
 /* Author: Jakub Kicinski <kubakici@wp.pl> */
 
 #include <errno.h>
+#include <fts.h>
 #include <libgen.h>
+#include <mntent.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -321,3 +323,83 @@ 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)
+{
+       struct bpf_prog_info pinned_info = {};
+       struct pinned_obj *obj_node = NULL;
+       __u32 len = sizeof(pinned_info);
+       struct mntent *mntent = NULL;
+       enum bpf_obj_type objtype;
+       FILE *mntfile = NULL;
+       FTSENT *ftse = NULL;
+       FTS *fts = NULL;
+       int fd, err;
+
+       mntfile = setmntent("/proc/mounts", "r");
+       if (!mntfile)
+               return -1;
+
+       while ((mntent = getmntent(mntfile))) {
+               char *path[] = { mntent->mnt_dir, NULL };
+
+               if (strncmp(mntent->mnt_type, "bpf", 3) != 0)
+                       continue;
+
+               fts = fts_open(path, 0, NULL);
+               if (!fts)
+                       continue;
+
+               while ((ftse = fts_read(fts))) {
+                       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) {
+                               close(fd);
+                               fts_close(fts);
+                               fclose(mntfile);
+                               return -1;
+                       }
+
+                       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(fts);
+       }
+       fclose(mntfile);
+       return 0;
+}
+
+void delete_pinned_obj_table(struct pinned_obj_table *tab)
+{
+       struct pinned_obj *obj;
+       struct hlist_node *tmp;
+       unsigned int bkt;
+
+       hash_for_each_safe(tab->table, bkt, tmp, obj, hash) {
+               hash_del(&obj->hash);
+               free(obj->path);
+               free(obj);
+       }
+}
index 78d9afb74ef4f82514e0ce47bc3f761f1032584d..6ad53f1797fade24e41223e2bd908be32fe2f839 100644 (file)
@@ -54,6 +54,8 @@ static int (*last_do_help)(int argc, char **argv);
 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;
 }
index 2ff2a361af0dfdc7d812ce9307a8045a8716f080..13453de2e5704579b2690f670aff97880159a8c3 100644 (file)
@@ -42,6 +42,7 @@
 #include <stdio.h>
 #include <linux/bpf.h>
 #include <linux/kernel.h>
+#include <linux/hashtable.h>
 
 #include "json_writer.h"
 
@@ -70,6 +71,8 @@ extern const char *bin_name;
 
 extern json_writer_t *json_wtr;
 extern bool json_output;
+extern struct pinned_obj_table prog_table;
+extern struct pinned_obj_table map_table;
 
 void p_err(const char *fmt, ...);
 void p_info(const char *fmt, ...);
@@ -78,6 +81,20 @@ 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;
+};
+
+int build_pinned_obj_table(struct pinned_obj_table *table,
+                          enum bpf_obj_type type);
+void delete_pinned_obj_table(struct pinned_obj_table *tab);
+
 struct cmd {
        const char *cmd;
        int (*func)(int argc, char **argv);
index e978ab23a77fab49394d70d6da15258e2f9222d6..de0980657cef6f5951a5fa0855f3577d137bc353 100644 (file)
@@ -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,14 @@ 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;
 
+               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 +497,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)
index d3ab808dc882dfba69b36207e2eb9de3e53fb1c1..8f94b8ac2e6385c869ff68faa33552a7b85cfa25 100644 (file)
@@ -272,6 +272,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);
 }
 
@@ -331,6 +343,16 @@ 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;
+
+               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");
 }
 
@@ -360,6 +382,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)