[RFC PATCH 3/3] sched/topology: Tear down domains without active domain housekeeping CPUs
Guopeng Zhang <[email protected]> Wed, 22 Jul 2026 19:52:38 +0800
| Newsgroups | org.kernel.vger.cgroups,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
From: Guopeng Zhang <[email protected]> During suspend, freeze_secondary_cpus() takes every CPU except the primary offline. If the primary CPU is excluded from HK_TYPE_DOMAIN, offlining the last domain housekeeping CPU leaves no active CPU from which to build the fallback scheduler domain. The frozen CPU-hotplug callback nevertheless requests one domain by passing a non-zero domain count with a NULL domain array. partition_sched_domains_locked() then constructs the fallback span from cpu_active_mask and housekeeping_cpumask(HK_TYPE_DOMAIN), which is empty. build_sched_domains() warns about the empty span, followed by a general protection fault in build_perf_domains(). Make cpuset_reset_sched_domains(), including its !CONFIG_CPUSETS stub, request zero domains when no active HK_TYPE_DOMAIN CPU remains. Distinguish that explicit zero-domain request from a non-zero request with a NULL domain array, for which the existing fallback-domain behavior must be retained. Fixes: d35be8bab9b0 ("CPU hotplug, cpusets, suspend: Don't modify cpusets during suspend/resume") Signed-off-by: Guopeng Zhang <[email protected]> --- include/linux/cpuset.h | 7 ++++++- kernel/cgroup/cpuset.c | 6 +++++- kernel/sched/topology.c | 9 ++++----- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/linux/cpuset.h b/include/linux/cpuset.h index a67ba1b32d16..461ba4876a8e 100644 --- a/include/linux/cpuset.h +++ b/include/linux/cpuset.h @@ -10,6 +10,7 @@ */ #include <linux/sched.h> +#include <linux/sched/isolation.h> #include <linux/sched/topology.h> #include <linux/sched/task.h> #include <linux/cpumask.h> @@ -284,7 +285,11 @@ static inline void rebuild_sched_domains(void) static inline void cpuset_reset_sched_domains(void) { - partition_sched_domains(1, NULL, NULL); + if (cpumask_intersects(cpu_active_mask, + housekeeping_cpumask(HK_TYPE_DOMAIN))) + partition_sched_domains(1, NULL, NULL); + else + partition_sched_domains(0, NULL, NULL); } static inline void cpuset_print_current_mems_allowed(void) diff --git a/kernel/cgroup/cpuset.c b/kernel/cgroup/cpuset.c index 03e82d6026f5..1e66723e01b4 100644 --- a/kernel/cgroup/cpuset.c +++ b/kernel/cgroup/cpuset.c @@ -1076,7 +1076,11 @@ void rebuild_sched_domains(void) void cpuset_reset_sched_domains(void) { mutex_lock(&cpuset_mutex); - partition_sched_domains(1, NULL, NULL); + if (cpumask_intersects(cpu_active_mask, + housekeeping_cpumask(HK_TYPE_DOMAIN))) + partition_sched_domains(1, NULL, NULL); + else + partition_sched_domains(0, NULL, NULL); mutex_unlock(&cpuset_mutex); } diff --git a/kernel/sched/topology.c b/kernel/sched/topology.c index 622e2e01974c..e8d34cb1ed84 100644 --- a/kernel/sched/topology.c +++ b/kernel/sched/topology.c @@ -3365,9 +3365,8 @@ static int dattrs_equal(struct sched_domain_attr *cur, int idx_cur, * and partition_sched_domains() will fallback to the single partition * 'fallback_doms', it also forces the domains to be rebuilt. * - * If doms_new == NULL it will be replaced with cpu_online_mask. - * ndoms_new == 0 is a special case for destroying existing domains, - * and it will not create the default domain. + * ndoms_new == 0 and doms_new == NULL is a special case for destroying + * existing domains, and it will not create the default domain. * * Call with hotplug lock and sched_domains_mutex held */ @@ -3387,7 +3386,7 @@ static void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new if (new_topology) asym_cpu_capacity_scan(); - if (!doms_new) { + if (ndoms_new && !doms_new) { WARN_ON_ONCE(dattr_new); n = 0; doms_new = alloc_sched_domains(1); @@ -3414,7 +3413,7 @@ static void partition_sched_domains_locked(int ndoms_new, cpumask_var_t doms_new } n = ndoms_cur; - if (!doms_new) { + if (ndoms_new && !doms_new) { n = 0; doms_new = &fallback_doms; cpumask_and(doms_new[0], cpu_active_mask, -- 2.43.0