lkml.org 
[lkml]   [2021]   [Sep]   [9]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH AUTOSEL 5.10 005/176] libbpf: Fix reuse of pinned map on older kernel
    Date
    From: Martynas Pumputis <m@lambda.lt>

    [ Upstream commit 97eb31384af943d6b97eb5947262cee4ef25cb87 ]

    When loading a BPF program with a pinned map, the loader checks whether
    the pinned map can be reused, i.e. their properties match. To derive
    such of the pinned map, the loader invokes BPF_OBJ_GET_INFO_BY_FD and
    then does the comparison.

    Unfortunately, on < 4.12 kernels the BPF_OBJ_GET_INFO_BY_FD is not
    available, so loading the program fails with the following error:

    libbpf: failed to get map info for map FD 5: Invalid argument
    libbpf: couldn't reuse pinned map at
    '/sys/fs/bpf/tc/globals/cilium_call_policy': parameter
    mismatch"
    libbpf: map 'cilium_call_policy': error reusing pinned map
    libbpf: map 'cilium_call_policy': failed to create:
    Invalid argument(-22)
    libbpf: failed to load object 'bpf_overlay.o'

    To fix this, fallback to derivation of the map properties via
    /proc/$PID/fdinfo/$MAP_FD if BPF_OBJ_GET_INFO_BY_FD fails with EINVAL,
    which can be used as an indicator that the kernel doesn't support
    the latter.

    Signed-off-by: Martynas Pumputis <m@lambda.lt>
    Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
    Acked-by: John Fastabend <john.fastabend@gmail.com>
    Link: https://lore.kernel.org/bpf/20210712125552.58705-1-m@lambda.lt
    Signed-off-by: Sasha Levin <sashal@kernel.org>
    ---
    tools/lib/bpf/libbpf.c | 48 +++++++++++++++++++++++++++++++++++++++---
    1 file changed, 45 insertions(+), 3 deletions(-)

    diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
    index 95eef7ebdac5..a4e61dd5d8b3 100644
    --- a/tools/lib/bpf/libbpf.c
    +++ b/tools/lib/bpf/libbpf.c
    @@ -3613,6 +3613,42 @@ static int bpf_map_find_btf_info(struct bpf_object *obj, struct bpf_map *map)
    return 0;
    }

    +static int bpf_get_map_info_from_fdinfo(int fd, struct bpf_map_info *info)
    +{
    + char file[PATH_MAX], buff[4096];
    + FILE *fp;
    + __u32 val;
    + int err;
    +
    + snprintf(file, sizeof(file), "/proc/%d/fdinfo/%d", getpid(), fd);
    + memset(info, 0, sizeof(*info));
    +
    + fp = fopen(file, "r");
    + if (!fp) {
    + err = -errno;
    + pr_warn("failed to open %s: %d. No procfs support?\n", file,
    + err);
    + return err;
    + }
    +
    + while (fgets(buff, sizeof(buff), fp)) {
    + if (sscanf(buff, "map_type:\t%u", &val) == 1)
    + info->type = val;
    + else if (sscanf(buff, "key_size:\t%u", &val) == 1)
    + info->key_size = val;
    + else if (sscanf(buff, "value_size:\t%u", &val) == 1)
    + info->value_size = val;
    + else if (sscanf(buff, "max_entries:\t%u", &val) == 1)
    + info->max_entries = val;
    + else if (sscanf(buff, "map_flags:\t%i", &val) == 1)
    + info->map_flags = val;
    + }
    +
    + fclose(fp);
    +
    + return 0;
    +}
    +
    int bpf_map__reuse_fd(struct bpf_map *map, int fd)
    {
    struct bpf_map_info info = {};
    @@ -3621,6 +3657,8 @@ int bpf_map__reuse_fd(struct bpf_map *map, int fd)
    char *new_name;

    err = bpf_obj_get_info_by_fd(fd, &info, &len);
    + if (err && errno == EINVAL)
    + err = bpf_get_map_info_from_fdinfo(fd, &info);
    if (err)
    return err;

    @@ -4032,12 +4070,16 @@ static bool map_is_reuse_compat(const struct bpf_map *map, int map_fd)
    struct bpf_map_info map_info = {};
    char msg[STRERR_BUFSIZE];
    __u32 map_info_len;
    + int err;

    map_info_len = sizeof(map_info);

    - if (bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len)) {
    - pr_warn("failed to get map info for map FD %d: %s\n",
    - map_fd, libbpf_strerror_r(errno, msg, sizeof(msg)));
    + err = bpf_obj_get_info_by_fd(map_fd, &map_info, &map_info_len);
    + if (err && errno == EINVAL)
    + err = bpf_get_map_info_from_fdinfo(map_fd, &map_info);
    + if (err) {
    + pr_warn("failed to get map info for map FD %d: %s\n", map_fd,
    + libbpf_strerror_r(errno, msg, sizeof(msg)));
    return false;
    }

    --
    2.30.2
    \
     
     \ /
      Last update: 2021-09-09 14:37    [W:2.460 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site