From: Ian Rogers <irogers@google.com>
To: Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@redhat.com>,
Arnaldo Carvalho de Melo <acme@kernel.org>,
Namhyung Kim <namhyung@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>,
Adrian Hunter <adrian.hunter@intel.com>,
James Clark <james.clark@linaro.org>,
linux-perf-users@vger.kernel.org, linux-kernel@vger.kernel.org,
Ian Rogers <irogers@google.com>
Subject: [PATCH 01/11] perf pmu: Generalize pmu_alias_info_file() and lazy single-event sysfs loading
Date: Fri, 13 Nov 2026 13:10:52 -0800 [thread overview]
Message-ID: <20261113211105.3118281-2-irogers@google.com> (raw)
In-Reply-To: <20261113211105.3118281-1-irogers@google.com>
Prepare struct perf_pmu_alias and sysfs event loading for layered
filesystem overlays while keeping struct perf_pmu_alias private to
pmu.c:
1. Add enum pmu_event_file_kind and pmu_event_file_kind() in pmu.c,
teaching pmu_alias_info_file() to recognize extended sidecar
extensions (.scale-unit, .desc, .long-desc, .topic, .compat,
.deprecated, .legacy-terms, .retire-lat-mean, .retire-lat-min, and
.retire-lat-max) alongside existing kernel sysfs sidecars (.unit,
.scale, .per-pkg, and .snapshot).
2. Switch sidecar attribute readers to openat() relative to an open
events directory fd, allowing boolean sidecars to express both 0
and 1 and marking alias->info_loaded once read so sidecars are not
re-opened repeatedly.
3. Make perf_pmu__find_alias() lazily open only the requested event
(trying exact, lowercase, and uppercase names) and its sidecars via
openat() instead of calling pmu_aliases_parse() to readdir() and
open every file in <sysfs>/<pmu>/events/ on a single-event lookup.
Signed-off-by: Ian Rogers <irogers@google.com>
---
tools/perf/util/pmu.c | 365 +++++++++++++++++++++++++++++-------------
1 file changed, 252 insertions(+), 113 deletions(-)
diff --git a/tools/perf/util/pmu.c b/tools/perf/util/pmu.c
index 01753d5c69d1..d10b8c0810fb 100644
--- a/tools/perf/util/pmu.c
+++ b/tools/perf/util/pmu.c
@@ -10,9 +10,11 @@
#include <unistd.h>
#include <errno.h>
#include <stdbool.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <strings.h>
#include <dirent.h>
#include <api/fs/fs.h>
#include <api/io.h>
@@ -54,9 +56,28 @@ enum event_source {
EVENT_SRC_SYS_JSON,
};
+enum pmu_event_file_kind {
+ PMU_EVENT_FILE_BASE,
+ PMU_EVENT_FILE_UNIT,
+ PMU_EVENT_FILE_SCALE,
+ PMU_EVENT_FILE_PER_PKG,
+ PMU_EVENT_FILE_SNAPSHOT,
+ PMU_EVENT_FILE_SCALE_UNIT,
+ PMU_EVENT_FILE_DESC,
+ PMU_EVENT_FILE_LONG_DESC,
+ PMU_EVENT_FILE_TOPIC,
+ PMU_EVENT_FILE_COMPAT,
+ PMU_EVENT_FILE_DEPRECATED,
+ PMU_EVENT_FILE_LEGACY_TERMS,
+ PMU_EVENT_FILE_RETIRE_LAT_MEAN,
+ PMU_EVENT_FILE_RETIRE_LAT_MIN,
+ PMU_EVENT_FILE_RETIRE_LAT_MAX,
+};
+
/**
- * struct perf_pmu_alias - An event either read from sysfs or builtin in
- * pmu-events.c, created by parsing the pmu-events json files.
+ * struct perf_pmu_alias - An event either read from sysfs, a directory
+ * overlay, or builtin in pmu-events.c, created by parsing the pmu-events json
+ * files.
*/
struct perf_pmu_alias {
/** @name: Name of the event like "mem-loads". */
@@ -74,7 +95,7 @@ struct perf_pmu_alias {
char *terms;
/**
* @legacy_terms: If the event aliases a legacy event, holds a copy
- * ofthe legacy event string.
+ * of the legacy event string.
*/
char *legacy_terms;
/**
@@ -82,8 +103,10 @@ struct perf_pmu_alias {
* differ from the PMU name as it won't have suffixes.
*/
char *pmu_name;
+ /** @compat: Optional uncore/system PMU identifier match pattern. */
+ char *compat;
/** @unit: Units for the event, such as bytes or cache lines. */
- char unit[UNIT_MAX_LEN+1];
+ char unit[UNIT_MAX_LEN + 1];
/** @scale: Value to scale read counter values by. */
double scale;
/** @retirement_latency_mean: Value to be given for unsampled retirement latency mean. */
@@ -111,7 +134,7 @@ struct perf_pmu_alias {
bool deprecated;
/**
* @legacy_deprecated_checked: Legacy events may not be supported by the
- * PMU need to be checked. If they aren't supported they are marked
+ * PMU and need to be checked. If they aren't supported they are marked
* deprecated.
*/
bool legacy_deprecated_checked;
@@ -119,6 +142,26 @@ struct perf_pmu_alias {
bool from_sysfs;
/** @info_loaded: Have the scale, unit and other values been read from disk? */
bool info_loaded;
+ /** @resolved: Fully resolved across all PMU layers. */
+ bool resolved;
+ /** @terms_from_legacy: @terms was promoted from @legacy_terms. */
+ bool terms_from_legacy;
+ /** @has_scale: Has scale been explicitly set by a layer? */
+ bool has_scale;
+ /** @has_unit: Has unit been explicitly set by a layer? */
+ bool has_unit;
+ /** @has_per_pkg: Has per_pkg been explicitly set by a layer? */
+ bool has_per_pkg;
+ /** @has_snapshot: Has snapshot been explicitly set by a layer? */
+ bool has_snapshot;
+ /** @has_deprecated: Has deprecated been explicitly set by a layer? */
+ bool has_deprecated;
+ /** @has_retire_lat_mean: Has retirement_latency_mean been explicitly set? */
+ bool has_retire_lat_mean;
+ /** @has_retire_lat_min: Has retirement_latency_min been explicitly set? */
+ bool has_retire_lat_min;
+ /** @has_retire_lat_max: Has retirement_latency_max been explicitly set? */
+ bool has_retire_lat_max;
};
static int pmu_aliases_parse(struct perf_pmu *pmu);
@@ -295,28 +338,64 @@ int perf_pmu__convert_scale(const char *scale, char **end, double *sval)
return parse_double(scale, end, sval);
}
-static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
+static const struct {
+ const char *suffix;
+ size_t len;
+ enum pmu_event_file_kind kind;
+} pmu_event_suffixes[] = {
+ { ".unit", 5, PMU_EVENT_FILE_UNIT },
+ { ".desc", 5, PMU_EVENT_FILE_DESC },
+ { ".scale", 6, PMU_EVENT_FILE_SCALE },
+ { ".topic", 6, PMU_EVENT_FILE_TOPIC },
+ { ".compat", 7, PMU_EVENT_FILE_COMPAT },
+ { ".per-pkg", 8, PMU_EVENT_FILE_PER_PKG },
+ { ".snapshot", 9, PMU_EVENT_FILE_SNAPSHOT },
+ { ".long-desc", 10, PMU_EVENT_FILE_LONG_DESC },
+ { ".scale-unit", 11, PMU_EVENT_FILE_SCALE_UNIT },
+ { ".deprecated", 11, PMU_EVENT_FILE_DEPRECATED },
+ { ".legacy-terms", 13, PMU_EVENT_FILE_LEGACY_TERMS },
+ { ".retire-lat-min", 15, PMU_EVENT_FILE_RETIRE_LAT_MIN },
+ { ".retire-lat-max", 15, PMU_EVENT_FILE_RETIRE_LAT_MAX },
+ { ".retire-lat-mean", 16, PMU_EVENT_FILE_RETIRE_LAT_MEAN },
+};
+
+static enum pmu_event_file_kind pmu_event_file_kind(const char *name, size_t *base_len)
+{
+ size_t len = strlen(name);
+
+ for (size_t i = 0; i < ARRAY_SIZE(pmu_event_suffixes); i++) {
+ size_t slen = pmu_event_suffixes[i].len;
+
+ if (len > slen && !strcasecmp(name + len - slen, pmu_event_suffixes[i].suffix)) {
+ if (base_len)
+ *base_len = len - slen;
+ return pmu_event_suffixes[i].kind;
+ }
+ }
+ if (base_len)
+ *base_len = len;
+ return PMU_EVENT_FILE_BASE;
+}
+
+static inline bool pmu_alias_info_file(const char *name)
+{
+ return pmu_event_file_kind(name, NULL) != PMU_EVENT_FILE_BASE;
+}
+
+static int perf_pmu__parse_scale_at(int events_dir_fd, const char *event_name,
+ struct perf_pmu_alias *alias)
{
- struct stat st;
ssize_t sret;
- size_t len;
char scale[128];
+ char filename[NAME_MAX + 16];
int fd, ret = -1;
- char path[PATH_MAX];
-
- len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
- if (!len)
- return 0;
- scnprintf(path + len, sizeof(path) - len, "%s/events/%s.scale", pmu->name, alias->name);
- fd = open(path, O_RDONLY);
+ scnprintf(filename, sizeof(filename), "%s.scale", event_name);
+ fd = openat(events_dir_fd, filename, O_RDONLY);
if (fd == -1)
return -1;
- if (fstat(fd, &st) < 0)
- goto error;
-
- sret = read(fd, scale, sizeof(scale)-1);
+ sret = read(fd, scale, sizeof(scale) - 1);
if (sret <= 0)
goto error;
@@ -326,25 +405,22 @@ static int perf_pmu__parse_scale(struct perf_pmu *pmu, struct perf_pmu_alias *al
scale[sret] = '\0';
ret = perf_pmu__convert_scale(scale, NULL, &alias->scale);
+ if (!ret)
+ alias->has_scale = true;
error:
close(fd);
return ret;
}
-static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
+static int perf_pmu__parse_unit_at(int events_dir_fd, const char *event_name,
+ struct perf_pmu_alias *alias)
{
- char path[PATH_MAX];
- size_t len;
+ char filename[NAME_MAX + 16];
ssize_t sret;
int fd;
-
- len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
- if (!len)
- return 0;
- scnprintf(path + len, sizeof(path) - len, "%s/events/%s.unit", pmu->name, alias->name);
-
- fd = open(path, O_RDONLY);
+ scnprintf(filename, sizeof(filename), "%s.unit", event_name);
+ fd = openat(events_dir_fd, filename, O_RDONLY);
if (fd == -1)
return -1;
@@ -359,6 +435,7 @@ static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *ali
else
alias->unit[sret] = '\0';
+ alias->has_unit = true;
return 0;
error:
close(fd);
@@ -366,45 +443,57 @@ static int perf_pmu__parse_unit(struct perf_pmu *pmu, struct perf_pmu_alias *ali
return -1;
}
-static bool perf_pmu__parse_event_source_bool(const char *pmu_name, const char *event_name,
- const char *suffix)
+static int perf_pmu__parse_bool_at(int events_dir_fd, const char *event_name,
+ const char *suffix, bool *out_val)
{
- char path[PATH_MAX];
- size_t len;
+ char filename[NAME_MAX + 32];
+ char buf[16];
+ ssize_t sret;
int fd;
- len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
- if (!len)
- return false;
-
- scnprintf(path + len, sizeof(path) - len, "%s/events/%s.%s", pmu_name, event_name, suffix);
-
- fd = open(path, O_RDONLY);
+ scnprintf(filename, sizeof(filename), "%s.%s", event_name, suffix);
+ fd = openat(events_dir_fd, filename, O_RDONLY);
if (fd == -1)
- return false;
+ return -ENOENT;
-#ifndef NDEBUG
- {
- char buf[8];
+ sret = read(fd, buf, sizeof(buf) - 1);
+ close(fd);
+ if (sret <= 0)
+ return -EINVAL;
- len = read(fd, buf, sizeof(buf));
- assert(len == 1 || len == 2);
- assert(buf[0] == '1');
- }
-#endif
+ while (sret > 0 && isspace(buf[sret - 1]))
+ sret--;
+ buf[sret] = '\0';
- close(fd);
- return true;
+ if (!strcmp(buf, "1") || !strcasecmp(buf, "true") || !strcasecmp(buf, "yes")) {
+ *out_val = true;
+ return 0;
+ }
+ if (!strcmp(buf, "0") || !strcasecmp(buf, "false") || !strcasecmp(buf, "no")) {
+ *out_val = false;
+ return 0;
+ }
+ return -EINVAL;
}
-static void perf_pmu__parse_per_pkg(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
+static void read_alias_info_at(int events_dir_fd, struct perf_pmu_alias *alias)
{
- alias->per_pkg = perf_pmu__parse_event_source_bool(pmu->name, alias->name, "per-pkg");
-}
+ bool val;
-static void perf_pmu__parse_snapshot(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
-{
- alias->snapshot = perf_pmu__parse_event_source_bool(pmu->name, alias->name, "snapshot");
+ if (!alias->from_sysfs || alias->info_loaded || events_dir_fd < 0)
+ return;
+
+ perf_pmu__parse_unit_at(events_dir_fd, alias->name, alias);
+ perf_pmu__parse_scale_at(events_dir_fd, alias->name, alias);
+ if (perf_pmu__parse_bool_at(events_dir_fd, alias->name, "per-pkg", &val) == 0) {
+ alias->per_pkg = val;
+ alias->has_per_pkg = true;
+ }
+ if (perf_pmu__parse_bool_at(events_dir_fd, alias->name, "snapshot", &val) == 0) {
+ alias->snapshot = val;
+ alias->has_snapshot = true;
+ }
+ alias->info_loaded = true;
}
/* Delete an alias entry. */
@@ -418,6 +507,7 @@ static void perf_pmu_free_alias(struct perf_pmu_alias *alias)
zfree(&alias->long_desc);
zfree(&alias->topic);
zfree(&alias->pmu_name);
+ zfree(&alias->compat);
zfree(&alias->terms);
zfree(&alias->legacy_terms);
free(alias);
@@ -438,13 +528,22 @@ static void perf_pmu__del_aliases(struct perf_pmu *pmu)
pmu->aliases = NULL;
}
+static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
+ const char *desc, const char *val, int val_fd,
+ const struct pmu_event *pe, enum event_source src,
+ int events_dir_fd);
+
static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu,
const char *name,
bool load)
{
- struct perf_pmu_alias *alias;
- bool has_sysfs_event;
- char event_file_name[NAME_MAX + 8];
+ struct perf_pmu_alias *alias = NULL;
+ char path[PATH_MAX];
+ char lower_name[NAME_MAX];
+ char upper_name[NAME_MAX];
+ const char *candidates[3];
+ size_t nr_candidates = 0, name_len, path_len;
+ int events_dir_fd;
if (hashmap__find(pmu->aliases, name, &alias))
return alias;
@@ -452,29 +551,61 @@ static struct perf_pmu_alias *perf_pmu__find_alias(struct perf_pmu *pmu,
if (!load || pmu->sysfs_aliases_loaded)
return NULL;
- /*
- * Test if alias/event 'name' exists in the PMU's sysfs/events
- * directory. If not skip parsing the sysfs aliases. Sysfs event
- * name must be all lower or all upper case.
- */
- scnprintf(event_file_name, sizeof(event_file_name), "events/%s", name);
- for (size_t i = 7, n = 7 + strlen(name); i < n; i++)
- event_file_name[i] = tolower(event_file_name[i]);
+ name_len = strlen(name);
+ if (name_len == 0 || name_len >= NAME_MAX || name[0] == '.' ||
+ strchr(name, '/') || pmu_alias_info_file(name))
+ return NULL;
- has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);
- if (!has_sysfs_event) {
- for (size_t i = 7, n = 7 + strlen(name); i < n; i++)
- event_file_name[i] = toupper(event_file_name[i]);
+ path_len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+ if (!path_len)
+ return NULL;
+ scnprintf(path + path_len, sizeof(path) - path_len, "%s/events", pmu->name);
- has_sysfs_event = perf_pmu__file_exists(pmu, event_file_name);
+ events_dir_fd = open(path, O_DIRECTORY | O_RDONLY);
+ if (events_dir_fd == -1) {
+ if (errno == ENOENT)
+ pmu->sysfs_aliases_loaded = true;
+ return NULL;
}
- if (has_sysfs_event) {
- pmu_aliases_parse(pmu);
- if (hashmap__find(pmu->aliases, name, &alias))
- return alias;
+
+ candidates[nr_candidates++] = name;
+ for (size_t i = 0; i < name_len; i++) {
+ lower_name[i] = tolower((unsigned char)name[i]);
+ upper_name[i] = toupper((unsigned char)name[i]);
}
+ lower_name[name_len] = '\0';
+ upper_name[name_len] = '\0';
- return NULL;
+ if (strcmp(lower_name, name) != 0)
+ candidates[nr_candidates++] = lower_name;
+ if (strcmp(upper_name, name) != 0 && strcmp(upper_name, lower_name) != 0)
+ candidates[nr_candidates++] = upper_name;
+
+ /*
+ * Lazily open only the requested event and its sidecars via openat()
+ * rather than scanning every file in sysfs/events/.
+ */
+ for (size_t i = 0; i < nr_candidates; i++) {
+ struct stat st;
+ int fd = openat(events_dir_fd, candidates[i], O_RDONLY);
+
+ if (fd < 0)
+ continue;
+ if (fstat(fd, &st) == 0 && !S_ISDIR(st.st_mode)) {
+ if (perf_pmu__new_alias(pmu, candidates[i], /*desc=*/NULL,
+ /*val=*/NULL, fd, /*pe=*/NULL,
+ EVENT_SRC_SYSFS, events_dir_fd) == 0 &&
+ hashmap__find(pmu->aliases, name, &alias)) {
+ read_alias_info_at(events_dir_fd, alias);
+ close(fd);
+ break;
+ }
+ }
+ close(fd);
+ }
+
+ close(events_dir_fd);
+ return alias;
}
static bool assign_str(const char *name, const char *field, char **old_str,
@@ -497,21 +628,30 @@ static bool assign_str(const char *name, const char *field, char **old_str,
static void read_alias_info(struct perf_pmu *pmu, struct perf_pmu_alias *alias)
{
+ char path[PATH_MAX];
+ size_t len;
+ int events_dir_fd;
+
if (!alias->from_sysfs || alias->info_loaded)
return;
- /*
- * load unit name and scale if available
- */
- perf_pmu__parse_unit(pmu, alias);
- perf_pmu__parse_scale(pmu, alias);
- perf_pmu__parse_per_pkg(pmu, alias);
- perf_pmu__parse_snapshot(pmu, alias);
+ len = perf_pmu__event_source_devices_scnprintf(path, sizeof(path));
+ if (!len)
+ return;
+ scnprintf(path + len, sizeof(path) - len, "%s/events", pmu->name);
+
+ events_dir_fd = open(path, O_DIRECTORY | O_RDONLY);
+ if (events_dir_fd == -1)
+ return;
+
+ read_alias_info_at(events_dir_fd, alias);
+ close(events_dir_fd);
}
struct update_alias_data {
struct perf_pmu *pmu;
struct perf_pmu_alias *alias;
+ int events_dir_fd;
bool legacy;
};
@@ -522,7 +662,10 @@ static int update_alias(const struct pmu_event *pe,
struct update_alias_data *data = vdata;
int ret = 0;
- read_alias_info(data->pmu, data->alias);
+ if (data->events_dir_fd >= 0)
+ read_alias_info_at(data->events_dir_fd, data->alias);
+ else
+ read_alias_info(data->pmu, data->alias);
assign_str(pe->name, "desc", &data->alias->desc, pe->desc);
assign_str(pe->name, "long_desc", &data->alias->long_desc, pe->long_desc);
assign_str(pe->name, "topic", &data->alias->topic, pe->topic);
@@ -559,8 +702,9 @@ static int update_alias(const struct pmu_event *pe,
}
static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
- const char *desc, const char *val, int val_fd,
- const struct pmu_event *pe, enum event_source src)
+ const char *desc, const char *val, int val_fd,
+ const struct pmu_event *pe, enum event_source src,
+ int events_dir_fd)
{
struct perf_pmu_alias *alias, *old_alias;
int ret = 0;
@@ -607,8 +751,10 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
ret = parse_double(pe->retirement_latency_max, NULL,
&alias->retirement_latency_max);
}
- if (ret)
+ if (ret) {
+ perf_pmu_free_alias(alias);
return ret;
+ }
if (val_fd < 0) {
alias->terms = strdup(val);
@@ -621,6 +767,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
ret = io__getline(&io, &alias->terms, &line_len) < 0 ? -errno : 0;
if (ret) {
pr_err("Failed to read alias %s\n", name);
+ perf_pmu_free_alias(alias);
return ret;
}
if (line_len >= 1 && alias->terms[line_len - 1] == '\n')
@@ -631,6 +778,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
alias->long_desc = long_desc ? strdup(long_desc) : NULL;
alias->topic = topic ? strdup(topic) : NULL;
alias->pmu_name = pmu_name ? strdup(pmu_name) : NULL;
+ alias->compat = (pe && pe->compat) ? strdup(pe->compat) : NULL;
if (unit) {
if (perf_pmu__convert_scale(unit, (char **)&unit, &alias->scale) < 0) {
perf_pmu_free_alias(alias);
@@ -647,6 +795,7 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
struct update_alias_data data = {
.pmu = pmu,
.alias = alias,
+ .events_dir_fd = events_dir_fd,
.legacy = false,
};
if ((pmu_events_table__find_event(pmu->events_table, pmu, name,
@@ -681,28 +830,11 @@ static int perf_pmu__new_alias(struct perf_pmu *pmu, const char *name,
return 0;
}
-static inline bool pmu_alias_info_file(const char *name)
-{
- size_t len;
-
- len = strlen(name);
- if (len > 5 && !strcmp(name + len - 5, ".unit"))
- return true;
- if (len > 6 && !strcmp(name + len - 6, ".scale"))
- return true;
- if (len > 8 && !strcmp(name + len - 8, ".per-pkg"))
- return true;
- if (len > 9 && !strcmp(name + len - 9, ".snapshot"))
- return true;
-
- return false;
-}
-
/*
* Reading the pmu event aliases definition, which should be located at:
* /sys/bus/event_source/devices/<dev>/events as sysfs group attributes.
*/
-static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
+static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd, bool eager_info)
{
struct io_dirent64 *evt_ent;
struct io_dir event_dir;
@@ -713,7 +845,7 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
char *name = evt_ent->d_name;
int fd;
- if (!strcmp(name, ".") || !strcmp(name, ".."))
+ if (!strcmp(name, ".") || !strcmp(name, "..") || name[0] == '.')
continue;
/*
@@ -730,8 +862,14 @@ static int __pmu_aliases_parse(struct perf_pmu *pmu, int events_dir_fd)
if (perf_pmu__new_alias(pmu, name, /*desc=*/ NULL,
/*val=*/ NULL, fd, /*pe=*/ NULL,
- EVENT_SRC_SYSFS) < 0)
+ EVENT_SRC_SYSFS, events_dir_fd) < 0)
pr_debug("Cannot set up %s\n", name);
+ else if (eager_info) {
+ struct perf_pmu_alias *alias;
+
+ if (hashmap__find(pmu->aliases, name, &alias))
+ read_alias_info_at(events_dir_fd, alias);
+ }
close(fd);
}
@@ -758,7 +896,7 @@ static int pmu_aliases_parse(struct perf_pmu *pmu)
pmu->sysfs_aliases_loaded = true;
return 0;
}
- ret = __pmu_aliases_parse(pmu, events_dir_fd);
+ ret = __pmu_aliases_parse(pmu, events_dir_fd, /*eager_info=*/false);
close(events_dir_fd);
return ret;
}
@@ -774,7 +912,7 @@ static int pmu_aliases_parse_eager(struct perf_pmu *pmu, int sysfs_fd)
pmu->sysfs_aliases_loaded = true;
return 0;
}
- ret = __pmu_aliases_parse(pmu, events_dir_fd);
+ ret = __pmu_aliases_parse(pmu, events_dir_fd, /*eager_info=*/true);
close(events_dir_fd);
return ret;
}
@@ -1066,7 +1204,7 @@ static int pmu_add_cpu_aliases_map_callback(const struct pmu_event *pe,
struct perf_pmu *pmu = vdata;
perf_pmu__new_alias(pmu, pe->name, pe->desc, pe->event, /*val_fd=*/ -1,
- pe, EVENT_SRC_CPU_JSON);
+ pe, EVENT_SRC_CPU_JSON, /*events_dir_fd=*/ -1);
return 0;
}
@@ -1119,7 +1257,8 @@ static int pmu_add_sys_aliases_iter_fn(const struct pmu_event *pe,
pe->event,
/*val_fd=*/ -1,
pe,
- EVENT_SRC_SYS_JSON);
+ EVENT_SRC_SYS_JSON,
+ /*events_dir_fd=*/ -1);
}
return 0;
}
base-commit: 4af65363b11fc4fe65fcb497f68bbe4f3e3a4d2c
prerequisite-patch-id: 3e93fd262f5e70cff78114a0736c8fc8abeb7977
prerequisite-patch-id: 5e284ee3a3af71e8bfe3e40719396cf60fbece96
prerequisite-patch-id: 4d4b5b43c0ca0ac929fb3b73db615805e022d86a
prerequisite-patch-id: 447412f5e17799157dc8981ffa28378bc5f7fe72
prerequisite-patch-id: ac7b807fcd0e795cc831307eed2d7148a609b941
prerequisite-patch-id: 8c306425c73d176dfeeede044b57f7ed383e19d1
prerequisite-patch-id: dfce7f2910fbd18bc8dc3965c52cf6b08a825180
prerequisite-patch-id: 4730aa572afe4e6d47f6aceaff92fccc15327881
prerequisite-patch-id: 17cb0dd6eaa58cec5d6309dda84f122c6e381d4d
prerequisite-patch-id: cda8414fd68671e1333246f22cbfedb980173821
--
2.56.1.703.gf848ed807c-goog
next prev parent reply other threads:[~2026-11-13 21:11 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 21:10 [PATCH 00/11] perf pmu: Layered sysfs-style PMU event and metric directories Ian Rogers
2026-11-13 21:10 ` Ian Rogers [this message]
2026-11-13 21:10 ` [PATCH 02/11] perf pmu: Add metric and metricgroup storage on struct perf_pmu Ian Rogers
2026-11-13 21:10 ` [PATCH 03/11] perf pmu-layer: Introduce stateless struct pmu_layer abstraction and builtin adapter Ian Rogers
2026-11-13 21:10 ` [PATCH 04/11] perf pmu-layer: Add openat-based directory layer with literal CPUID/symlink lookup Ian Rogers
2026-11-13 21:10 ` [PATCH 05/11] perf config: Add pmu-events.dir configuration option Ian Rogers
2026-11-13 21:10 ` [PATCH 06/11] perf pmu: Switch alias resolution and enumeration to layered PMU stack Ian Rogers
2026-11-13 21:10 ` [PATCH 07/11] perf metricgroup: Route metric and metricgroup lookups through struct perf_pmu Ian Rogers
2026-11-13 21:10 ` [PATCH 08/11] perf list, jevents: Add --export-dir and --output-dir sysfs-style exporters Ian Rogers
2026-11-13 21:11 ` [PATCH 09/11] perf jevents: Add compiled-in model and sys table iterators Ian Rogers
2026-11-13 21:11 ` [PATCH 10/11] perf list: Add --export-cpuid to export compiled-in CPU models Ian Rogers
2026-11-13 21:11 ` [PATCH 11/11] perf tests: Add round-trip export, CPUID symlink, and pmu-events.dir overlay tests Ian Rogers
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261113211105.3118281-2-irogers@google.com \
--to=irogers@google.com \
--cc=acme@kernel.org \
--cc=adrian.hunter@intel.com \
--cc=james.clark@linaro.org \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=namhyung@kernel.org \
--cc=peterz@infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®