Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sched/isolation: Force housekeeping if isolcpus and nohz_full don't leave any

Currently the user can set up isolcpus and nohz_full in such a way that
leaves no housekeeping CPU (i.e. no CPU that is neither domain isolated
nor nohz full). This can be a problem for other subsystems (e.g. the
timer wheel imgration).

Prevent this configuration by invalidating the last setting in case the
union of isolcpus (domain) and nohz_full covers all CPUs.

Signed-off-by: Gabriele Monaco <gmonaco@redhat.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Waiman Long <longman@redhat.com>
Reviewed-by: Frederic Weisbecker <frederic@kernel.org>
Link: https://patch.msgid.link/20251120145653.296659-6-gmonaco@redhat.com

authored by

Gabriele Monaco and committed by
Thomas Gleixner
185bccc7 22f8e416

+23
+23
kernel/sched/isolation.c
··· 167 167 } 168 168 } 169 169 170 + /* 171 + * Check the combination of nohz_full and isolcpus=domain, 172 + * necessary to avoid problems with the timer migration 173 + * hierarchy. managed_irq is ignored by this check since it 174 + * isn't considered in the timer migration logic. 175 + */ 176 + iter_flags = housekeeping.flags & (HK_FLAG_KERNEL_NOISE | HK_FLAG_DOMAIN); 177 + type = find_first_bit(&iter_flags, HK_TYPE_MAX); 178 + /* 179 + * Pass the check if none of these flags were previously set or 180 + * are not in the current selection. 181 + */ 182 + iter_flags = flags & (HK_FLAG_KERNEL_NOISE | HK_FLAG_DOMAIN); 183 + first_cpu = (type == HK_TYPE_MAX || !iter_flags) ? 0 : 184 + cpumask_first_and_and(cpu_present_mask, 185 + housekeeping_staging, housekeeping.cpumasks[type]); 186 + if (first_cpu >= min(nr_cpu_ids, setup_max_cpus)) { 187 + pr_warn("Housekeeping: must include one present CPU " 188 + "neither in nohz_full= nor in isolcpus=domain, " 189 + "ignoring setting %s\n", str); 190 + goto free_housekeeping_staging; 191 + } 192 + 170 193 iter_flags = flags & ~housekeeping.flags; 171 194 172 195 for_each_set_bit(type, &iter_flags, HK_TYPE_MAX)