mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-29 03:01:39 -04:00
libbpf: Extract and generalize CPU mask parsing logic
commit 6803ee25f0ead1e836808acb14396bb9a9849113 upstream. This logic is re-used for parsing a set of online CPUs. Having it as an isolated piece of code working with input string makes it conveninent to test this logic as well. While refactoring, also improve the robustness of original implementation. Signed-off-by: Andrii Nakryiko <[email protected]> Signed-off-by: Alexei Starovoitov <[email protected]> Link: https://lore.kernel.org/bpf/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
This commit is contained in:
parent
10cfaa7456
commit
35d9107ad3
2 changed files with 86 additions and 42 deletions
|
|
@ -5905,62 +5905,104 @@ void bpf_program__bpil_offs_to_addr(struct bpf_prog_info_linear *info_linear)
|
|||
}
|
||||
}
|
||||
|
||||
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz)
|
||||
{
|
||||
int err = 0, n, len, start, end = -1;
|
||||
bool *tmp;
|
||||
|
||||
*mask = NULL;
|
||||
*mask_sz = 0;
|
||||
|
||||
/* Each sub string separated by ',' has format \d+-\d+ or \d+ */
|
||||
while (*s) {
|
||||
if (*s == ',' || *s == '\n') {
|
||||
s++;
|
||||
continue;
|
||||
}
|
||||
n = sscanf(s, "%d%n-%d%n", &start, &len, &end, &len);
|
||||
if (n <= 0 || n > 2) {
|
||||
pr_warning("Failed to get CPU range %s: %d\n", s, n);
|
||||
err = -EINVAL;
|
||||
goto cleanup;
|
||||
} else if (n == 1) {
|
||||
end = start;
|
||||
}
|
||||
if (start < 0 || start > end) {
|
||||
pr_warning("Invalid CPU range [%d,%d] in %s\n",
|
||||
start, end, s);
|
||||
err = -EINVAL;
|
||||
goto cleanup;
|
||||
}
|
||||
tmp = realloc(*mask, end + 1);
|
||||
if (!tmp) {
|
||||
err = -ENOMEM;
|
||||
goto cleanup;
|
||||
}
|
||||
*mask = tmp;
|
||||
memset(tmp + *mask_sz, 0, start - *mask_sz);
|
||||
memset(tmp + start, 1, end - start + 1);
|
||||
*mask_sz = end + 1;
|
||||
s += len;
|
||||
}
|
||||
if (!*mask_sz) {
|
||||
pr_warning("Empty CPU range\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
cleanup:
|
||||
free(*mask);
|
||||
*mask = NULL;
|
||||
return err;
|
||||
}
|
||||
|
||||
int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz)
|
||||
{
|
||||
int fd, err = 0, len;
|
||||
char buf[128];
|
||||
|
||||
fd = open(fcpu, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
err = -errno;
|
||||
pr_warning("Failed to open cpu mask file %s: %d\n", fcpu, err);
|
||||
return err;
|
||||
}
|
||||
len = read(fd, buf, sizeof(buf));
|
||||
close(fd);
|
||||
if (len <= 0) {
|
||||
err = len ? -errno : -EINVAL;
|
||||
pr_warning("Failed to read cpu mask from %s: %d\n", fcpu, err);
|
||||
return err;
|
||||
}
|
||||
if (len >= sizeof(buf)) {
|
||||
pr_warning("CPU mask is too big in file %s\n", fcpu);
|
||||
return -E2BIG;
|
||||
}
|
||||
buf[len] = '\0';
|
||||
|
||||
return parse_cpu_mask_str(buf, mask, mask_sz);
|
||||
}
|
||||
|
||||
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;
|
||||
int tmp_cpus = 0;
|
||||
static int cpus;
|
||||
char buf[128];
|
||||
int error = 0;
|
||||
int fd = -1;
|
||||
int err, n, i, tmp_cpus;
|
||||
bool *mask;
|
||||
|
||||
tmp_cpus = READ_ONCE(cpus);
|
||||
if (tmp_cpus > 0)
|
||||
return tmp_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 = len ? errno : EINVAL;
|
||||
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';
|
||||
err = parse_cpu_mask_file(fcpu, &mask, &n);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (ir = 0, tmp_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;
|
||||
}
|
||||
tmp_cpus += end - start + 1;
|
||||
il = ir + 1;
|
||||
}
|
||||
}
|
||||
if (tmp_cpus <= 0) {
|
||||
pr_warning("Invalid #CPUs %d from %s\n", tmp_cpus, fcpu);
|
||||
return -EINVAL;
|
||||
tmp_cpus = 0;
|
||||
for (i = 0; i < n; i++) {
|
||||
if (mask[i])
|
||||
tmp_cpus++;
|
||||
}
|
||||
free(mask);
|
||||
|
||||
WRITE_ONCE(cpus, tmp_cpus);
|
||||
return tmp_cpus;
|
||||
|
|
|
|||
|
|
@ -63,6 +63,8 @@ do { \
|
|||
#define pr_info(fmt, ...) __pr(LIBBPF_INFO, fmt, ##__VA_ARGS__)
|
||||
#define pr_debug(fmt, ...) __pr(LIBBPF_DEBUG, fmt, ##__VA_ARGS__)
|
||||
|
||||
int parse_cpu_mask_str(const char *s, bool **mask, int *mask_sz);
|
||||
int parse_cpu_mask_file(const char *fcpu, bool **mask, int *mask_sz);
|
||||
int libbpf__load_raw_btf(const char *raw_types, size_t types_len,
|
||||
const char *str_sec, size_t str_len);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue