All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCHv2 perf/core 0/7] Libbpf improvements
@ 2017-01-23  1:11 Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation Joe Stringer
                   ` (7 more replies)
  0 siblings, 8 replies; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Patch 1 fixes an issue when using drastically different BPF map definitions
inside ELFs from a client using libbpf, vs the map definition libbpf uses.

Patches 2-4 add some simple, useful helper functions for setting prog type
and retrieving libbpf errors without depending on kernel headers from
userspace programs.

Patches 5-7 add a new pinning functionality for maps, programs, and objects.
Library users may call bpf_map__pin(map, path) or bpf_program__pin(prog, path)
to pin maps and programs separately, or use bpf_object__pin(obj, path) to
pin all maps and programs from the BPF object to the path. The map and program
variations require a full path where it will be pinned in the filesystem,
and the object variation will create directories "maps/" and "progs/" under
the specified path, then mount each map and program under those subdirectories.

---
v1: Initial post.
v2: Wang Nan provided improvements to patch 1.
    Dropped patch 2 from v1.
    Added acks for acked patches.
    Split the bpf_obj__pin() to also provide map / program pinning APIs.
    Allow users to provide full filesystem path (don't autodetect/mount BPFFS).

Joe Stringer (7):
  tools lib bpf: Fix map offsets in relocation
  tools lib bpf: Define prog_type fns with macro
  tools lib bpf: Add set/is helpers for all prog types
  tools lib bpf: Add libbpf_get_error()
  tools lib bpf: Add bpf_program__pin()
  tools lib bpf: Add bpf_map__pin()
  tools lib bpf: Add bpf_object__pin()

 tools/lib/bpf/libbpf.c  | 240 ++++++++++++++++++++++++++++++++++++++++++------
 tools/lib/bpf/libbpf.h  |  17 +++-
 tools/perf/tests/llvm.c |   2 +-
 3 files changed, 229 insertions(+), 30 deletions(-)

-- 
2.11.0

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-26 15:29   ` [tip:perf/core] " tip-bot for Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 2/7] tools lib bpf: Define prog_type fns with macro Joe Stringer
                   ` (6 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme
  Cc: wangnan0, ast, daniel, linux-kernel, netdev, Arnaldo Carvalho de Melo

Commit 4708bbda5cb2 ("tools lib bpf: Fix maps resolution") attempted to
fix map resolution by identifying the number of symbols that point to
maps, and using this number to resolve each of the maps.

However, during relocation the original definition of the map size was
still in use. For up to two maps, the calculation was correct if there
was a small difference in size between the map definition in libbpf and
the one that the client library uses. However if the difference was
large, particularly if more than two maps were used in the BPF program,
the relocation would fail.

For example, when using a map definition with size 28, with three maps,
map relocation would count
    (sym_offset / sizeof(struct bpf_map_def) => map_idx)
    (0 / 16 => 0), ie map_idx = 0
    (28 / 16 => 1), ie map_idx = 1
    (56 / 16 => 3), ie map_idx = 3

So, libbpf reports:
    libbpf: bpf relocation: map_idx 3 large than 2

Fix map relocation by checking the exact offset of maps when doing
relocation.

Fixes: 4708bbda5cb2 ("tools lib bpf: Fix maps resolution")
Signed-off-by: Joe Stringer <joe@ovn.org>
Signed-off-by: Wang Nan <wangnan0@huawei.com>
[Allow different map size in an object]
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
---
v2: Use cached offsets of maps for relocation (Wang Nan)

This is a repost of the version Wang Nan posted on Jan 19.
---
 tools/lib/bpf/libbpf.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84e6b35da4bd..671d5ad07cf1 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -779,7 +779,7 @@ static int
 bpf_program__collect_reloc(struct bpf_program *prog,
 			   size_t nr_maps, GElf_Shdr *shdr,
 			   Elf_Data *data, Elf_Data *symbols,
-			   int maps_shndx)
+			   int maps_shndx, struct bpf_map *maps)
 {
 	int i, nrels;
 
@@ -829,7 +829,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__RELOC;
 		}
 
-		map_idx = sym.st_value / sizeof(struct bpf_map_def);
+		/* TODO: 'maps' is sorted. We can use bsearch to make it faster. */
+		for (map_idx = 0; map_idx < nr_maps; map_idx++) {
+			if (maps[map_idx].offset == sym.st_value) {
+				pr_debug("relocation: find map %zd (%s) for insn %u\n",
+					 map_idx, maps[map_idx].name, insn_idx);
+				break;
+			}
+		}
+
 		if (map_idx >= nr_maps) {
 			pr_warning("bpf relocation: map_idx %d large than %d\n",
 				   (int)map_idx, (int)nr_maps - 1);
@@ -953,7 +961,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 		err = bpf_program__collect_reloc(prog, nr_maps,
 						 shdr, data,
 						 obj->efile.symbols,
-						 obj->efile.maps_shndx);
+						 obj->efile.maps_shndx,
+						 obj->maps);
 		if (err)
 			return err;
 	}
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 2/7] tools lib bpf: Define prog_type fns with macro
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-26 15:30   ` [tip:perf/core] " tip-bot for Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 3/7] tools lib bpf: Add set/is helpers for all prog types Joe Stringer
                   ` (5 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Turning this into a macro allows future prog types to be added with a
single line per type.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
---
v2: Add ack.
---
 tools/lib/bpf/libbpf.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 671d5ad07cf1..371cb40a2304 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1428,37 +1428,28 @@ static void bpf_program__set_type(struct bpf_program *prog,
 	prog->type = type;
 }
 
-int bpf_program__set_tracepoint(struct bpf_program *prog)
-{
-	if (!prog)
-		return -EINVAL;
-	bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
-	return 0;
-}
-
-int bpf_program__set_kprobe(struct bpf_program *prog)
-{
-	if (!prog)
-		return -EINVAL;
-	bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
-	return 0;
-}
-
 static bool bpf_program__is_type(struct bpf_program *prog,
 				 enum bpf_prog_type type)
 {
 	return prog ? (prog->type == type) : false;
 }
 
-bool bpf_program__is_tracepoint(struct bpf_program *prog)
-{
-	return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT);
-}
-
-bool bpf_program__is_kprobe(struct bpf_program *prog)
-{
-	return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE);
-}
+#define BPF_PROG_TYPE_FNS(NAME, TYPE)			\
+int bpf_program__set_##NAME(struct bpf_program *prog)	\
+{							\
+	if (!prog)					\
+		return -EINVAL;				\
+	bpf_program__set_type(prog, TYPE);		\
+	return 0;					\
+}							\
+							\
+bool bpf_program__is_##NAME(struct bpf_program *prog)	\
+{							\
+	return bpf_program__is_type(prog, TYPE);	\
+}							\
+
+BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
+BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
 
 int bpf_map__fd(struct bpf_map *map)
 {
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 3/7] tools lib bpf: Add set/is helpers for all prog types
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 2/7] tools lib bpf: Define prog_type fns with macro Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-26 15:30   ` [tip:perf/core] " tip-bot for Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 4/7] tools lib bpf: Add libbpf_get_error() Joe Stringer
                   ` (4 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

These bpf_prog_types were exposed in the uapi but there were no
corresponding functions to set these types for programs in libbpf.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
---
v2: Add ack.
---
 tools/lib/bpf/libbpf.c |  5 +++++
 tools/lib/bpf/libbpf.h | 10 ++++++++++
 2 files changed, 15 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 371cb40a2304..406838fa9c4f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1448,8 +1448,13 @@ bool bpf_program__is_##NAME(struct bpf_program *prog)	\
 	return bpf_program__is_type(prog, TYPE);	\
 }							\
 
+BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
 BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
+BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
+BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
 BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
+BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
+BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
 
 int bpf_map__fd(struct bpf_map *map)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a5a8b86a06fe..2188ccdc0e2d 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -174,11 +174,21 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n);
 /*
  * Adjust type of bpf program. Default is kprobe.
  */
+int bpf_program__set_socket_filter(struct bpf_program *prog);
 int bpf_program__set_tracepoint(struct bpf_program *prog);
 int bpf_program__set_kprobe(struct bpf_program *prog);
+int bpf_program__set_sched_cls(struct bpf_program *prog);
+int bpf_program__set_sched_act(struct bpf_program *prog);
+int bpf_program__set_xdp(struct bpf_program *prog);
+int bpf_program__set_perf_event(struct bpf_program *prog);
 
+bool bpf_program__is_socket_filter(struct bpf_program *prog);
 bool bpf_program__is_tracepoint(struct bpf_program *prog);
 bool bpf_program__is_kprobe(struct bpf_program *prog);
+bool bpf_program__is_sched_cls(struct bpf_program *prog);
+bool bpf_program__is_sched_act(struct bpf_program *prog);
+bool bpf_program__is_xdp(struct bpf_program *prog);
+bool bpf_program__is_perf_event(struct bpf_program *prog);
 
 /*
  * We don't need __attribute__((packed)) now since it is
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 4/7] tools lib bpf: Add libbpf_get_error()
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
                   ` (2 preceding siblings ...)
  2017-01-23  1:11 ` [PATCHv2 perf/core 3/7] tools lib bpf: Add set/is helpers for all prog types Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-26 15:31   ` [tip:perf/core] " tip-bot for Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin() Joe Stringer
                   ` (3 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

This function will turn a libbpf pointer into a standard error code (or
0 if the pointer is valid). This also allows removal of the dependency
on linux/err.h in the public header file, which causes problems in
userspace programs built against libbpf.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
---
v2: Add ack.
---
 tools/lib/bpf/libbpf.c  | 8 ++++++++
 tools/lib/bpf/libbpf.h  | 4 +++-
 tools/perf/tests/llvm.c | 2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 406838fa9c4f..e6cd62b1264b 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/bpf.h>
 #include <linux/list.h>
@@ -1542,3 +1543,10 @@ bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
 	}
 	return ERR_PTR(-ENOENT);
 }
+
+long libbpf_get_error(const void *ptr)
+{
+	if (IS_ERR(ptr))
+		return PTR_ERR(ptr);
+	return 0;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 2188ccdc0e2d..4014d1ba5e3d 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -22,8 +22,8 @@
 #define __BPF_LIBBPF_H
 
 #include <stdio.h>
+#include <stdint.h>
 #include <stdbool.h>
-#include <linux/err.h>
 #include <sys/types.h>  // for size_t
 
 enum libbpf_errno {
@@ -234,4 +234,6 @@ int bpf_map__set_priv(struct bpf_map *map, void *priv,
 		      bpf_map_clear_priv_t clear_priv);
 void *bpf_map__priv(struct bpf_map *map);
 
+long libbpf_get_error(const void *ptr);
+
 #endif
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 02a33ebcd992..d357dab72e68 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -13,7 +13,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
 	struct bpf_object *obj;
 
 	obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
-	if (IS_ERR(obj))
+	if (libbpf_get_error(obj))
 		return TEST_FAIL;
 	bpf_object__close(obj);
 	return TEST_OK;
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
                   ` (3 preceding siblings ...)
  2017-01-23  1:11 ` [PATCHv2 perf/core 4/7] tools lib bpf: Add libbpf_get_error() Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-25  1:04   ` Wangnan (F)
  2017-01-23  1:11 ` [PATCHv2 perf/core 6/7] tools lib bpf: Add bpf_map__pin() Joe Stringer
                   ` (2 subsequent siblings)
  7 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Add a new API to pin a BPF program to the filesystem. The user can
specify the path full path within a BPF filesystem to pin the program.
Programs with multiple instances are pinned as 'foo', 'foo_1', 'foo_2',
and so on.

Signed-off-by: Joe Stringer <joe@ovn.org>
---
v2: Don't automount BPF filesystem
    Split program, map, object pinning into separate APIs and separate
    patches.
---
 tools/lib/bpf/libbpf.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  1 +
 2 files changed, 77 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e6cd62b1264b..eea5c74808f7 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -4,6 +4,7 @@
  * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
  * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
  * Copyright (C) 2015 Huawei Inc.
+ * Copyright (C) 2017 Nicira, Inc.
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -22,6 +23,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <stdarg.h>
+#include <libgen.h>
 #include <inttypes.h>
 #include <string.h>
 #include <unistd.h>
@@ -31,7 +33,10 @@
 #include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/bpf.h>
+#include <linux/magic.h>
 #include <linux/list.h>
+#include <linux/limits.h>
+#include <sys/vfs.h>
 #include <libelf.h>
 #include <gelf.h>
 
@@ -1237,6 +1242,77 @@ int bpf_object__load(struct bpf_object *obj)
 	return err;
 }
 
+static int check_path(const char *path)
+{
+	struct statfs st_fs;
+	char *dname, *dir;
+	int err = 0;
+
+	if (path == NULL)
+		return -EINVAL;
+
+	dname = strdup(path);
+	dir = dirname(dname);
+	if (statfs(dir, &st_fs)) {
+		pr_warning("failed to statfs %s: %s\n", dir, strerror(errno));
+		err = -errno;
+	}
+	free(dname);
+
+	if (!err && st_fs.f_type != BPF_FS_MAGIC) {
+		pr_warning("specified path %s is not on BPF FS\n", path);
+		err = -EINVAL;
+	}
+
+	return err;
+}
+
+int bpf_program__pin(struct bpf_program *prog, const char *path)
+{
+	int i, err;
+
+	err = check_path(path);
+	if (err)
+		return err;
+
+	if (prog == NULL) {
+		pr_warning("invalid program pointer\n");
+		return -EINVAL;
+	}
+
+	if (prog->instances.nr <= 0) {
+		pr_warning("no instances of prog %s to pin\n",
+			   prog->section_name);
+		return -EINVAL;
+	}
+
+	if (bpf_obj_pin(prog->instances.fds[0], path)) {
+		pr_warning("failed to pin program: %s\n", strerror(errno));
+		return -errno;
+	}
+	pr_debug("pinned program '%s'\n", path);
+
+	for (i = 1; i < prog->instances.nr; i++) {
+		char buf[PATH_MAX];
+		int len;
+
+		len = snprintf(buf, PATH_MAX, "%s_%d", path, i);
+		if (len < 0)
+			return -EINVAL;
+		else if (len > PATH_MAX)
+			return -ENAMETOOLONG;
+
+		if (bpf_obj_pin(prog->instances.fds[i], buf)) {
+			pr_warning("failed to pin program: %s\n",
+				   strerror(errno));
+			return -errno;
+		}
+		pr_debug("pinned program '%s'\n", buf);
+	}
+
+	return 0;
+}
+
 void bpf_object__close(struct bpf_object *obj)
 {
 	size_t i;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 4014d1ba5e3d..7973087c377b 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -106,6 +106,7 @@ void *bpf_program__priv(struct bpf_program *prog);
 const char *bpf_program__title(struct bpf_program *prog, bool needs_copy);
 
 int bpf_program__fd(struct bpf_program *prog);
+int bpf_program__pin(struct bpf_program *prog, const char *path);
 
 struct bpf_insn;
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 6/7] tools lib bpf: Add bpf_map__pin()
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
                   ` (4 preceding siblings ...)
  2017-01-23  1:11 ` [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin() Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-23  1:11 ` [PATCHv2 perf/core 7/7] tools lib bpf: Add bpf_object__pin() Joe Stringer
  2017-01-24 16:12 ` [PATCHv2 perf/core 0/7] Libbpf improvements Arnaldo Carvalho de Melo
  7 siblings, 0 replies; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Add a new API to pin a BPF map to the filesystem. The user can
specify the path full path within a BPF filesystem to pin the map.

Signed-off-by: Joe Stringer <joe@ovn.org>
---
v2: Don't automount BPF filesystem
    Split program, map, object pinning into separate APIs and separate
    patches.
---
 tools/lib/bpf/libbpf.c | 22 ++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  1 +
 2 files changed, 23 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index eea5c74808f7..c1d8b07e21d2 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1313,6 +1313,28 @@ int bpf_program__pin(struct bpf_program *prog, const char *path)
 	return 0;
 }
 
+int bpf_map__pin(struct bpf_map *map, const char *path)
+{
+	int err;
+
+	err = check_path(path);
+	if (err)
+		return err;
+
+	if (map == NULL) {
+		pr_warning("invalid map pointer\n");
+		return -EINVAL;
+	}
+
+	if (bpf_obj_pin(map->fd, path)) {
+		pr_warning("failed to pin map: %s\n", strerror(errno));
+		return -errno;
+	}
+
+	pr_debug("pinned map '%s'\n", path);
+	return 0;
+}
+
 void bpf_object__close(struct bpf_object *obj)
 {
 	size_t i;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 7973087c377b..524247cfd205 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -234,6 +234,7 @@ typedef void (*bpf_map_clear_priv_t)(struct bpf_map *, void *);
 int bpf_map__set_priv(struct bpf_map *map, void *priv,
 		      bpf_map_clear_priv_t clear_priv);
 void *bpf_map__priv(struct bpf_map *map);
+int bpf_map__pin(struct bpf_map *map, const char *path);
 
 long libbpf_get_error(const void *ptr);
 
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [PATCHv2 perf/core 7/7] tools lib bpf: Add bpf_object__pin()
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
                   ` (5 preceding siblings ...)
  2017-01-23  1:11 ` [PATCHv2 perf/core 6/7] tools lib bpf: Add bpf_map__pin() Joe Stringer
@ 2017-01-23  1:11 ` Joe Stringer
  2017-01-24 16:12 ` [PATCHv2 perf/core 0/7] Libbpf improvements Arnaldo Carvalho de Melo
  7 siblings, 0 replies; 20+ messages in thread
From: Joe Stringer @ 2017-01-23  1:11 UTC (permalink / raw)
  To: acme; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Add a new API to pin a BPF object to the filesystem. The user can
specify the path full path within a BPF filesystem to pin the object.
Programs will be pinned under a subdirectory 'progs', and maps will be
pinned under a subdirectory 'maps'.

For example, with the directory '/sys/fs/bpf/foo':
/sys/fs/bpf/foo/progs/PROG_NAME
/sys/fs/bpf/foo/maps/MAP_NAME

Signed-off-by: Joe Stringer <joe@ovn.org>
---
v2: Don't automount BPF filesystem
    Split program, map, object pinning into separate APIs and separate
    patches.
---
 tools/lib/bpf/libbpf.c | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++
 tools/lib/bpf/libbpf.h |  1 +
 2 files changed, 74 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index c1d8b07e21d2..41645dc51fa1 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -36,6 +36,7 @@
 #include <linux/magic.h>
 #include <linux/list.h>
 #include <linux/limits.h>
+#include <sys/stat.h>
 #include <sys/vfs.h>
 #include <libelf.h>
 #include <gelf.h>
@@ -1335,6 +1336,78 @@ int bpf_map__pin(struct bpf_map *map, const char *path)
 	return 0;
 }
 
+static int make_dir(const char *path, const char *dir)
+{
+	char buf[PATH_MAX];
+	int len, err = 0;
+
+	len = snprintf(buf, PATH_MAX, "%s/%s", path, dir);
+	if (len < 0)
+		err = -EINVAL;
+	else if (len >= PATH_MAX)
+		err = -ENAMETOOLONG;
+	if (!err && mkdir(buf, 0700) && errno != EEXIST)
+		err = -errno;
+
+	if (err)
+		pr_warning("failed to make dir %s/%s: %s\n", path, dir,
+			   strerror(-err));
+	return err;
+}
+
+int bpf_object__pin(struct bpf_object *obj, const char *path)
+{
+	struct bpf_program *prog;
+	struct bpf_map *map;
+	int err;
+
+	if (!obj)
+		return -ENOENT;
+
+	if (!obj->loaded) {
+		pr_warning("object not yet loaded; load it first\n");
+		return -ENOENT;
+	}
+
+	err = make_dir(path, "maps");
+	if (err)
+		return err;
+
+	bpf_map__for_each(map, obj) {
+		char buf[PATH_MAX];
+		int len;
+
+		len = snprintf(buf, PATH_MAX, "%s/maps/%s", path,
+			       bpf_map__name(map));
+		if (len < 0 || len > PATH_MAX)
+			return -EINVAL;
+
+		err = bpf_map__pin(map, buf);
+		if (err)
+			return err;
+	}
+
+	err = make_dir(path, "progs");
+	if (err)
+		return err;
+
+	bpf_object__for_each_program(prog, obj) {
+		char buf[PATH_MAX];
+		int len;
+
+		len = snprintf(buf, PATH_MAX, "%s/progs/%s", path,
+			       prog->section_name);
+		if (len < 0 || len > PATH_MAX)
+			return -EINVAL;
+
+		err = bpf_program__pin(prog, buf);
+		if (err)
+			return err;
+	}
+
+	return 0;
+}
+
 void bpf_object__close(struct bpf_object *obj)
 {
 	size_t i;
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 524247cfd205..8363ee6db4a0 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -65,6 +65,7 @@ struct bpf_object *bpf_object__open(const char *path);
 struct bpf_object *bpf_object__open_buffer(void *obj_buf,
 					   size_t obj_buf_sz,
 					   const char *name);
+int bpf_object__pin(struct bpf_object *object, const char *path);
 void bpf_object__close(struct bpf_object *object);
 
 /* Load/unload object into/from kernel */
-- 
2.11.0

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 0/7] Libbpf improvements
  2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
                   ` (6 preceding siblings ...)
  2017-01-23  1:11 ` [PATCHv2 perf/core 7/7] tools lib bpf: Add bpf_object__pin() Joe Stringer
@ 2017-01-24 16:12 ` Arnaldo Carvalho de Melo
  2017-01-25  0:50   ` Joe Stringer
  7 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-01-24 16:12 UTC (permalink / raw)
  To: Joe Stringer; +Cc: wangnan0, ast, daniel, linux-kernel, netdev

Em Sun, Jan 22, 2017 at 05:11:21PM -0800, Joe Stringer escreveu:
> Patch 1 fixes an issue when using drastically different BPF map definitions
> inside ELFs from a client using libbpf, vs the map definition libbpf uses.
> 
> Patches 2-4 add some simple, useful helper functions for setting prog type
> and retrieving libbpf errors without depending on kernel headers from
> userspace programs.
> 
> Patches 5-7 add a new pinning functionality for maps, programs, and objects.
> Library users may call bpf_map__pin(map, path) or bpf_program__pin(prog, path)
> to pin maps and programs separately, or use bpf_object__pin(obj, path) to
> pin all maps and programs from the BPF object to the path. The map and program
> variations require a full path where it will be pinned in the filesystem,
> and the object variation will create directories "maps/" and "progs/" under
> the specified path, then mount each map and program under those subdirectories.

Merged the ones either acked by Wang or adjusted by you to address
Wang's remarks, the last ones introducing those __pin() methods, please
provide users together with those APIs, preferably entries for 'perf
test',

- Arnaldo
 
> ---
> v1: Initial post.
> v2: Wang Nan provided improvements to patch 1.
>     Dropped patch 2 from v1.
>     Added acks for acked patches.
>     Split the bpf_obj__pin() to also provide map / program pinning APIs.
>     Allow users to provide full filesystem path (don't autodetect/mount BPFFS).
> 
> Joe Stringer (7):
>   tools lib bpf: Fix map offsets in relocation
>   tools lib bpf: Define prog_type fns with macro
>   tools lib bpf: Add set/is helpers for all prog types
>   tools lib bpf: Add libbpf_get_error()
>   tools lib bpf: Add bpf_program__pin()
>   tools lib bpf: Add bpf_map__pin()
>   tools lib bpf: Add bpf_object__pin()
> 
>  tools/lib/bpf/libbpf.c  | 240 ++++++++++++++++++++++++++++++++++++++++++------
>  tools/lib/bpf/libbpf.h  |  17 +++-
>  tools/perf/tests/llvm.c |   2 +-
>  3 files changed, 229 insertions(+), 30 deletions(-)
> 
> -- 
> 2.11.0

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 0/7] Libbpf improvements
  2017-01-24 16:12 ` [PATCHv2 perf/core 0/7] Libbpf improvements Arnaldo Carvalho de Melo
@ 2017-01-25  0:50   ` Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: Joe Stringer @ 2017-01-25  0:50 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: Wang Nan, ast, Daniel Borkmann, LKML, netdev

On 24 January 2017 at 08:12, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Em Sun, Jan 22, 2017 at 05:11:21PM -0800, Joe Stringer escreveu:
>> Patch 1 fixes an issue when using drastically different BPF map definitions
>> inside ELFs from a client using libbpf, vs the map definition libbpf uses.
>>
>> Patches 2-4 add some simple, useful helper functions for setting prog type
>> and retrieving libbpf errors without depending on kernel headers from
>> userspace programs.
>>
>> Patches 5-7 add a new pinning functionality for maps, programs, and objects.
>> Library users may call bpf_map__pin(map, path) or bpf_program__pin(prog, path)
>> to pin maps and programs separately, or use bpf_object__pin(obj, path) to
>> pin all maps and programs from the BPF object to the path. The map and program
>> variations require a full path where it will be pinned in the filesystem,
>> and the object variation will create directories "maps/" and "progs/" under
>> the specified path, then mount each map and program under those subdirectories.
>
> Merged the ones either acked by Wang or adjusted by you to address
> Wang's remarks, the last ones introducing those __pin() methods, please
> provide users together with those APIs, preferably entries for 'perf
> test',

OK great, I'll rebase the last 3 patches and add a test to perf test
for pinning.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-23  1:11 ` [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin() Joe Stringer
@ 2017-01-25  1:04   ` Wangnan (F)
  2017-01-25  1:06     ` Wangnan (F)
  0 siblings, 1 reply; 20+ messages in thread
From: Wangnan (F) @ 2017-01-25  1:04 UTC (permalink / raw)
  To: Joe Stringer, acme; +Cc: ast, daniel, linux-kernel, netdev



On 2017/1/23 9:11, Joe Stringer wrote:
> Add a new API to pin a BPF program to the filesystem. The user can
> specify the path full path within a BPF filesystem to pin the program.
> Programs with multiple instances are pinned as 'foo', 'foo_1', 'foo_2',
> and so on.
>
> Signed-off-by: Joe Stringer <joe@ovn.org>
> ---
> v2: Don't automount BPF filesystem
>      Split program, map, object pinning into separate APIs and separate
>      patches.
> ---
>   tools/lib/bpf/libbpf.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++
>   tools/lib/bpf/libbpf.h |  1 +
>   2 files changed, 77 insertions(+)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index e6cd62b1264b..eea5c74808f7 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -4,6 +4,7 @@
>    * Copyright (C) 2013-2015 Alexei Starovoitov <ast@kernel.org>
>    * Copyright (C) 2015 Wang Nan <wangnan0@huawei.com>
>    * Copyright (C) 2015 Huawei Inc.
> + * Copyright (C) 2017 Nicira, Inc.
>    *
>    * This program is free software; you can redistribute it and/or
>    * modify it under the terms of the GNU Lesser General Public
> @@ -22,6 +23,7 @@
>   #include <stdlib.h>
>   #include <stdio.h>
>   #include <stdarg.h>
> +#include <libgen.h>
>   #include <inttypes.h>
>   #include <string.h>
>   #include <unistd.h>
> @@ -31,7 +33,10 @@
>   #include <linux/err.h>
>   #include <linux/kernel.h>
>   #include <linux/bpf.h>
> +#include <linux/magic.h>
>   #include <linux/list.h>
> +#include <linux/limits.h>
> +#include <sys/vfs.h>
>   #include <libelf.h>
>   #include <gelf.h>
>   
> @@ -1237,6 +1242,77 @@ int bpf_object__load(struct bpf_object *obj)
>   	return err;
>   }
>   
> +static int check_path(const char *path)
> +{
> +	struct statfs st_fs;
> +	char *dname, *dir;
> +	int err = 0;
> +
> +	if (path == NULL)
> +		return -EINVAL;
> +
> +	dname = strdup(path);
> +	dir = dirname(dname);
> +	if (statfs(dir, &st_fs)) {
> +		pr_warning("failed to statfs %s: %s\n", dir, strerror(errno));
> +		err = -errno;
> +	}
> +	free(dname);
> +
> +	if (!err && st_fs.f_type != BPF_FS_MAGIC) {
> +		pr_warning("specified path %s is not on BPF FS\n", path);
> +		err = -EINVAL;
> +	}
> +
> +	return err;
> +}
> +
> +int bpf_program__pin(struct bpf_program *prog, const char *path)

In your next patch please let caller select one instance:

int bpf_program__pin(struct bpf_program *prog, int instance, const char 
*path)
(please choose a better name)

Then your can wrap it with another function to pin all instances, implement
naming schema (%s_%d) there.

Then implement naming schema in bpf_object__pin like:

%s/objectname_mapname
%s/objectname_progname_%d

and make a bpf_{map,program}__pin the raw pinning functions with no 
naming schema.

Thank you.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-25  1:04   ` Wangnan (F)
@ 2017-01-25  1:06     ` Wangnan (F)
  2017-01-25  1:16       ` Joe Stringer
  0 siblings, 1 reply; 20+ messages in thread
From: Wangnan (F) @ 2017-01-25  1:06 UTC (permalink / raw)
  To: Joe Stringer, acme; +Cc: ast, daniel, linux-kernel, netdev



On 2017/1/25 9:04, Wangnan (F) wrote:
>
>
> On 2017/1/23 9:11, Joe Stringer wrote:
>> Add a new API to pin a BPF program to the filesystem. The user can
>> specify the path full path within a BPF filesystem to pin the program.
>> Programs with multiple instances are pinned as 'foo', 'foo_1', 'foo_2',
>> and so on.
>>
>> Signed-off-by: Joe Stringer <joe@ovn.org>
>> ---
>> v2: Don't automount BPF filesystem
>>      Split program, map, object pinning into separate APIs and separate
>>      patches.
>> ---

[SNIP]

>> +int bpf_program__pin(struct bpf_program *prog, const char *path)
>
> In your next patch please let caller select one instance:
>
> int bpf_program__pin(struct bpf_program *prog, int instance, const 
> char *path)
> (please choose a better name)
>
> Then your can wrap it with another function to pin all instances, 
> implement
> naming schema (%s_%d) there.
>
> Then implement naming schema in bpf_object__pin like:
>
> %s/objectname_mapname
> %s/objectname_progname_%d
>

Is it possible to use directory tree instead?

%s/object/mapname
%s/object/prog/instance

Thank you.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-25  1:06     ` Wangnan (F)
@ 2017-01-25  1:16       ` Joe Stringer
  2017-01-25  2:18         ` Wangnan (F)
  0 siblings, 1 reply; 20+ messages in thread
From: Joe Stringer @ 2017-01-25  1:16 UTC (permalink / raw)
  To: Wangnan (F); +Cc: Arnaldo Carvalho de Melo, ast, Daniel Borkmann, LKML, netdev

On 24 January 2017 at 17:06, Wangnan (F) <wangnan0@huawei.com> wrote:
>
>
> On 2017/1/25 9:04, Wangnan (F) wrote:
>>
>>
>>
>> On 2017/1/23 9:11, Joe Stringer wrote:
>>>
>>> Add a new API to pin a BPF program to the filesystem. The user can
>>> specify the path full path within a BPF filesystem to pin the program.
>>> Programs with multiple instances are pinned as 'foo', 'foo_1', 'foo_2',
>>> and so on.
>>>
>>> Signed-off-by: Joe Stringer <joe@ovn.org>
>>> ---
>>> v2: Don't automount BPF filesystem
>>>      Split program, map, object pinning into separate APIs and separate
>>>      patches.
>>> ---
>
>
> [SNIP]
>
>>> +int bpf_program__pin(struct bpf_program *prog, const char *path)
>>
>>
>> In your next patch please let caller select one instance:
>>
>> int bpf_program__pin(struct bpf_program *prog, int instance, const char
>> *path)
>> (please choose a better name)
>>
>> Then your can wrap it with another function to pin all instances,
>> implement
>> naming schema (%s_%d) there.
>>
>> Then implement naming schema in bpf_object__pin like:
>>
>> %s/objectname_mapname
>> %s/objectname_progname_%d
>>
>
> Is it possible to use directory tree instead?
>
> %s/object/mapname
> %s/object/prog/instance

I don't think objects have names, so let's assume an object with two
program instances named foo, and one map named bar.

A call of bpf_object__pin(obj, "/sys/fs/bpf/myobj") would mount with
the following files and directories:
/sys/fs/bpf/myobj/foo/1
/sys/fs/bpf/myobj/foo/2
/sys/fs/bpf/myobj/bar

Alternatively, if you want to control exactly where you want the
progs/maps to be pinned, you can call eg
bpf_program__pin_instance(prog, "/sys/fs/bpf/wherever", 0) and that
instance will be mounted to /sys/fs/bpf/wherever, or alternatively
bpf_program__pin(prog, "/sys/fs/bpf/foo"), and you will end up with
/sys/fs/bpf/foo/{0,1}.

This looks pretty reasonable to me.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-25  1:16       ` Joe Stringer
@ 2017-01-25  2:18         ` Wangnan (F)
  2017-01-26 19:32           ` Arnaldo Carvalho de Melo
  0 siblings, 1 reply; 20+ messages in thread
From: Wangnan (F) @ 2017-01-25  2:18 UTC (permalink / raw)
  To: Joe Stringer; +Cc: Arnaldo Carvalho de Melo, ast, Daniel Borkmann, LKML, netdev



On 2017/1/25 9:16, Joe Stringer wrote:
> On 24 January 2017 at 17:06, Wangnan (F) <wangnan0@huawei.com> wrote:
>>
>> On 2017/1/25 9:04, Wangnan (F) wrote:
>>>
>>>
>>> On 2017/1/23 9:11, Joe Stringer wrote:
>>>> Add a new API to pin a BPF program to the filesystem. The user can
>>>> specify the path full path within a BPF filesystem to pin the program.
>>>> Programs with multiple instances are pinned as 'foo', 'foo_1', 'foo_2',
>>>> and so on.
>>>>
>>>> Signed-off-by: Joe Stringer <joe@ovn.org>
>>>> ---
>>>> v2: Don't automount BPF filesystem
>>>>       Split program, map, object pinning into separate APIs and separate
>>>>       patches.
>>>> ---
>>
>> [SNIP]
>>
>>>> +int bpf_program__pin(struct bpf_program *prog, const char *path)
>>>
>>> In your next patch please let caller select one instance:
>>>
>>> int bpf_program__pin(struct bpf_program *prog, int instance, const char
>>> *path)
>>> (please choose a better name)
>>>
>>> Then your can wrap it with another function to pin all instances,
>>> implement
>>> naming schema (%s_%d) there.
>>>
>>> Then implement naming schema in bpf_object__pin like:
>>>
>>> %s/objectname_mapname
>>> %s/objectname_progname_%d
>>>
>> Is it possible to use directory tree instead?
>>
>> %s/object/mapname
>> %s/object/prog/instance
> I don't think objects have names, so let's assume an object with two
> program instances named foo, and one map named bar.
>
> A call of bpf_object__pin(obj, "/sys/fs/bpf/myobj") would mount with
> the following files and directories:
> /sys/fs/bpf/myobj/foo/1
> /sys/fs/bpf/myobj/foo/2
> /sys/fs/bpf/myobj/bar
>
> Alternatively, if you want to control exactly where you want the
> progs/maps to be pinned, you can call eg
> bpf_program__pin_instance(prog, "/sys/fs/bpf/wherever", 0) and that
> instance will be mounted to /sys/fs/bpf/wherever, or alternatively
> bpf_program__pin(prog, "/sys/fs/bpf/foo"), and you will end up with
> /sys/fs/bpf/foo/{0,1}.
>
> This looks pretty reasonable to me.

It looks good to me.

Thank you.

^ permalink raw reply	[flat|nested] 20+ messages in thread

* [tip:perf/core] tools lib bpf: Fix map offsets in relocation
  2017-01-23  1:11 ` [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation Joe Stringer
@ 2017-01-26 15:29   ` tip-bot for Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Joe Stringer @ 2017-01-26 15:29 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: linux-kernel, wangnan0, daniel, ast, acme, hpa, joe, mingo, tglx

Commit-ID:  94e5adece8b37a23d99fb1f8a5de94b23194f387
Gitweb:     http://git.kernel.org/tip/94e5adece8b37a23d99fb1f8a5de94b23194f387
Author:     Joe Stringer <joe@ovn.org>
AuthorDate: Sun, 22 Jan 2017 17:11:22 -0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Jan 2017 11:42:56 -0300

tools lib bpf: Fix map offsets in relocation

Commit 4708bbda5cb2 ("tools lib bpf: Fix maps resolution") attempted to
fix map resolution by identifying the number of symbols that point to
maps, and using this number to resolve each of the maps.

However, during relocation the original definition of the map size was
still in use. For up to two maps, the calculation was correct if there
was a small difference in size between the map definition in libbpf and
the one that the client library uses. However if the difference was
large, particularly if more than two maps were used in the BPF program,
the relocation would fail.

For example, when using a map definition with size 28, with three maps,
map relocation would count:

    (sym_offset / sizeof(struct bpf_map_def) => map_idx)
    (0 / 16 => 0), ie map_idx = 0
    (28 / 16 => 1), ie map_idx = 1
    (56 / 16 => 3), ie map_idx = 3

So, libbpf reports:

    libbpf: bpf relocation: map_idx 3 large than 2

Fix map relocation by checking the exact offset of maps when doing
relocation.

Signed-off-by: Joe Stringer <joe@ovn.org>
[Allow different map size in an object]
Signed-off-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: netdev@vger.kernel.org
Fixes: 4708bbda5cb2 ("tools lib bpf: Fix maps resolution")
Link: http://lkml.kernel.org/r/20170123011128.26534-2-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 84e6b35..671d5ad 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -779,7 +779,7 @@ static int
 bpf_program__collect_reloc(struct bpf_program *prog,
 			   size_t nr_maps, GElf_Shdr *shdr,
 			   Elf_Data *data, Elf_Data *symbols,
-			   int maps_shndx)
+			   int maps_shndx, struct bpf_map *maps)
 {
 	int i, nrels;
 
@@ -829,7 +829,15 @@ bpf_program__collect_reloc(struct bpf_program *prog,
 			return -LIBBPF_ERRNO__RELOC;
 		}
 
-		map_idx = sym.st_value / sizeof(struct bpf_map_def);
+		/* TODO: 'maps' is sorted. We can use bsearch to make it faster. */
+		for (map_idx = 0; map_idx < nr_maps; map_idx++) {
+			if (maps[map_idx].offset == sym.st_value) {
+				pr_debug("relocation: find map %zd (%s) for insn %u\n",
+					 map_idx, maps[map_idx].name, insn_idx);
+				break;
+			}
+		}
+
 		if (map_idx >= nr_maps) {
 			pr_warning("bpf relocation: map_idx %d large than %d\n",
 				   (int)map_idx, (int)nr_maps - 1);
@@ -953,7 +961,8 @@ static int bpf_object__collect_reloc(struct bpf_object *obj)
 		err = bpf_program__collect_reloc(prog, nr_maps,
 						 shdr, data,
 						 obj->efile.symbols,
-						 obj->efile.maps_shndx);
+						 obj->efile.maps_shndx,
+						 obj->maps);
 		if (err)
 			return err;
 	}

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] tools lib bpf: Define prog_type fns with macro
  2017-01-23  1:11 ` [PATCHv2 perf/core 2/7] tools lib bpf: Define prog_type fns with macro Joe Stringer
@ 2017-01-26 15:30   ` tip-bot for Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Joe Stringer @ 2017-01-26 15:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, linux-kernel, mingo, hpa, tglx, joe, daniel, wangnan0, ast

Commit-ID:  ed7940731ac89616b8a516c560a76dca44a152a8
Gitweb:     http://git.kernel.org/tip/ed7940731ac89616b8a516c560a76dca44a152a8
Author:     Joe Stringer <joe@ovn.org>
AuthorDate: Sun, 22 Jan 2017 17:11:23 -0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Jan 2017 11:42:57 -0300

tools lib bpf: Define prog_type fns with macro

Turning this into a macro allows future prog types to be added with a
single line per type.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: netdev@vger.kernel.org
Link: http://lkml.kernel.org/r/20170123011128.26534-3-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c | 41 ++++++++++++++++-------------------------
 1 file changed, 16 insertions(+), 25 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 671d5ad..371cb40 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1428,37 +1428,28 @@ static void bpf_program__set_type(struct bpf_program *prog,
 	prog->type = type;
 }
 
-int bpf_program__set_tracepoint(struct bpf_program *prog)
-{
-	if (!prog)
-		return -EINVAL;
-	bpf_program__set_type(prog, BPF_PROG_TYPE_TRACEPOINT);
-	return 0;
-}
-
-int bpf_program__set_kprobe(struct bpf_program *prog)
-{
-	if (!prog)
-		return -EINVAL;
-	bpf_program__set_type(prog, BPF_PROG_TYPE_KPROBE);
-	return 0;
-}
-
 static bool bpf_program__is_type(struct bpf_program *prog,
 				 enum bpf_prog_type type)
 {
 	return prog ? (prog->type == type) : false;
 }
 
-bool bpf_program__is_tracepoint(struct bpf_program *prog)
-{
-	return bpf_program__is_type(prog, BPF_PROG_TYPE_TRACEPOINT);
-}
-
-bool bpf_program__is_kprobe(struct bpf_program *prog)
-{
-	return bpf_program__is_type(prog, BPF_PROG_TYPE_KPROBE);
-}
+#define BPF_PROG_TYPE_FNS(NAME, TYPE)			\
+int bpf_program__set_##NAME(struct bpf_program *prog)	\
+{							\
+	if (!prog)					\
+		return -EINVAL;				\
+	bpf_program__set_type(prog, TYPE);		\
+	return 0;					\
+}							\
+							\
+bool bpf_program__is_##NAME(struct bpf_program *prog)	\
+{							\
+	return bpf_program__is_type(prog, TYPE);	\
+}							\
+
+BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
+BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
 
 int bpf_map__fd(struct bpf_map *map)
 {

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] tools lib bpf: Add set/is helpers for all prog types
  2017-01-23  1:11 ` [PATCHv2 perf/core 3/7] tools lib bpf: Add set/is helpers for all prog types Joe Stringer
@ 2017-01-26 15:30   ` tip-bot for Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Joe Stringer @ 2017-01-26 15:30 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: acme, ast, linux-kernel, joe, mingo, tglx, wangnan0, daniel, hpa

Commit-ID:  7803ba73099867d1f6ca866857277d92e0da4080
Gitweb:     http://git.kernel.org/tip/7803ba73099867d1f6ca866857277d92e0da4080
Author:     Joe Stringer <joe@ovn.org>
AuthorDate: Sun, 22 Jan 2017 17:11:24 -0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Jan 2017 11:42:58 -0300

tools lib bpf: Add set/is helpers for all prog types

These bpf_prog_types were exposed in the uapi but there were no
corresponding functions to set these types for programs in libbpf.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: netdev@vger.kernel.org
Link: http://lkml.kernel.org/r/20170123011128.26534-4-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c |  5 +++++
 tools/lib/bpf/libbpf.h | 10 ++++++++++
 2 files changed, 15 insertions(+)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 371cb40..406838f 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -1448,8 +1448,13 @@ bool bpf_program__is_##NAME(struct bpf_program *prog)	\
 	return bpf_program__is_type(prog, TYPE);	\
 }							\
 
+BPF_PROG_TYPE_FNS(socket_filter, BPF_PROG_TYPE_SOCKET_FILTER);
 BPF_PROG_TYPE_FNS(kprobe, BPF_PROG_TYPE_KPROBE);
+BPF_PROG_TYPE_FNS(sched_cls, BPF_PROG_TYPE_SCHED_CLS);
+BPF_PROG_TYPE_FNS(sched_act, BPF_PROG_TYPE_SCHED_ACT);
 BPF_PROG_TYPE_FNS(tracepoint, BPF_PROG_TYPE_TRACEPOINT);
+BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP);
+BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT);
 
 int bpf_map__fd(struct bpf_map *map)
 {
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index a5a8b86..2188ccd 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -174,11 +174,21 @@ int bpf_program__nth_fd(struct bpf_program *prog, int n);
 /*
  * Adjust type of bpf program. Default is kprobe.
  */
+int bpf_program__set_socket_filter(struct bpf_program *prog);
 int bpf_program__set_tracepoint(struct bpf_program *prog);
 int bpf_program__set_kprobe(struct bpf_program *prog);
+int bpf_program__set_sched_cls(struct bpf_program *prog);
+int bpf_program__set_sched_act(struct bpf_program *prog);
+int bpf_program__set_xdp(struct bpf_program *prog);
+int bpf_program__set_perf_event(struct bpf_program *prog);
 
+bool bpf_program__is_socket_filter(struct bpf_program *prog);
 bool bpf_program__is_tracepoint(struct bpf_program *prog);
 bool bpf_program__is_kprobe(struct bpf_program *prog);
+bool bpf_program__is_sched_cls(struct bpf_program *prog);
+bool bpf_program__is_sched_act(struct bpf_program *prog);
+bool bpf_program__is_xdp(struct bpf_program *prog);
+bool bpf_program__is_perf_event(struct bpf_program *prog);
 
 /*
  * We don't need __attribute__((packed)) now since it is

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* [tip:perf/core] tools lib bpf: Add libbpf_get_error()
  2017-01-23  1:11 ` [PATCHv2 perf/core 4/7] tools lib bpf: Add libbpf_get_error() Joe Stringer
@ 2017-01-26 15:31   ` tip-bot for Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: tip-bot for Joe Stringer @ 2017-01-26 15:31 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: ast, hpa, tglx, mingo, acme, wangnan0, joe, linux-kernel, daniel

Commit-ID:  e28ff1a8382ee02b10cf11cf3b48541dc3d14a58
Gitweb:     http://git.kernel.org/tip/e28ff1a8382ee02b10cf11cf3b48541dc3d14a58
Author:     Joe Stringer <joe@ovn.org>
AuthorDate: Sun, 22 Jan 2017 17:11:25 -0800
Committer:  Arnaldo Carvalho de Melo <acme@redhat.com>
CommitDate: Thu, 26 Jan 2017 11:42:58 -0300

tools lib bpf: Add libbpf_get_error()

This function will turn a libbpf pointer into a standard error code (or
0 if the pointer is valid).

This also allows removal of the dependency on linux/err.h in the public
header file, which causes problems in userspace programs built against
libbpf.

Signed-off-by: Joe Stringer <joe@ovn.org>
Acked-by: Wang Nan <wangnan0@huawei.com>
Cc: Alexei Starovoitov <ast@fb.com>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: netdev@vger.kernel.org
Link: http://lkml.kernel.org/r/20170123011128.26534-5-joe@ovn.org
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
---
 tools/lib/bpf/libbpf.c  | 8 ++++++++
 tools/lib/bpf/libbpf.h  | 4 +++-
 tools/perf/tests/llvm.c | 2 +-
 3 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 406838f..e6cd62b 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -28,6 +28,7 @@
 #include <fcntl.h>
 #include <errno.h>
 #include <asm/unistd.h>
+#include <linux/err.h>
 #include <linux/kernel.h>
 #include <linux/bpf.h>
 #include <linux/list.h>
@@ -1542,3 +1543,10 @@ bpf_object__find_map_by_offset(struct bpf_object *obj, size_t offset)
 	}
 	return ERR_PTR(-ENOENT);
 }
+
+long libbpf_get_error(const void *ptr)
+{
+	if (IS_ERR(ptr))
+		return PTR_ERR(ptr);
+	return 0;
+}
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 2188ccd..4014d1b 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -22,8 +22,8 @@
 #define __BPF_LIBBPF_H
 
 #include <stdio.h>
+#include <stdint.h>
 #include <stdbool.h>
-#include <linux/err.h>
 #include <sys/types.h>  // for size_t
 
 enum libbpf_errno {
@@ -234,4 +234,6 @@ int bpf_map__set_priv(struct bpf_map *map, void *priv,
 		      bpf_map_clear_priv_t clear_priv);
 void *bpf_map__priv(struct bpf_map *map);
 
+long libbpf_get_error(const void *ptr);
+
 #endif
diff --git a/tools/perf/tests/llvm.c b/tools/perf/tests/llvm.c
index 02a33eb..d357dab 100644
--- a/tools/perf/tests/llvm.c
+++ b/tools/perf/tests/llvm.c
@@ -13,7 +13,7 @@ static int test__bpf_parsing(void *obj_buf, size_t obj_buf_sz)
 	struct bpf_object *obj;
 
 	obj = bpf_object__open_buffer(obj_buf, obj_buf_sz, NULL);
-	if (IS_ERR(obj))
+	if (libbpf_get_error(obj))
 		return TEST_FAIL;
 	bpf_object__close(obj);
 	return TEST_OK;

^ permalink raw reply related	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-25  2:18         ` Wangnan (F)
@ 2017-01-26 19:32           ` Arnaldo Carvalho de Melo
  2017-01-26 19:43             ` Joe Stringer
  0 siblings, 1 reply; 20+ messages in thread
From: Arnaldo Carvalho de Melo @ 2017-01-26 19:32 UTC (permalink / raw)
  To: Joe Stringer, ast; +Cc: Wangnan (F), Daniel Borkmann, LKML, netdev

Em Wed, Jan 25, 2017 at 10:18:22AM +0800, Wangnan (F) escreveu:
> On 2017/1/25 9:16, Joe Stringer wrote:
> > On 24 January 2017 at 17:06, Wangnan (F) <wangnan0@huawei.com> wrote:
> > > On 2017/1/25 9:04, Wangnan (F) wrote:
> > > Is it possible to use directory tree instead?

> > > %s/object/mapname
> > > %s/object/prog/instance
> > I don't think objects have names, so let's assume an object with two
> > program instances named foo, and one map named bar.

> > A call of bpf_object__pin(obj, "/sys/fs/bpf/myobj") would mount with
> > the following files and directories:
> > /sys/fs/bpf/myobj/foo/1
> > /sys/fs/bpf/myobj/foo/2
> > /sys/fs/bpf/myobj/bar

> > Alternatively, if you want to control exactly where you want the
> > progs/maps to be pinned, you can call eg
> > bpf_program__pin_instance(prog, "/sys/fs/bpf/wherever", 0) and that
> > instance will be mounted to /sys/fs/bpf/wherever, or alternatively
> > bpf_program__pin(prog, "/sys/fs/bpf/foo"), and you will end up with
> > /sys/fs/bpf/foo/{0,1}.

> > This looks pretty reasonable to me.

> It looks good to me.

Ok, please continue from perf/core, Ingo merged the first patch of this
patchset today,

- Arnaldo

^ permalink raw reply	[flat|nested] 20+ messages in thread

* Re: [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin()
  2017-01-26 19:32           ` Arnaldo Carvalho de Melo
@ 2017-01-26 19:43             ` Joe Stringer
  0 siblings, 0 replies; 20+ messages in thread
From: Joe Stringer @ 2017-01-26 19:43 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo; +Cc: ast, Wangnan (F), Daniel Borkmann, LKML, netdev

On 26 January 2017 at 11:32, Arnaldo Carvalho de Melo <acme@kernel.org> wrote:
> Em Wed, Jan 25, 2017 at 10:18:22AM +0800, Wangnan (F) escreveu:
>> On 2017/1/25 9:16, Joe Stringer wrote:
>> > On 24 January 2017 at 17:06, Wangnan (F) <wangnan0@huawei.com> wrote:
>> > > On 2017/1/25 9:04, Wangnan (F) wrote:
>> > > Is it possible to use directory tree instead?
>
>> > > %s/object/mapname
>> > > %s/object/prog/instance
>> > I don't think objects have names, so let's assume an object with two
>> > program instances named foo, and one map named bar.
>
>> > A call of bpf_object__pin(obj, "/sys/fs/bpf/myobj") would mount with
>> > the following files and directories:
>> > /sys/fs/bpf/myobj/foo/1
>> > /sys/fs/bpf/myobj/foo/2
>> > /sys/fs/bpf/myobj/bar
>
>> > Alternatively, if you want to control exactly where you want the
>> > progs/maps to be pinned, you can call eg
>> > bpf_program__pin_instance(prog, "/sys/fs/bpf/wherever", 0) and that
>> > instance will be mounted to /sys/fs/bpf/wherever, or alternatively
>> > bpf_program__pin(prog, "/sys/fs/bpf/foo"), and you will end up with
>> > /sys/fs/bpf/foo/{0,1}.
>
>> > This looks pretty reasonable to me.
>
>> It looks good to me.
>
> Ok, please continue from perf/core, Ingo merged the first patch of this
> patchset today,

Ok thanks, I'll continue from there.

^ permalink raw reply	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2017-01-26 19:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-01-23  1:11 [PATCHv2 perf/core 0/7] Libbpf improvements Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 1/7] tools lib bpf: Fix map offsets in relocation Joe Stringer
2017-01-26 15:29   ` [tip:perf/core] " tip-bot for Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 2/7] tools lib bpf: Define prog_type fns with macro Joe Stringer
2017-01-26 15:30   ` [tip:perf/core] " tip-bot for Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 3/7] tools lib bpf: Add set/is helpers for all prog types Joe Stringer
2017-01-26 15:30   ` [tip:perf/core] " tip-bot for Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 4/7] tools lib bpf: Add libbpf_get_error() Joe Stringer
2017-01-26 15:31   ` [tip:perf/core] " tip-bot for Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 5/7] tools lib bpf: Add bpf_program__pin() Joe Stringer
2017-01-25  1:04   ` Wangnan (F)
2017-01-25  1:06     ` Wangnan (F)
2017-01-25  1:16       ` Joe Stringer
2017-01-25  2:18         ` Wangnan (F)
2017-01-26 19:32           ` Arnaldo Carvalho de Melo
2017-01-26 19:43             ` Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 6/7] tools lib bpf: Add bpf_map__pin() Joe Stringer
2017-01-23  1:11 ` [PATCHv2 perf/core 7/7] tools lib bpf: Add bpf_object__pin() Joe Stringer
2017-01-24 16:12 ` [PATCHv2 perf/core 0/7] Libbpf improvements Arnaldo Carvalho de Melo
2017-01-25  0:50   ` Joe Stringer

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.