tools: bpftool: show filenames of pinned objects

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>
diff --git a/tools/bpf/bpftool/common.c b/tools/bpf/bpftool/common.c
index 6b3d25d..2bd3b28 100644
--- a/tools/bpf/bpftool/common.c
+++ b/tools/bpf/bpftool/common.c
@@ -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);
+	}
+}