mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
perf pmu: Switch 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. 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>
This commit is contained in:
parent
f7cada5f7e
commit
6a81a3fd9e
|
|
@ -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;
|
||||
io_dir__init(&caps_dir, caps_fd);
|
||||
|
||||
caps_fd = dirfd(caps_dir);
|
||||
|
||||
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;
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user