The current housekeeping management logic in kernel/sched/isolation.c is heavily tied to the boot process. Functions like housekeeping_setup() and housekeeping_init() are marked with __init, and they use alloc_bootmem_cpumask_var() for memory allocation. This prevents any runtime reconfiguration of housekeeping masks.
Refactor the infrastructure to support dynamic updates: 1. Remove __init markers from core functions to keep them available after boot. 2. Replace bootmem allocation with runtime-safe alloc_cpumask_var() using appropriate GFP flags (GFP_NOWAIT during early boot, GFP_KERNEL at runtime). 3. Introduce housekeeping_mutex to protect the global state during concurrent updates. 4. Update include/linux/sched/isolation.h to reflect function signature changes. This lays the foundation for runtime isolation reconfiguration without requiring a system reboot. Signed-off-by: Qiliang Yuan <[email protected]> Signed-off-by: Qiliang Yuan <[email protected]> --- include/linux/sched/isolation.h | 2 +- kernel/sched/isolation.c | 32 ++++++++++++++++++++++++-------- 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h index d8501f4709b5..cecb80b09120 100644 --- a/include/linux/sched/isolation.h +++ b/include/linux/sched/isolation.h @@ -31,7 +31,7 @@ extern const struct cpumask *housekeeping_cpumask(enum hk_type type); extern bool housekeeping_enabled(enum hk_type type); extern void housekeeping_affine(struct task_struct *t, enum hk_type type); extern bool housekeeping_test_cpu(int cpu, enum hk_type type); -extern void __init housekeeping_init(void); +extern void housekeeping_init(void); #else diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c index 3ad0d6df6a0a..811bf6cbe68d 100644 --- a/kernel/sched/isolation.c +++ b/kernel/sched/isolation.c @@ -8,6 +8,7 @@ * */ #include <linux/sched/isolation.h> +#include <linux/mutex.h> #include "sched.h" enum hk_flags { @@ -16,6 +17,7 @@ enum hk_flags { HK_FLAG_KERNEL_NOISE = BIT(HK_TYPE_KERNEL_NOISE), }; +static DEFINE_MUTEX(housekeeping_mutex); DEFINE_STATIC_KEY_FALSE(housekeeping_overridden); EXPORT_SYMBOL_GPL(housekeeping_overridden); @@ -84,7 +86,7 @@ bool housekeeping_test_cpu(int cpu, enum hk_type type) } EXPORT_SYMBOL_GPL(housekeeping_test_cpu); -void __init housekeeping_init(void) +void housekeeping_init(void) { enum hk_type type; @@ -102,20 +104,30 @@ void __init housekeeping_init(void) } } -static void __init housekeeping_setup_type(enum hk_type type, +static void housekeeping_setup_type(enum hk_type type, cpumask_var_t housekeeping_staging) { + unsigned int gfp = GFP_KERNEL; + + if (system_state < SYSTEM_RUNNING) + gfp = GFP_NOWAIT; + + if (!housekeeping.cpumasks[type]) + alloc_cpumask_var(&housekeeping.cpumasks[type], gfp); - alloc_bootmem_cpumask_var(&housekeeping.cpumasks[type]); cpumask_copy(housekeeping.cpumasks[type], housekeeping_staging); } -static int __init housekeeping_setup(char *str, unsigned long flags) +static int housekeeping_setup(char *str, unsigned long flags) { cpumask_var_t non_housekeeping_mask, housekeeping_staging; unsigned int first_cpu; int err = 0; + unsigned int gfp = GFP_KERNEL; + + if (system_state < SYSTEM_RUNNING) + gfp = GFP_NOWAIT; if ((flags & HK_FLAG_KERNEL_NOISE) && !(housekeeping.flags & HK_FLAG_KERNEL_NOISE)) { if (!IS_ENABLED(CONFIG_NO_HZ_FULL)) { @@ -125,13 +137,17 @@ static int __init housekeeping_setup(char *str, unsigned long flags) } } - alloc_bootmem_cpumask_var(&non_housekeeping_mask); + if (!alloc_cpumask_var(&non_housekeeping_mask, gfp)) + return 0; + if (cpulist_parse(str, non_housekeeping_mask) < 0) { pr_warn("Housekeeping: nohz_full= or isolcpus= incorrect CPU range\n"); goto free_non_housekeeping_mask; } - alloc_bootmem_cpumask_var(&housekeeping_staging); + if (!alloc_cpumask_var(&housekeeping_staging, gfp)) + goto free_non_housekeeping_mask; + cpumask_andnot(housekeeping_staging, cpu_possible_mask, non_housekeeping_mask); @@ -203,9 +219,9 @@ static int __init housekeeping_setup(char *str, unsigned long flags) err = 1; free_housekeeping_staging: - free_bootmem_cpumask_var(housekeeping_staging); + free_cpumask_var(housekeeping_staging); free_non_housekeeping_mask: - free_bootmem_cpumask_var(non_housekeeping_mask); + free_cpumask_var(non_housekeeping_mask); return err; } -- 2.51.0

