Extend housekeeping_dereference_check() to validate all runtime-mutable types (HK_TYPE_DOMAIN, HK_TYPE_KERNEL_NOISE, HK_TYPE_MANAGED_IRQ), not only HK_TYPE_DOMAIN. Boot-only types (HK_TYPE_DOMAIN_BOOT) remain unchecked.
Add housekeeping_cpumask_rcu() for callers that already hold an RCU read lock. This variant uses rcu_dereference() without the lockdep annotation, avoiding false-positive lockdep warnings in RCU read-side critical sections. Use READ_ONCE() consistently when testing housekeeping.flags in paths that may race with housekeeping_update_types(). Signed-off-by: Jing Wu <[email protected]> Signed-off-by: Qiliang Yuan <[email protected]> --- include/linux/sched/isolation.h | 6 +++++ kernel/sched/isolation.c | 57 +++++++++++++++++++++++++++++++---------- 2 files changed, 49 insertions(+), 14 deletions(-) diff --git a/include/linux/sched/isolation.h b/include/linux/sched/isolation.h index eecbcbe802bd0..ed6e1c6980131 100644 --- a/include/linux/sched/isolation.h +++ b/include/linux/sched/isolation.h @@ -40,6 +40,7 @@ enum hk_type { DECLARE_STATIC_KEY_FALSE(housekeeping_overridden); extern int housekeeping_any_cpu(enum hk_type type); extern const struct cpumask *housekeeping_cpumask(enum hk_type type); +extern const struct cpumask *housekeeping_cpumask_rcu(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); @@ -87,6 +88,11 @@ static inline const struct cpumask *housekeeping_cpumask(enum hk_type type) return cpu_possible_mask; } +static inline const struct cpumask *housekeeping_cpumask_rcu(enum hk_type type) +{ + return cpu_possible_mask; +} + static inline bool housekeeping_enabled(enum hk_type type) { return false; diff --git a/kernel/sched/isolation.c b/kernel/sched/isolation.c index 4eca18cc5e8ce..3d5d3f12853c7 100644 --- a/kernel/sched/isolation.c +++ b/kernel/sched/isolation.c @@ -121,25 +121,40 @@ bool housekeeping_enabled(enum hk_type type) } EXPORT_SYMBOL_GPL(housekeeping_enabled); +/* + * Types that can change at runtime via cpuset isolated partitions. + * Boot-only types (DOMAIN_BOOT) are always safe to read without lockdep. + */ +static bool housekeeping_type_can_change(enum hk_type type) +{ + switch (type) { + case HK_TYPE_DOMAIN: + case HK_TYPE_KERNEL_NOISE: + case HK_TYPE_MANAGED_IRQ: + return true; + default: + return false; + } +} + static bool housekeeping_dereference_check(enum hk_type type) { - if (IS_ENABLED(CONFIG_LOCKDEP) && type == HK_TYPE_DOMAIN) { - /* Cpuset isn't even writable yet? */ - if (system_state <= SYSTEM_SCHEDULING) - return true; + if (!IS_ENABLED(CONFIG_LOCKDEP) || !housekeeping_type_can_change(type)) + return true; - /* CPU hotplug write locked, so cpuset partition can't be overwritten */ - if (IS_ENABLED(CONFIG_HOTPLUG_CPU) && lockdep_is_cpus_write_held()) - return true; + /* Cpuset isn't even writable yet? */ + if (system_state <= SYSTEM_SCHEDULING) + return true; - /* Cpuset lock held, partitions not writable */ - if (IS_ENABLED(CONFIG_CPUSETS) && lockdep_is_cpuset_held()) - return true; + /* CPU hotplug write locked, so cpuset partition can't be overwritten */ + if (IS_ENABLED(CONFIG_HOTPLUG_CPU) && lockdep_is_cpus_write_held()) + return true; - return false; - } + /* Cpuset lock held, partitions not writable */ + if (IS_ENABLED(CONFIG_CPUSETS) && lockdep_is_cpuset_held()) + return true; - return true; + return false; } static inline struct cpumask *housekeeping_cpumask_dereference(enum hk_type type) @@ -162,12 +177,26 @@ const struct cpumask *housekeeping_cpumask(enum hk_type type) } EXPORT_SYMBOL_GPL(housekeeping_cpumask); +const struct cpumask *housekeeping_cpumask_rcu(enum hk_type type) +{ + const struct cpumask *mask = NULL; + + if (static_branch_unlikely(&housekeeping_overridden)) { + if (READ_ONCE(housekeeping.flags) & BIT(type)) + mask = rcu_dereference(housekeeping.cpumasks[type]); + } + if (!mask) + mask = cpu_possible_mask; + return mask; +} +EXPORT_SYMBOL_GPL(housekeeping_cpumask_rcu); + int housekeeping_any_cpu(enum hk_type type) { int cpu; if (static_branch_unlikely(&housekeeping_overridden)) { - if (housekeeping.flags & BIT(type)) { + if (READ_ONCE(housekeeping.flags) & BIT(type)) { cpu = sched_numa_find_closest(housekeeping_cpumask(type), smp_processor_id()); if (cpu < nr_cpu_ids) return cpu; -- 2.43.0

