Message ID | 20170123011128.26534-6-joe@ovn.org |
---|---|
State | Not Applicable, archived |
Delegated to: | David Miller |
Headers | show |
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.
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.
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.
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.
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
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.
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;
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(+)