Commit d53dee3f authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Alexei Starovoitov
Browse files

tools/bpftool: Show info for processes holding BPF map/prog/link/btf FDs



Add bpf_iter-based way to find all the processes that hold open FDs against
BPF object (map, prog, link, btf). bpftool always attempts to discover this,
but will silently give up if kernel doesn't yet support bpf_iter BPF programs.
Process name and PID are emitted for each process (task group).

Sample output for each of 4 BPF objects:

$ sudo ./bpftool prog show
2694: cgroup_device  tag 8c42dee26e8cd4c2  gpl
        loaded_at 2020-06-16T15:34:32-0700  uid 0
        xlated 648B  jited 409B  memlock 4096B
        pids systemd(1)
2907: cgroup_skb  name egress  tag 9ad187367cf2b9e8  gpl
        loaded_at 2020-06-16T18:06:54-0700  uid 0
        xlated 48B  jited 59B  memlock 4096B  map_ids 2436
        btf_id 1202
        pids test_progs(2238417), test_progs(22384459)

$ sudo ./bpftool map show
2436: array  name test_cgr.bss  flags 0x400
        key 4B  value 8B  max_entries 1  memlock 8192B
        btf_id 1202
        pids test_progs(2238417), test_progs(22384459)
2445: array  name pid_iter.rodata  flags 0x480
        key 4B  value 4B  max_entries 1  memlock 8192B
        btf_id 1214  frozen
        pids bpftool(2239612)

$ sudo ./bpftool link show
61: cgroup  prog 2908
        cgroup_id 375301  attach_type egress
        pids test_progs(2238417), test_progs(22384459)
62: cgroup  prog 2908
        cgroup_id 375344  attach_type egress
        pids test_progs(2238417), test_progs(22384459)

$ sudo ./bpftool btf show
1202: size 1527B  prog_ids 2908,2907  map_ids 2436
        pids test_progs(2238417), test_progs(22384459)
1242: size 34684B
        pids bpftool(2258892)

Signed-off-by: default avatarAndrii Nakryiko <andriin@fb.com>
Signed-off-by: default avatarAlexei Starovoitov <ast@kernel.org>
Reviewed-by: default avatarQuentin Monnet <quentin@isovalent.com>
Link: https://lore.kernel.org/bpf/20200619231703.738941-9-andriin@fb.com
parent bd9bedf8
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -150,6 +150,8 @@ $(OUTPUT)%.skel.h: $(OUTPUT)%.bpf.o $(BPFTOOL_BOOTSTRAP)

$(OUTPUT)prog.o: $(OUTPUT)profiler.skel.h

$(OUTPUT)pids.o: $(OUTPUT)pid_iter.skel.h

endif
endif

+6 −0
Original line number Diff line number Diff line
@@ -809,6 +809,7 @@ show_btf_plain(struct bpf_btf_info *info, int fd,
			printf("%s%u", n++ == 0 ? "  map_ids " : ",",
			       obj->obj_id);
	}
	emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");

	printf("\n");
}
@@ -841,6 +842,9 @@ show_btf_json(struct bpf_btf_info *info, int fd,
			jsonw_uint(json_wtr, obj->obj_id);
	}
	jsonw_end_array(json_wtr);	/* map_ids */

	emit_obj_refs_json(&refs_table, info->id, json_wtr); /* pids */

	jsonw_end_object(json_wtr);	/* btf object */
}

@@ -893,6 +897,7 @@ static int do_show(int argc, char **argv)
			close(fd);
		return err;
	}
	build_obj_refs_table(&refs_table, BPF_OBJ_BTF);

	if (fd >= 0) {
		err = show_btf(fd, &btf_prog_table, &btf_map_table);
@@ -939,6 +944,7 @@ static int do_show(int argc, char **argv)
exit_free:
	delete_btf_table(&btf_prog_table);
	delete_btf_table(&btf_map_table);
	delete_obj_refs_table(&refs_table);

	return err;
}
+7 −0
Original line number Diff line number Diff line
@@ -143,6 +143,9 @@ static int show_link_close_json(int fd, struct bpf_link_info *info)
		}
		jsonw_end_array(json_wtr);
	}

	emit_obj_refs_json(&refs_table, info->id, json_wtr);

	jsonw_end_object(json_wtr);

	return 0;
@@ -212,6 +215,7 @@ static int show_link_close_plain(int fd, struct bpf_link_info *info)
				printf("\n\tpinned %s", obj->path);
		}
	}
	emit_obj_refs_plain(&refs_table, info->id, "\n\tpids ");

	printf("\n");

@@ -257,6 +261,7 @@ static int do_show(int argc, char **argv)

	if (show_pinned)
		build_pinned_obj_table(&link_table, BPF_OBJ_LINK);
	build_obj_refs_table(&refs_table, BPF_OBJ_LINK);

	if (argc == 2) {
		fd = link_parse_fd(&argc, &argv);
@@ -296,6 +301,8 @@ static int do_show(int argc, char **argv)
	if (json_output)
		jsonw_end_array(json_wtr);

	delete_obj_refs_table(&refs_table);

	return errno == ENOENT ? 0 : -1;
}

+1 −0
Original line number Diff line number Diff line
@@ -31,6 +31,7 @@ bool relaxed_maps;
struct pinned_obj_table prog_table;
struct pinned_obj_table map_table;
struct pinned_obj_table link_table;
struct obj_refs_table refs_table;

static void __noreturn clean_and_exit(int i)
{
+27 −0
Original line number Diff line number Diff line
@@ -127,11 +127,13 @@ static const char * const attach_type_name[__MAX_BPF_ATTACH_TYPE] = {
extern const char * const map_type_name[];
extern const size_t map_type_name_size;

/* keep in sync with the definition in skeleton/pid_iter.bpf.c */
enum bpf_obj_type {
	BPF_OBJ_UNKNOWN,
	BPF_OBJ_PROG,
	BPF_OBJ_MAP,
	BPF_OBJ_LINK,
	BPF_OBJ_BTF,
};

extern const char *bin_name;
@@ -139,12 +141,14 @@ extern const char *bin_name;
extern json_writer_t *json_wtr;
extern bool json_output;
extern bool show_pinned;
extern bool show_pids;
extern bool block_mount;
extern bool verifier_logs;
extern bool relaxed_maps;
extern struct pinned_obj_table prog_table;
extern struct pinned_obj_table map_table;
extern struct pinned_obj_table link_table;
extern struct obj_refs_table refs_table;

void __printf(1, 2) p_err(const char *fmt, ...);
void __printf(1, 2) p_info(const char *fmt, ...);
@@ -168,12 +172,35 @@ struct pinned_obj {
	struct hlist_node hash;
};

struct obj_refs_table {
	DECLARE_HASHTABLE(table, 16);
};

struct obj_ref {
	int pid;
	char comm[16];
};

struct obj_refs {
	struct hlist_node node;
	__u32 id;
	int ref_cnt;
	struct obj_ref *refs;
};

struct btf;
struct bpf_line_info;

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);
__weak int build_obj_refs_table(struct obj_refs_table *table,
				enum bpf_obj_type type);
__weak void delete_obj_refs_table(struct obj_refs_table *table);
__weak void emit_obj_refs_json(struct obj_refs_table *table, __u32 id,
			       json_writer_t *json_wtr);
__weak void emit_obj_refs_plain(struct obj_refs_table *table, __u32 id,
				const char *prefix);
void print_dev_plain(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);
void print_dev_json(__u32 ifindex, __u64 ns_dev, __u64 ns_inode);

Loading