The watchdog is initialized at boot to run on all housekeeping CPUs (HK_TYPE_KERNEL_NOISE). When a cpuset isolated partition removes CPUs from that mask at runtime, watchdog continues running on those CPUs because nothing updates watchdog_cpumask.
Save the boot-time watchdog_cpumask as watchdog_cpumask_boot, which captures the user's intended coverage (possibly narrowed via kernel parameter or sysctl) before any runtime isolation. Introduce lockup_detector_hk_update() which intersects this boot snapshot with the current HK_TYPE_KERNEL_NOISE mask and reconfigures the detector. This ensures that isolated CPUs are excluded while honoring any manual narrowing the admin applied at or after boot. lockup_detector_hk_update() snapshots the RCU-protected housekeeping mask under rcu_read_lock(), then updates watchdog_cpumask and calls __lockup_detector_reconfigure() under watchdog_mutex, matching the same locking discipline used by proc_watchdog_cpumask(). Co-developed-by: Qiliang Yuan <[email protected]> Signed-off-by: Qiliang Yuan <[email protected]> Signed-off-by: Jing Wu <[email protected]> --- include/linux/nmi.h | 2 ++ kernel/watchdog.c | 24 ++++++++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/include/linux/nmi.h b/include/linux/nmi.h index bc1162895f355..0bbe562de67b7 100644 --- a/include/linux/nmi.h +++ b/include/linux/nmi.h @@ -37,6 +37,7 @@ extern int sysctl_hardlockup_all_cpu_backtrace; static inline void lockup_detector_init(void) { } static inline void lockup_detector_retry_init(void) { } static inline void lockup_detector_soft_poweroff(void) { } +static inline void lockup_detector_hk_update(void) { } #endif /* !CONFIG_LOCKUP_DETECTOR */ #ifdef CONFIG_SOFTLOCKUP_DETECTOR @@ -120,6 +121,7 @@ void watchdog_hardlockup_enable(unsigned int cpu); void watchdog_hardlockup_disable(unsigned int cpu); void lockup_detector_reconfigure(void); +void lockup_detector_hk_update(void); #ifdef CONFIG_HARDLOCKUP_DETECTOR_BUDDY void watchdog_buddy_check_hardlockup(int hrtimer_interrupts); diff --git a/kernel/watchdog.c b/kernel/watchdog.c index c18c3e9781d7b..26463f6d3a39d 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -53,6 +53,8 @@ static int __read_mostly watchdog_hardlockup_available; struct cpumask watchdog_cpumask __read_mostly; unsigned long *watchdog_cpumask_bits = cpumask_bits(&watchdog_cpumask); +/* Boot snapshot: user's intended watchdog mask before any runtime isolation. */ +static struct cpumask watchdog_cpumask_boot __ro_after_init; #ifdef CONFIG_HARDLOCKUP_DETECTOR @@ -1348,6 +1350,27 @@ static void __init lockup_detector_delay_init(struct work_struct *work) lockup_detector_setup(); } +void lockup_detector_hk_update(void) +{ + cpumask_var_t new_mask; + + if (!alloc_cpumask_var(&new_mask, GFP_KERNEL)) + return; + + rcu_read_lock(); + cpumask_and(new_mask, &watchdog_cpumask_boot, + housekeeping_cpumask_rcu(HK_TYPE_KERNEL_NOISE)); + rcu_read_unlock(); + + mutex_lock(&watchdog_mutex); + cpumask_copy(&watchdog_cpumask, new_mask); + __lockup_detector_reconfigure(false); + mutex_unlock(&watchdog_mutex); + + free_cpumask_var(new_mask); +} +EXPORT_SYMBOL_GPL(lockup_detector_hk_update); + /* * lockup_detector_retry_init - retry init lockup detector if possible. * @@ -1390,6 +1413,7 @@ void __init lockup_detector_init(void) cpumask_copy(&watchdog_cpumask, housekeeping_cpumask(HK_TYPE_KERNEL_NOISE)); + cpumask_copy(&watchdog_cpumask_boot, &watchdog_cpumask); if (!watchdog_hardlockup_probe()) watchdog_hardlockup_available = true; -- 2.43.0

