Re: [RFC PATCH v2 03/10] arm_mpam: resctrl: Do not fail CPU online when domain setup fails
From: Jinjie Ruan
Date: Mon Oct 26 2026 - 05:58:53 EST
在 2026/10/20 6:07, Reinette Chatre 写道:
> When a CPU comes online, mpam_resctrl_online_cpu() adds it to the resctrl
> domains of each resource in use, and sets up a new domain when the CPU
> is the first of its domain to come online. A failure to set up a domain
> is returned as the failure of MPAM's CPU hotplug startup callback.
Indeed the code works this way.
>
> The CPU hotplug core does not run the teardown callback for a CPU whose
> startup callback failed, so everything done for the CPU before the
> failure stays in place: the CPU remains in the domains of the resources
> that were handled before the failing one, and MPAM's per-MSC state for
> the CPU is not undone. If the failure happens when MPAM installs its
> CPU hotplug callbacks during enabling, the hotplug core discards the
> callbacks, leaving MPAM enabled and resctrl initialized but MPAM no
By the way, I previously ran into a case during testing where adding the
"maxcpu" boot parameter caused MPAM enabling to fail.
Link:
https://lore.kernel.org/all/20261020134239.3921377-6-ruanjinjie@xxxxxxxxxx/
> longer notified of CPU hotplug. If it happens when a CPU comes online
> later, the CPU fails to come online.
>
> Setting up a domain only fails if a memory allocation fails or if a
> class unexpectedly has no component for the CPU. For such rare failures
> losing a resctrl domain is a smaller cost than failing CPU online or
> leaving MPAM in an inconsistent state.
>
> Do not report domain setup failures from mpam_resctrl_online_cpu() and
> leave the CPU without a domain for that resource. Make
> mpam_resctrl_alloc_domain() return nothing since its failures are no
> longer reported. Keep adding the CPU to resctrl's default group even
Yes, We now always call resctrl_online_cpu() to add them to the default
group.
> when a domain could not be set up, since the CPU is online and runs
> tasks regardless, and resctrl expects every online CPU to belong to a
> resource group. Drop the warning when a CPU going offline has no domain,
> since a missing domain is now expected.
It is now valid for the domain to be empty when a CPU goes offline.
>
> Only domains that were set up are exposed through resctrl and torn down
> when their CPUs go offline. When another CPU of the same domain comes
> online, it sets up the domain again, and if that succeeds the domain
> does not include the CPU for which setup failed.
>
> Signed-off-by: Reinette Chatre <reinette.chatre@xxxxxxxxx>
> ---
> drivers/resctrl/mpam_devices.c | 2 +-
> drivers/resctrl/mpam_internal.h | 4 ++--
> drivers/resctrl/mpam_resctrl.c | 31 +++++++++++++++----------------
> 3 files changed, 18 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/resctrl/mpam_devices.c b/drivers/resctrl/mpam_devices.c
> index 48adc49b833c..d17d7a72dba1 100644
> --- a/drivers/resctrl/mpam_devices.c
> +++ b/drivers/resctrl/mpam_devices.c
> @@ -2249,7 +2249,7 @@ static int mpam_cpu_online(unsigned int cpu)
> }
>
> if (mpam_resctrl_enabled)
> - return mpam_resctrl_online_cpu(cpu);
> + mpam_resctrl_online_cpu(cpu);
>
> return 0;
> }
> diff --git a/drivers/resctrl/mpam_internal.h b/drivers/resctrl/mpam_internal.h
> index 1f86cc158100..84c7adbb1a40 100644
> --- a/drivers/resctrl/mpam_internal.h
> +++ b/drivers/resctrl/mpam_internal.h
> @@ -525,13 +525,13 @@ int mpam_get_cpumask_from_cache_id(unsigned long cache_id, u32 cache_level,
> #ifdef CONFIG_RESCTRL_FS
> int mpam_resctrl_setup(void);
> void mpam_resctrl_exit(void);
> -int mpam_resctrl_online_cpu(unsigned int cpu);
> +void mpam_resctrl_online_cpu(unsigned int cpu);
> void mpam_resctrl_offline_cpu(unsigned int cpu);
> void mpam_resctrl_teardown_class(struct mpam_class *class);
> #else
> static inline int mpam_resctrl_setup(void) { return 0; }
> static inline void mpam_resctrl_exit(void) { }
> -static inline int mpam_resctrl_online_cpu(unsigned int cpu) { return 0; }
> +static inline void mpam_resctrl_online_cpu(unsigned int cpu) { }
> static inline void mpam_resctrl_offline_cpu(unsigned int cpu) { }
> static inline void mpam_resctrl_teardown_class(struct mpam_class *class) { }
> #endif /* CONFIG_RESCTRL_FS */
> diff --git a/drivers/resctrl/mpam_resctrl.c b/drivers/resctrl/mpam_resctrl.c
> index b07e5dd895dd..dc442851fd7e 100644
> --- a/drivers/resctrl/mpam_resctrl.c
> +++ b/drivers/resctrl/mpam_resctrl.c
> @@ -1615,8 +1615,8 @@ static struct mpam_component *find_component(struct mpam_class *class, int cpu)
> return NULL;
> }
>
> -static struct mpam_resctrl_dom *
> -mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
> +static void mpam_resctrl_alloc_domain(unsigned int cpu,
> + struct mpam_resctrl_res *res)
> {
> int err;
> struct mpam_resctrl_dom *dom;
> @@ -1631,11 +1631,11 @@ mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
> comp = find_component(class, cpu);
> /* class has no component for this CPU */
> if (WARN_ON_ONCE(!comp))
> - return ERR_PTR(-EINVAL);
> + return;
>
> dom = kzalloc_node(sizeof(*dom), GFP_KERNEL, cpu_to_node(cpu));
> if (!dom)
> - return ERR_PTR(-ENOMEM);
> + return;
>
> if (r->alloc_capable) {
> dom->ctrl_comp = comp;
> @@ -1678,7 +1678,6 @@ mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
> }
> if (!any_mon_comp) {
> WARN_ON_ONCE(0);
> - err = -EFAULT;
> goto offline_ctrl_domain;
> }
>
> @@ -1694,7 +1693,7 @@ mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
> pr_debug("Skipped monitor domain online - no monitors\n");
> }
>
> - return dom;
> + return;
>
> offline_ctrl_domain:
> if (r->alloc_capable) {
> @@ -1703,9 +1702,6 @@ mpam_resctrl_alloc_domain(unsigned int cpu, struct mpam_resctrl_res *res)
> }
> free_domain:
> kfree(dom);
> - dom = ERR_PTR(err);
> -
> - return dom;
> }
>
> /*
> @@ -1757,7 +1753,7 @@ mpam_resctrl_get_domain_from_cpu(int cpu, struct mpam_resctrl_res *res)
> return mpam_resctrl_get_mon_domain_from_cpu(cpu);
> }
>
> -int mpam_resctrl_online_cpu(unsigned int cpu)
> +void mpam_resctrl_online_cpu(unsigned int cpu)
> {
> struct mpam_resctrl_res *res;
> enum resctrl_res_level rid;
> @@ -1772,9 +1768,13 @@ int mpam_resctrl_online_cpu(unsigned int cpu)
>
> dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
> if (!dom) {
> - dom = mpam_resctrl_alloc_domain(cpu, res);
> - if (IS_ERR(dom))
> - return PTR_ERR(dom);
> + /*
> + * On failure the CPU is left without a domain for this
> + * resource, which mpam_resctrl_offline_cpu() tolerates.
> + * resctrl_online_cpu() still adds the CPU to the default
> + * group because the CPU is online and runs tasks.
> + */
> + mpam_resctrl_alloc_domain(cpu, res);
> } else {
> if (r->alloc_capable) {
> struct rdt_ctrl_domain *ctrl_d = &dom->resctrl_ctrl_dom;
> @@ -1790,8 +1790,6 @@ int mpam_resctrl_online_cpu(unsigned int cpu)
> }
>
> resctrl_online_cpu(cpu);
> -
> - return 0;
> }
>
> void mpam_resctrl_offline_cpu(unsigned int cpu)
> @@ -1812,8 +1810,9 @@ void mpam_resctrl_offline_cpu(unsigned int cpu)
> if (!res->class)
> continue; // dummy resource
>
> + /* The domain may be missing if its setup failed. */
> dom = mpam_resctrl_get_domain_from_cpu(cpu, res);
> - if (WARN_ON_ONCE(!dom))
> + if (!dom)
> continue;
Reviewed-by: Jinjie Ruan <ruanjinjie@xxxxxxxxxx>
>
> if (r->alloc_capable) {
--
Best regards,
Jinjie