On Thu, Jun 06, 2019 at 09:58:36AM -0700, Hechao Li wrote: > Adding a new API libbpf_num_possible_cpus() that helps user with > per-CPU map operations. > > Signed-off-by: Hechao Li <hechaol@xxxxxx> > --- > tools/lib/bpf/libbpf.c | 53 ++++++++++++++++++++++++++++++++++++++++ > tools/lib/bpf/libbpf.h | 16 ++++++++++++ > tools/lib/bpf/libbpf.map | 1 + > 3 files changed, 70 insertions(+) > > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c > index ba89d9727137..ea80ba6f7dfd 100644 > --- a/tools/lib/bpf/libbpf.c > +++ b/tools/lib/bpf/libbpf.c > @@ -3827,3 +3827,56 @@ void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear) > desc->array_offset, addr); > } > } > + > +int libbpf_num_possible_cpus(void) > +{ > + static const char *fcpu = "/sys/devices/system/cpu/possible"; > + int len = 0, n = 0, il = 0, ir = 0; > + unsigned int start = 0, end = 0; > + static int cpus; > + char buf[128]; > + int error = 0; > + int fd = -1; > + > + if (cpus > 0) > + return cpus; > + > + fd = open(fcpu, O_RDONLY); > + if (fd < 0) { > + error = errno; > + pr_warning("Failed to open file %s: %s\n", > + fcpu, strerror(error)); > + return -error; > + } > + len = read(fd, buf, sizeof(buf)); > + close(fd); > + if (len <= 0) { > + error = errno; What is the errno when len == 0? > + pr_warning("Failed to read # of possible cpus from %s: %s\n", > + fcpu, strerror(error)); > + return -error; > + } > + if (len == sizeof(buf)) { > + pr_warning("File %s size overflow\n", fcpu); > + return -EOVERFLOW; > + } > + buf[len] = '\0'; > + > + for (ir = 0, cpus = 0; ir <= len; ir++) { > + /* Each sub string separated by ',' has format \d+-\d+ or \d+ */ > + if (buf[ir] == ',' || buf[ir] == '\0') { > + buf[ir] = '\0'; > + n = sscanf(&buf[il], "%u-%u", &start, &end); > + if (n <= 0) { > + pr_warning("Failed to get # CPUs from %s\n", > + &buf[il]); > + return -EINVAL; > + } else if (n == 1) { > + end = start; > + } > + cpus += end - start + 1; > + il = ir + 1; > + } > + } > + return cpus; > +} > diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h > index 1af0d48178c8..f5e82eb2e5d4 100644 > --- a/tools/lib/bpf/libbpf.h > +++ b/tools/lib/bpf/libbpf.h > @@ -454,6 +454,22 @@ bpf_program__bpil_addr_to_offs(struct bpf_prog_info_linear *info_linear); > LIBBPF_API void > bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear); > > +/* > + * A helper function to get the number of possible CPUs before looking up > + * per-CPU maps. Negative errno is returned on failure. > + * > + * Example usage: > + * > + * int ncpus = libbpf_num_possible_cpus(); > + * if (ncpus <= 0) { > + * // error handling > + * } > + * long values[ncpus]; > + * bpf_map_lookup_elem(per_cpu_map_fd, key, values); > + * > + */ > +LIBBPF_API int libbpf_num_possible_cpus(void); > + > #ifdef __cplusplus > } /* extern "C" */ > #endif > diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map > index 46dcda89df21..2c6d835620d2 100644 > --- a/tools/lib/bpf/libbpf.map > +++ b/tools/lib/bpf/libbpf.map > @@ -172,4 +172,5 @@ LIBBPF_0.0.4 { > btf_dump__new; > btf__parse_elf; > bpf_object__load_xattr; > + libbpf_num_possible_cpus; > } LIBBPF_0.0.3; > -- > 2.17.1 >