Commit d996c726 authored by Ian Rogers's avatar Ian Rogers Committed by Namhyung Kim
Browse files

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: default avatarIan Rogers <irogers@google.com>
Link: https://lore.kernel.org/r/20250222061015.303622-8-irogers@google.com


Signed-off-by: default avatarNamhyung Kim <namhyung@kernel.org>
parent bb327140
Loading
Loading
Loading
Loading
+17 −25
Original line number Diff line number Diff line
@@ -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;
}