For BPF_MAP_TYPE_PERF_EVENT_ARRAY typically correct size is number of
possible CPUs. This is impossible to specify at compilation time. This
change adds automatic setting of PERF_EVENT_ARRAY size to number of
system CPUs, unless non-zero size is specified explicitly. This allows
to adjust size for advanced specific cases, while providing convenient
and logical defaults.

Signed-off-by: Andrii Nakryiko <andr...@fb.com>
---
 tools/lib/bpf/libbpf.c | 31 ++++++++++++++++++++++++-------
 1 file changed, 24 insertions(+), 7 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index e2bf3eedd0ae..a5ae7207d19a 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -2118,6 +2118,7 @@ static int
 bpf_object__create_maps(struct bpf_object *obj)
 {
        struct bpf_create_map_attr create_attr = {};
+       int nr_cpus = 0;
        unsigned int i;
        int err;
 
@@ -2140,7 +2141,22 @@ bpf_object__create_maps(struct bpf_object *obj)
                create_attr.map_flags = def->map_flags;
                create_attr.key_size = def->key_size;
                create_attr.value_size = def->value_size;
-               create_attr.max_entries = def->max_entries;
+               if (def->type == BPF_MAP_TYPE_PERF_EVENT_ARRAY &&
+                   !def->max_entries) {
+                       if (!nr_cpus)
+                               nr_cpus = libbpf_num_possible_cpus();
+                       if (nr_cpus < 0) {
+                               pr_warning("failed to determine number of 
system CPUs: %d\n",
+                                          nr_cpus);
+                               err = nr_cpus;
+                               goto err_out;
+                       }
+                       pr_debug("map '%s': setting size to %d\n",
+                                map->name, nr_cpus);
+                       create_attr.max_entries = nr_cpus;
+               } else {
+                       create_attr.max_entries = def->max_entries;
+               }
                create_attr.btf_fd = 0;
                create_attr.btf_key_type_id = 0;
                create_attr.btf_value_type_id = 0;
@@ -2157,9 +2173,10 @@ bpf_object__create_maps(struct bpf_object *obj)
                *pfd = bpf_create_map_xattr(&create_attr);
                if (*pfd < 0 && (create_attr.btf_key_type_id ||
                                 create_attr.btf_value_type_id)) {
-                       cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
+                       err = -errno;
+                       cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg));
                        pr_warning("Error in bpf_create_map_xattr(%s):%s(%d). 
Retrying without BTF.\n",
-                                  map->name, cp, errno);
+                                  map->name, cp, err);
                        create_attr.btf_fd = 0;
                        create_attr.btf_key_type_id = 0;
                        create_attr.btf_value_type_id = 0;
@@ -2171,11 +2188,11 @@ bpf_object__create_maps(struct bpf_object *obj)
                if (*pfd < 0) {
                        size_t j;
 
-                       err = *pfd;
+                       err = -errno;
 err_out:
-                       cp = libbpf_strerror_r(errno, errmsg, sizeof(errmsg));
-                       pr_warning("failed to create map (name: '%s'): %s\n",
-                                  map->name, cp);
+                       cp = libbpf_strerror_r(err, errmsg, sizeof(errmsg));
+                       pr_warning("failed to create map (name: '%s'): 
%s(%d)\n",
+                                  map->name, cp, err);
                        for (j = 0; j < i; j++)
                                zclose(obj->maps[j].fd);
                        return err;
-- 
2.17.1

Reply via email to