From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751906AbdASKWm (ORCPT ); Thu, 19 Jan 2017 05:22:42 -0500 Received: from szxga02-in.huawei.com ([119.145.14.65]:31520 "EHLO szxga02-in.huawei.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751491AbdASKWk (ORCPT ); Thu, 19 Jan 2017 05:22:40 -0500 Subject: Re: [PATCH perf/core 6/6] tools lib bpf: Add bpf_object__pin() To: Joe Stringer , References: <20170118235724.26103-1-joe@ovn.org> <20170118235724.26103-7-joe@ovn.org> CC: , , From: "Wangnan (F)" Message-ID: <160e796e-8af3-e437-82c2-424169c3f80f@huawei.com> Date: Thu, 19 Jan 2017 18:22:13 +0800 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Thunderbird/45.5.1 MIME-Version: 1.0 In-Reply-To: <20170118235724.26103-7-joe@ovn.org> Content-Type: text/plain; charset="utf-8"; format=flowed Content-Transfer-Encoding: 7bit X-Originating-IP: [10.111.194.139] X-CFilter-Loop: Reflected X-Mirapoint-Virus-RAPID-Raw: score=unknown(0), refid=str=0001.0A020201.5880936B.031D,ss=1,re=0.000,recu=0.000,reip=0.000,cl=1,cld=1,fgs=0, ip=0.0.0.0, so=2013-06-18 04:22:30, dmn=2013-03-21 17:37:32 X-Mirapoint-Loop-Id: 6423a02ea5b5031a599a16bf6612c234 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 2017/1/19 7:57, Joe Stringer wrote: > Add a new API to pin a BPF object to the filesystem. The user can > specify a subdirectory under the BPF filesystem to pin these programs. > > For example, with the subdirectory 'foo', programs and maps are pinned: > /sys/fs/bpf/foo/progs/PROG_NAME > /sys/fs/bpf/foo/maps/MAP_NAME > > If the user has specified an alternative BPF filesystem mountpoint via > /proc/mounts, that will be read and used instead. > > Signed-off-by: Joe Stringer > --- > tools/lib/bpf/libbpf.c | 136 +++++++++++++++++++++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 1 + > 2 files changed, 137 insertions(+) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index 6b651c19870d..181dca0bdacb 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -4,6 +4,7 @@ > * Copyright (C) 2013-2015 Alexei Starovoitov > * Copyright (C) 2015 Wang Nan > * Copyright (C) 2015 Huawei Inc. > + * Copyright (C) 2016 Nicira, Inc. > * > * This program is free software; you can redistribute it and/or > * modify it under the terms of the GNU Lesser General Public > @@ -31,7 +32,12 @@ > #include > #include > #include > +#include > #include > +#include > +#include > +#include > +#include > #include > #include > > @@ -1231,6 +1237,136 @@ int bpf_object__load(struct bpf_object *obj) > return err; > } > > +#define stringize(x) #x > + > +static int mount_bpf(char *path) We can use tools/lib/api/fs/fs.c to help us mounting filesystems. Try not reinventing it. > +{ > + const char *mounts_fmt = "%*s %"stringize(PATH_MAX)"s %#"stringize(NAME_MAX)"s %*s\n"; > + struct statfs st_fs; > + char type[NAME_MAX]; > + int err = 0; > + FILE *fp; > + > + /* Populate 'path'. */ > + fp = fopen("/proc/mounts", "r"); > + if (fp) { > + while (fscanf(fp, mounts_fmt, path, type) == 2) { > + if (!strcmp(type, "bpf")) > + break; > + } > + if (fclose(fp)) { > + err = -errno; > + pr_warning("failed to close /proc/mounts: %s\n", > + strerror(errno)); > + } > + if (strcmp(type, "bpf")) { > + err = -errno; > + pr_debug("failed to find bpf mount\n"); > + } > + } else { > + err = -errno; > + pr_warning("cannot open /proc/mounts: %s\n", strerror(errno)); > + } > + if (err) { > + pr_debug("using /sys/fs/bpf for BPF filesystem mountpoint\n"); > + strcpy(path, "/sys/fs/bpf"); > + } > + > + if (!statfs(path, &st_fs) && st_fs.f_type == BPF_FS_MAGIC) > + return 0; > + > + if (mount("bpf", path, "bpf", 0, NULL)) { > + pr_warning("failed to mount bpf: %s\n", strerror(errno)); > + return -errno; > + } > + > + return 0; > +} > + > +static int make_dirs(const char *path, const char *subdir, char *buf, > + size_t len) > +{ > + snprintf(buf, len, "%s/%s/", path, subdir); > + if (mkdir(buf, 0700) && errno != EEXIST) { > + pr_warning("failed to mkdir %s: %s\n", subdir, strerror(errno)); > + return -errno; > + } > + > + snprintf(buf, len, "%s/%s/maps/", path, subdir); > + if (mkdir(buf, 0700) && errno != EEXIST) { > + pr_warning("failed to mkdir map: %s\n", strerror(errno)); > + return -errno; > + } > + > + snprintf(buf, len, "%s/%s/progs/", path, subdir); > + if (mkdir(buf, 0700) && errno != EEXIST) { > + pr_warning("failed to mkdir prog: %s\n", strerror(errno)); > + return -errno; > + } > + > + return 0; > +} > + > +int bpf_object__pin(struct bpf_object *obj, const char *subdir) > +{ We must pin a whole object? I suggest we provide bpf_program__pin and bpf_map__pin, and build bpf_object__pin on top of them. Thank you. > + const size_t len = 255; > + char path[PATH_MAX]; > + char buf[len]; > + size_t i, j; > + int err = 0; > + > + if (!obj) > + return -ENOENT; > + > + if (!obj->loaded) { > + pr_warning("object not yet loaded; load it first\n"); > + return -ENOENT; > + } > + > + err = mount_bpf(path); > + if (err) > + return err; > + > + err = make_dirs(path, subdir, buf, len); > + if (err) > + return err; > + > + for (i = 0; i < obj->nr_maps; i++) { > + struct bpf_map *map = &obj->maps[i]; > + > + snprintf(buf, len, "%s/%s/maps/%s", path, subdir, > + bpf_map__name(map)); > + if (bpf_obj_pin(map->fd, buf)) { > + err = -errno; > + pr_warning("failed to pin map: %s\n", strerror(errno)); > + goto out; > + } > + pr_debug("Loaded map '%s' at '%s'\n", bpf_map__name(map), buf); > + } > + > + if (obj->programs && obj->nr_programs) { > + for (i = 0; i < obj->nr_programs; i++) { > + struct bpf_program *prog = &obj->programs[i]; > + > + for (j = 0; j < prog->instances.nr; j++) { > + snprintf(buf, len, "%s/%s/progs/%s_%zu", path, > + subdir, prog->section_name, j); > + if (bpf_obj_pin(prog->instances.fds[j], buf)) { > + err = -errno; > + pr_warning("failed to pin prog: %s\n", > + strerror(errno)); > + goto out; > + } > + pr_debug("Loaded prog '%s' at '%s'\n", > + prog->section_name, buf); > + } > + } > + } > + > +out: > + return err; > +} > + > 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..920699a437be 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 *subdir); > void bpf_object__close(struct bpf_object *object); > > /* Load/unload object into/from kernel */