diff options
author | 2025-02-21 22:10:12 -0800 | |
---|---|---|
committer | 2025-02-24 15:46:33 -0800 | |
commit | d996c726a5a4c794ed1d1e54702179d319d1c7e8 (patch) | |
tree | 0218055a1a3a3f4df1a9bd7875d71952746121c0 | |
parent | perf parse-events: Switch tracepoints to io_dir__readdir (diff) | |
download | wireguard-linux-d996c726a5a4c794ed1d1e54702179d319d1c7e8.tar.xz wireguard-linux-d996c726a5a4c794ed1d1e54702179d319d1c7e8.zip |
perf hwmon_pmu: Switch event discovery to io_dir__readdir
Avoid DIR allocations when scanning sysfs by using io_dir for the
readdir implementation, that allocates about 1kb on the stack.
Signed-off-by: Ian Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250222061015.303622-8-irogers@google.com
Signed-off-by: Namhyung Kim <namhyung@kernel.org>
-rw-r--r-- | tools/perf/util/hwmon_pmu.c | 42 |
1 files changed, 17 insertions, 25 deletions
diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c index acd889b2462f..3cce77fc8004 100644 --- a/tools/perf/util/hwmon_pmu.c +++ b/tools/perf/util/hwmon_pmu.c @@ -11,13 +11,13 @@ #include <sys/types.h> #include <assert.h> #include <ctype.h> -#include <dirent.h> #include <fcntl.h> #include <stddef.h> #include <stdlib.h> #include <string.h> #include <api/fs/fs.h> #include <api/io.h> +#include <api/io_dir.h> #include <linux/kernel.h> #include <linux/string.h> #include <linux/zalloc.h> @@ -235,31 +235,22 @@ static void fix_name(char *p) static int hwmon_pmu__read_events(struct hwmon_pmu *pmu) { - DIR *dir; - struct dirent *ent; - int dup_fd, err = 0; + int err = 0; struct hashmap_entry *cur, *tmp; size_t bkt; + struct io_dirent64 *ent; + struct io_dir dir; if (pmu->pmu.sysfs_aliases_loaded) return 0; - /* - * Use a dup-ed fd as closedir will close it. Use openat so that the - * directory contents are refreshed. - */ - dup_fd = openat(pmu->hwmon_dir_fd, ".", O_DIRECTORY); + /* Use openat so that the directory contents are refreshed. */ + io_dir__init(&dir, openat(pmu->hwmon_dir_fd, ".", O_CLOEXEC | O_DIRECTORY | O_RDONLY)); - if (dup_fd == -1) - return -ENOMEM; + if (dir.dirfd < 0) + return -ENOENT; - dir = fdopendir(dup_fd); - if (!dir) { - close(dup_fd); - return -ENOMEM; - } - - while ((ent = readdir(dir)) != NULL) { + while ((ent = io_dir__readdir(&dir)) != NULL) { enum hwmon_type type; int number; enum hwmon_item item; @@ -347,7 +338,7 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu) pmu->pmu.sysfs_aliases_loaded = true; err_out: - closedir(dir); + close(dir.dirfd); return err; } @@ -702,8 +693,8 @@ int hwmon_pmu__check_alias(struct parse_events_terms *terms, struct perf_pmu_inf int perf_pmus__read_hwmon_pmus(struct list_head *pmus) { char *line = NULL; - DIR *class_hwmon_dir; - struct dirent *class_hwmon_ent; + struct io_dirent64 *class_hwmon_ent; + struct io_dir class_hwmon_dir; char buf[PATH_MAX]; const char *sysfs = sysfs__mountpoint(); @@ -711,11 +702,12 @@ int perf_pmus__read_hwmon_pmus(struct list_head *pmus) return 0; scnprintf(buf, sizeof(buf), "%s/class/hwmon/", sysfs); - class_hwmon_dir = opendir(buf); - if (!class_hwmon_dir) + io_dir__init(&class_hwmon_dir, open(buf, O_CLOEXEC | O_DIRECTORY | O_RDONLY)); + + if (class_hwmon_dir.dirfd < 0) return 0; - while ((class_hwmon_ent = readdir(class_hwmon_dir)) != NULL) { + while ((class_hwmon_ent = io_dir__readdir(&class_hwmon_dir)) != NULL) { size_t line_len; int hwmon_dir, name_fd; struct io io; @@ -745,7 +737,7 @@ int perf_pmus__read_hwmon_pmus(struct list_head *pmus) close(name_fd); } free(line); - closedir(class_hwmon_dir); + close(class_hwmon_dir.dirfd); return 0; } |