mirror of
https://github.com/netdata/libbpf.git
synced 2026-04-04 23:59:07 +08:00
libbpf: Fix BPF_MAP_TYPE_PERF_EVENT_ARRAY auto-pinning
When a BPF map of type BPF_MAP_TYPE_PERF_EVENT_ARRAY doesn't have the
max_entries parameter set, the map will be created with max_entries set
to the number of available CPUs. When we try to reuse such a pinned map,
map_is_reuse_compat will return false, as max_entries in the map
definition differs from max_entries of the existing map, causing the
following error:
libbpf: couldn't reuse pinned map at '/sys/fs/bpf/m_logging': parameter mismatch
Fix this by overwriting max_entries in the map definition. For this to
work, we need to do this in bpf_object__create_maps, before calling
bpf_object__reuse_map.
Fixes: 57a00f41644f ("libbpf: Add auto-pinning of maps when loading BPF objects")
Signed-off-by: Stijn Tintel <stijn@linux-ipv6.be>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Song Liu <songliubraving@fb.com>
Link: https://lore.kernel.org/bpf/20220225152355.315204-1-stijn@linux-ipv6.be
This commit is contained in:
committed by
Andrii Nakryiko
parent
426672106e
commit
9b53decb02
44
src/libbpf.c
44
src/libbpf.c
@@ -4859,7 +4859,6 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
|||||||
LIBBPF_OPTS(bpf_map_create_opts, create_attr);
|
LIBBPF_OPTS(bpf_map_create_opts, create_attr);
|
||||||
struct bpf_map_def *def = &map->def;
|
struct bpf_map_def *def = &map->def;
|
||||||
const char *map_name = NULL;
|
const char *map_name = NULL;
|
||||||
__u32 max_entries;
|
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
||||||
if (kernel_supports(obj, FEAT_PROG_NAME))
|
if (kernel_supports(obj, FEAT_PROG_NAME))
|
||||||
@@ -4869,21 +4868,6 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
|||||||
create_attr.numa_node = map->numa_node;
|
create_attr.numa_node = map->numa_node;
|
||||||
create_attr.map_extra = map->map_extra;
|
create_attr.map_extra = map->map_extra;
|
||||||
|
|
||||||
if (def->type == BPF_MAP_TYPE_PERF_EVENT_ARRAY && !def->max_entries) {
|
|
||||||
int nr_cpus;
|
|
||||||
|
|
||||||
nr_cpus = libbpf_num_possible_cpus();
|
|
||||||
if (nr_cpus < 0) {
|
|
||||||
pr_warn("map '%s': failed to determine number of system CPUs: %d\n",
|
|
||||||
map->name, nr_cpus);
|
|
||||||
return nr_cpus;
|
|
||||||
}
|
|
||||||
pr_debug("map '%s': setting size to %d\n", map->name, nr_cpus);
|
|
||||||
max_entries = nr_cpus;
|
|
||||||
} else {
|
|
||||||
max_entries = def->max_entries;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bpf_map__is_struct_ops(map))
|
if (bpf_map__is_struct_ops(map))
|
||||||
create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
|
create_attr.btf_vmlinux_value_type_id = map->btf_vmlinux_value_type_id;
|
||||||
|
|
||||||
@@ -4933,7 +4917,7 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
|||||||
|
|
||||||
if (obj->gen_loader) {
|
if (obj->gen_loader) {
|
||||||
bpf_gen__map_create(obj->gen_loader, def->type, map_name,
|
bpf_gen__map_create(obj->gen_loader, def->type, map_name,
|
||||||
def->key_size, def->value_size, max_entries,
|
def->key_size, def->value_size, def->max_entries,
|
||||||
&create_attr, is_inner ? -1 : map - obj->maps);
|
&create_attr, is_inner ? -1 : map - obj->maps);
|
||||||
/* Pretend to have valid FD to pass various fd >= 0 checks.
|
/* Pretend to have valid FD to pass various fd >= 0 checks.
|
||||||
* This fd == 0 will not be used with any syscall and will be reset to -1 eventually.
|
* This fd == 0 will not be used with any syscall and will be reset to -1 eventually.
|
||||||
@@ -4942,7 +4926,7 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
|||||||
} else {
|
} else {
|
||||||
map->fd = bpf_map_create(def->type, map_name,
|
map->fd = bpf_map_create(def->type, map_name,
|
||||||
def->key_size, def->value_size,
|
def->key_size, def->value_size,
|
||||||
max_entries, &create_attr);
|
def->max_entries, &create_attr);
|
||||||
}
|
}
|
||||||
if (map->fd < 0 && (create_attr.btf_key_type_id ||
|
if (map->fd < 0 && (create_attr.btf_key_type_id ||
|
||||||
create_attr.btf_value_type_id)) {
|
create_attr.btf_value_type_id)) {
|
||||||
@@ -4959,7 +4943,7 @@ static int bpf_object__create_map(struct bpf_object *obj, struct bpf_map *map, b
|
|||||||
map->btf_value_type_id = 0;
|
map->btf_value_type_id = 0;
|
||||||
map->fd = bpf_map_create(def->type, map_name,
|
map->fd = bpf_map_create(def->type, map_name,
|
||||||
def->key_size, def->value_size,
|
def->key_size, def->value_size,
|
||||||
max_entries, &create_attr);
|
def->max_entries, &create_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
err = map->fd < 0 ? -errno : 0;
|
err = map->fd < 0 ? -errno : 0;
|
||||||
@@ -5063,6 +5047,24 @@ static int bpf_object_init_prog_arrays(struct bpf_object *obj)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int map_set_def_max_entries(struct bpf_map *map)
|
||||||
|
{
|
||||||
|
if (map->def.type == BPF_MAP_TYPE_PERF_EVENT_ARRAY && !map->def.max_entries) {
|
||||||
|
int nr_cpus;
|
||||||
|
|
||||||
|
nr_cpus = libbpf_num_possible_cpus();
|
||||||
|
if (nr_cpus < 0) {
|
||||||
|
pr_warn("map '%s': failed to determine number of system CPUs: %d\n",
|
||||||
|
map->name, nr_cpus);
|
||||||
|
return nr_cpus;
|
||||||
|
}
|
||||||
|
pr_debug("map '%s': setting size to %d\n", map->name, nr_cpus);
|
||||||
|
map->def.max_entries = nr_cpus;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
bpf_object__create_maps(struct bpf_object *obj)
|
bpf_object__create_maps(struct bpf_object *obj)
|
||||||
{
|
{
|
||||||
@@ -5095,6 +5097,10 @@ bpf_object__create_maps(struct bpf_object *obj)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = map_set_def_max_entries(map);
|
||||||
|
if (err)
|
||||||
|
goto err_out;
|
||||||
|
|
||||||
retried = false;
|
retried = false;
|
||||||
retry:
|
retry:
|
||||||
if (map->pin_path) {
|
if (map->pin_path) {
|
||||||
|
|||||||
Reference in New Issue
Block a user