On Tue, Oct 22, 2019 at 9:08 AM Toke Høiland-Jørgensen <toke@xxxxxxxxxx> wrote: > > From: Toke Høiland-Jørgensen <toke@xxxxxxxxxx> > > While the current map pinning functions will check whether the pin path is > contained on a BPF filesystem, it does not offer any options to mount the > file system if it doesn't exist. Since we now have pinning options, add a > new one to automount a BPF filesystem at the pinning path if that is not Next thing we'll be adding extra options to mount BPF FS... Can we leave the task of auto-mounting BPF FS to tools/applications? > already pointing at a bpffs. > > The mounting logic itself is copied from the iproute2 BPF helper functions. > > Signed-off-by: Toke Høiland-Jørgensen <toke@xxxxxxxxxx> > --- > tools/lib/bpf/libbpf.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 5 ++++- > 2 files changed, 51 insertions(+), 1 deletion(-) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index aea3916de341..f527224bb211 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -37,6 +37,7 @@ > #include <sys/epoll.h> > #include <sys/ioctl.h> > #include <sys/mman.h> > +#include <sys/mount.h> > #include <sys/stat.h> > #include <sys/types.h> > #include <sys/vfs.h> > @@ -4072,6 +4073,35 @@ int bpf_map__unpin(struct bpf_map *map, const char *path) > return 0; > } > > +static int mount_bpf_fs(const char *target) > +{ > + bool bind_done = false; > + > + while (mount("", target, "none", MS_PRIVATE | MS_REC, NULL)) { what does this loop do? we need some comments explaining what's going on here (or better yet just drop this entirely and let bpftool/iproute2 do the mounting). > + if (errno != EINVAL || bind_done) { > + pr_warning("mount --make-private %s failed: %s\n", > + target, strerror(errno)); > + return -1; > + } > + > + if (mount(target, target, "none", MS_BIND, NULL)) { > + pr_warning("mount --bind %s %s failed: %s\n", > + target, target, strerror(errno)); > + return -1; > + } > + > + bind_done = true; > + } > + > + if (mount("bpf", target, "bpf", 0, "mode=0700")) { > + fprintf(stderr, "mount -t bpf bpf %s failed: %s\n", > + target, strerror(errno)); > + return -1; > + } > + > + return 0; > +} > + > static int get_pin_path(char *buf, size_t buf_len, > struct bpf_map *map, struct bpf_object_pin_opts *opts, > bool mkdir) > @@ -4102,6 +4132,23 @@ static int get_pin_path(char *buf, size_t buf_len, Nothing in `get_pin_path` indicates that it's going to do an entire FS mount, please split this out of get_pin_path. > err = make_dir(path); > if (err) > return err; > + > + if (OPTS_GET(opts, mount_bpf_fs, false)) { > + struct statfs st_fs; > + char *cp; > + > + if (statfs(path, &st_fs)) { > + char errmsg[STRERR_BUFSIZE]; > + > + cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg)); > + pr_warning("failed to statfs %s: %s\n", path, cp); > + return -errno; > + } > + if (st_fs.f_type != BPF_FS_MAGIC && > + mount_bpf_fs(path)) { > + return -EINVAL; > + } > + } > } > > len = snprintf(buf, buf_len, "%s/%s", path, bpf_map__name(map)); > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h > index 2131eeafb18d..76b9a6cc7063 100644 > --- a/tools/lib/bpf/libbpf.h > +++ b/tools/lib/bpf/libbpf.h > @@ -143,8 +143,11 @@ struct bpf_object_pin_opts { > * and this type used for all maps instead. > */ > enum libbpf_pin_type override_type; > + > + /* Whether to attempt to mount a BPF FS if it's not already mounted */ > + bool mount_bpf_fs; > }; > -#define bpf_object_pin_opts__last_field override_type > +#define bpf_object_pin_opts__last_field mount_bpf_fs > > LIBBPF_API int bpf_object__pin_maps(struct bpf_object *obj, const char *path); > LIBBPF_API int bpf_object__unpin_maps(struct bpf_object *obj, >