From: Wei Li liwei391@huawei.com
hulk inclusion category: Bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/I47H3V CVE: NA
-------------------------------------------------
Use the new pmu_attr_update_notifier_chain to update attribute groups to fix kabi broken introduced by the following commit: "Intel: perf/core: Add attr_groups_update into struct pmu" "Intel: perf/x86: Use the new pmu::update_attrs attribute group".
Signed-off-by: Wei Li liwei391@huawei.com Signed-off-by: Zheng Zengkai zhengzengkai@huawei.com Reviewed-by: Yang Jihong yangjihong1@huawei.com --- arch/x86/events/core.c | 18 +++++++++++++++++- include/linux/perf_event.h | 4 +++- kernel/events/core.c | 28 +++++++++++++++++++++++++--- 3 files changed, 45 insertions(+), 5 deletions(-)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index 4e5873593056..7239f6109cc0 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -1810,6 +1810,22 @@ ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event) static struct attribute_group x86_pmu_attr_group; static struct attribute_group x86_pmu_caps_group;
+static int x86_pmu_attr_update_notify(struct notifier_block *nb, + unsigned long ret, void *group) +{ + struct pmu *tmp = group; + + if (tmp != &pmu) + return NOTIFY_DONE; + + *(int *)ret = sysfs_update_groups(&tmp->dev->kobj, x86_pmu.attr_update); + return NOTIFY_STOP; +} + +static struct notifier_block x86_pmu_attr_update_notifier = { + .notifier_call = &x86_pmu_attr_update_notify, +}; + static int __init init_hw_perf_events(void) { struct x86_pmu_quirk *quirk; @@ -1868,7 +1884,7 @@ static int __init init_hw_perf_events(void) if (!x86_pmu.events_sysfs_show) x86_pmu_events_group.attrs = &empty_attrs;
- pmu.attr_update = x86_pmu.attr_update; + pmu_attr_update_register_notifier(&x86_pmu_attr_update_notifier);
pr_info("... version: %d\n", x86_pmu.version); pr_info("... bit width: %d\n", x86_pmu.cntval_bits); diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h index 53869bbd8b5d..41bc1d3b311f 100644 --- a/include/linux/perf_event.h +++ b/include/linux/perf_event.h @@ -279,7 +279,6 @@ struct pmu { struct module *module; struct device *dev; const struct attribute_group **attr_groups; - const struct attribute_group **attr_update; const char *name; int type;
@@ -897,6 +896,9 @@ extern void perf_event_itrace_started(struct perf_event *event); extern int perf_pmu_register(struct pmu *pmu, const char *name, int type); extern void perf_pmu_unregister(struct pmu *pmu);
+extern int pmu_attr_update_register_notifier(struct notifier_block *nb); +extern int pmu_attr_update_unregister_notifier(struct notifier_block *nb); + extern int perf_num_counters(void); extern const char *perf_pmu_name(void); extern void __perf_event_task_sched_in(struct task_struct *prev, diff --git a/kernel/events/core.c b/kernel/events/core.c index 56617b912475..09869287b7ae 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -9690,6 +9690,30 @@ static struct bus_type pmu_bus = { .name = "event_source", .dev_groups = pmu_dev_groups, }; +static BLOCKING_NOTIFIER_HEAD(pmu_attr_update_notifier_chain); + +int pmu_attr_update_register_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_register( + &pmu_attr_update_notifier_chain, nb); +} +EXPORT_SYMBOL_GPL(pmu_attr_update_register_notifier); + +int pmu_attr_update_unregister_notifier(struct notifier_block *nb) +{ + return blocking_notifier_chain_unregister( + &pmu_attr_update_notifier_chain, nb); +} +EXPORT_SYMBOL_GPL(pmu_attr_update_unregister_notifier); + +static int pmu_attr_update_notifier_call_chain(struct pmu *pmu) +{ + int ret = 0; + + blocking_notifier_call_chain(&pmu_attr_update_notifier_chain, + (unsigned long)&ret, (void *)pmu); + return ret; +}
static void pmu_dev_release(struct device *dev) { @@ -9724,9 +9748,7 @@ static int pmu_dev_alloc(struct pmu *pmu) if (ret) goto del_dev;
- if (pmu->attr_update) - ret = sysfs_update_groups(&pmu->dev->kobj, pmu->attr_update); - + ret = pmu_attr_update_notifier_call_chain(pmu); if (ret) goto del_dev;