[PATCH 2/7] perf: Create a symlink for a PMU

kan.liang
2021-06-24T01:37:01Z

From: Kan Liang <kan.liang@linux.intel.com>

A perf PMU may have two PMU names. For example, Intel Sapphire Rapids
server supports the discovery mechanism. Without the platform-specific
support, an uncore PMU is named by a type ID plus a box ID, e.g.,
uncore_type_0_0, because the real name of the uncore PMU cannot be
retrieved from the discovery table. With the platform-specific support
later, perf has the mapping information from a type ID to a specific
uncore unit. Just like the previous platforms, the uncore PMU will be
named by the real PMU name, e.g., uncore_cha_0. The user scripts which
work well with the old name may not work anymore. To avoid the issue, a
symlink should be created from the new to the old name.

The perf PMU devices are created under /sys/bus/event_source/devices/.
The symlink should be created in the same directory to facilitate the
perf tool.

Add a new variable, link_name, to store the new name of a PMU. Link it
to the old name if applies.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
---
include/linux/perf_event.h | 1 +
kernel/events/core.c | 19 +++++++++++++++++++
2 files changed, 20 insertions(+)

diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index f5a6a2f..c8a3388 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -284,6 +284,7 @@ struct pmu {
const struct attribute_group **attr_groups;
const struct attribute_group **attr_update;
const char *name;
+ const char *link_name;
int type;

/*
diff --git a/kernel/events/core.c b/kernel/events/core.c
index f0cc8e5..b6024f6 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -10952,6 +10952,16 @@ static struct bus_type pmu_bus = {

static void pmu_dev_release(struct device *dev)
{
+ struct pmu *pmu = dev_get_drvdata(dev);
+
+ if (pmu && pmu->link_name) {
+ struct kset *devices_kset;
+
+ devices_kset = bus_get_devices_kset(pmu->dev->bus);
+ if (devices_kset)
+ sysfs_remove_link(&devices_kset->kobj, pmu->link_name);
+ }
+
kfree(dev);
}

@@ -10989,6 +10999,15 @@ static int pmu_dev_alloc(struct pmu *pmu)
if (ret)
goto del_dev;

+ if (pmu->link_name) {
+ struct kset *devices_kset;
+
+ devices_kset = bus_get_devices_kset(pmu->dev->bus);
+ if (devices_kset)
+ ret = sysfs_create_link(&devices_kset->kobj,
+ &pmu->dev->kobj,
+ pmu->link_name);
+ }
out:
return ret;

--
2.7.4