]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
perf pmu: Switch to io_dir__readdir
authorIan Rogers <irogers@google.com>
Sat, 22 Feb 2025 06:10:08 +0000 (22:10 -0800)
committerNamhyung Kim <namhyung@kernel.org>
Mon, 24 Feb 2025 23:46:33 +0000 (15:46 -0800)
Avoid DIR allocations when scanning sysfs by using io_dir for the
readdir implementation, that allocates about 1kb on the stack.

Acked-by: Namhyung Kim <namhyung@kernel.org>
Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250222061015.303622-4-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
tools/perf/util/pmu.c
tools/perf/util/pmus.c

index ec3878c890a9dc1ace093fb25b42a60aa84c5a2f..e51c17b1ea3590ea5c5b3b1ced71490abc851072 100644 (file)
@@ -13,6 +13,7 @@
 #include <dirent.h>
 #include <api/fs/fs.h>
 #include <api/io.h>
+#include <api/io_dir.h>
 #include <locale.h>
 #include <fnmatch.h>
 #include <math.h>
@@ -195,19 +196,17 @@ static void perf_pmu_format__load(const struct perf_pmu *pmu, struct perf_pmu_fo
  */
 static int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_load)
 {
-       struct dirent *evt_ent;
-       DIR *format_dir;
+       struct io_dirent64 *evt_ent;
+       struct io_dir format_dir;
        int ret = 0;
 
-       format_dir = fdopendir(dirfd);
-       if (!format_dir)
-               return -EINVAL;
+       io_dir__init(&format_dir, dirfd);
 
-       while ((evt_ent = readdir(format_dir)) != NULL) {
+       while ((evt_ent = io_dir__readdir(&format_dir)) != NULL) {
                struct perf_pmu_format *format;
                char *name = evt_ent->d_name;
 
-               if (!strcmp(name, ".") || !strcmp(name, ".."))
+               if (io_dir__is_dir(&format_dir, evt_ent))
                        continue;
 
                format = perf_pmu__new_format(&pmu->format, name);
@@ -234,7 +233,7 @@ static int perf_pmu__format_parse(struct perf_pmu *pmu, int dirfd, bool eager_lo
                }
        }
 
-       closedir(format_dir);
+       close(format_dir.dirfd);
        return ret;
 }
 
@@ -635,14 +634,12 @@ static inline bool pmu_alias_info_file(const char *name)
  */
 static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
 {
-       struct dirent *evt_ent;
-       DIR *event_dir;
+       struct io_dirent64 *evt_ent;
+       struct io_dir event_dir;
 
-       event_dir = fdopendir(events_dir_fd);
-       if (!event_dir)
-               return -EINVAL;
+       io_dir__init(&event_dir, events_dir_fd);
 
-       while ((evt_ent = readdir(event_dir))) {
+       while ((evt_ent = io_dir__readdir(&event_dir))) {
                char *name = evt_ent->d_name;
                int fd;
                FILE *file;
@@ -674,7 +671,6 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
                fclose(file);
        }
 
-       closedir(event_dir);
        pmu->sysfs_aliases_loaded = true;
        return 0;
 }
@@ -2221,10 +2217,9 @@ static void perf_pmu__del_caps(struct perf_pmu *pmu)
  */
 int perf_pmu__caps_parse(struct perf_pmu *pmu)
 {
-       struct stat st;
        char caps_path[PATH_MAX];
-       DIR *caps_dir;
-       struct dirent *evt_ent;
+       struct io_dir caps_dir;
+       struct io_dirent64 *evt_ent;
        int caps_fd;
 
        if (pmu->caps_initialized)
@@ -2235,24 +2230,21 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu)
        if (!perf_pmu__pathname_scnprintf(caps_path, sizeof(caps_path), pmu->name, "caps"))
                return -1;
 
-       if (stat(caps_path, &st) < 0) {
+       caps_fd = open(caps_path, O_CLOEXEC | O_DIRECTORY | O_RDONLY);
+       if (caps_fd == -1) {
                pmu->caps_initialized = true;
                return 0;       /* no error if caps does not exist */
        }
 
-       caps_dir = opendir(caps_path);
-       if (!caps_dir)
-               return -EINVAL;
-
-       caps_fd = dirfd(caps_dir);
+       io_dir__init(&caps_dir, caps_fd);
 
-       while ((evt_ent = readdir(caps_dir)) != NULL) {
+       while ((evt_ent = io_dir__readdir(&caps_dir)) != NULL) {
                char *name = evt_ent->d_name;
                char value[128];
                FILE *file;
                int fd;
 
-               if (!strcmp(name, ".") || !strcmp(name, ".."))
+               if (io_dir__is_dir(&caps_dir, evt_ent))
                        continue;
 
                fd = openat(caps_fd, name, O_RDONLY);
@@ -2274,7 +2266,7 @@ int perf_pmu__caps_parse(struct perf_pmu *pmu)
                fclose(file);
        }
 
-       closedir(caps_dir);
+       close(caps_fd);
 
        pmu->caps_initialized = true;
        return pmu->nr_caps;
index 8a0a919415d497affaa89775061f30a1a926e0b1..afd59d678fd02c48faa7d3800ed08afbfa63f393 100644 (file)
@@ -3,10 +3,10 @@
 #include <linux/list_sort.h>
 #include <linux/string.h>
 #include <linux/zalloc.h>
+#include <api/io_dir.h>
 #include <subcmd/pager.h>
 #include <sys/types.h>
 #include <ctype.h>
-#include <dirent.h>
 #include <pthread.h>
 #include <string.h>
 #include <unistd.h>
@@ -235,20 +235,16 @@ static void pmu_read_sysfs(unsigned int to_read_types)
 
        if (to_read_types & (PERF_TOOL_PMU_TYPE_PE_CORE_MASK | PERF_TOOL_PMU_TYPE_PE_OTHER_MASK)) {
                int fd = perf_pmu__event_source_devices_fd();
-               DIR *dir;
-               struct dirent *dent;
+               struct io_dir dir;
+               struct io_dirent64 *dent;
                bool core_only = (to_read_types & PERF_TOOL_PMU_TYPE_PE_OTHER_MASK) == 0;
 
                if (fd < 0)
                        goto skip_pe_pmus;
 
-               dir = fdopendir(fd);
-               if (!dir) {
-                       close(fd);
-                       goto skip_pe_pmus;
-               }
+               io_dir__init(&dir, fd);
 
-               while ((dent = readdir(dir))) {
+               while ((dent = io_dir__readdir(&dir)) != NULL) {
                        if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
                                continue;
                        if (core_only && !is_pmu_core(dent->d_name))
@@ -257,7 +253,7 @@ static void pmu_read_sysfs(unsigned int to_read_types)
                        perf_pmu__find2(fd, dent->d_name);
                }
 
-               closedir(dir);
+               close(fd);
        }
 skip_pe_pmus:
        if ((to_read_types & PERF_TOOL_PMU_TYPE_PE_CORE_MASK) && list_empty(&core_pmus)) {
@@ -721,8 +717,8 @@ bool perf_pmus__supports_extended_type(void)
 char *perf_pmus__default_pmu_name(void)
 {
        int fd;
-       DIR *dir;
-       struct dirent *dent;
+       struct io_dir dir;
+       struct io_dirent64 *dent;
        char *result = NULL;
 
        if (!list_empty(&core_pmus))
@@ -732,13 +728,9 @@ char *perf_pmus__default_pmu_name(void)
        if (fd < 0)
                return strdup("cpu");
 
-       dir = fdopendir(fd);
-       if (!dir) {
-               close(fd);
-               return strdup("cpu");
-       }
+       io_dir__init(&dir, fd);
 
-       while ((dent = readdir(dir))) {
+       while ((dent = io_dir__readdir(&dir)) != NULL) {
                if (!strcmp(dent->d_name, ".") || !strcmp(dent->d_name, ".."))
                        continue;
                if (is_pmu_core(dent->d_name)) {
@@ -747,7 +739,7 @@ char *perf_pmus__default_pmu_name(void)
                }
        }
 
-       closedir(dir);
+       close(fd);
        return result ?: strdup("cpu");
 }