@@ -21,7 +21,7 @@ DEFINE_STATIC_KEY_FALSE(housekeeping_overridden);
2121EXPORT_SYMBOL_GPL (housekeeping_overridden );
2222
2323struct housekeeping {
24- cpumask_var_t cpumasks [HK_TYPE_MAX ];
24+ struct cpumask __rcu * cpumasks [HK_TYPE_MAX ];
2525 unsigned long flags ;
2626};
2727
@@ -33,17 +33,28 @@ bool housekeeping_enabled(enum hk_type type)
3333}
3434EXPORT_SYMBOL_GPL (housekeeping_enabled );
3535
36+ const struct cpumask * housekeeping_cpumask (enum hk_type type )
37+ {
38+ if (static_branch_unlikely (& housekeeping_overridden )) {
39+ if (housekeeping .flags & BIT (type )) {
40+ return rcu_dereference_check (housekeeping .cpumasks [type ], 1 );
41+ }
42+ }
43+ return cpu_possible_mask ;
44+ }
45+ EXPORT_SYMBOL_GPL (housekeeping_cpumask );
46+
3647int housekeeping_any_cpu (enum hk_type type )
3748{
3849 int cpu ;
3950
4051 if (static_branch_unlikely (& housekeeping_overridden )) {
4152 if (housekeeping .flags & BIT (type )) {
42- cpu = sched_numa_find_closest (housekeeping . cpumasks [ type ] , smp_processor_id ());
53+ cpu = sched_numa_find_closest (housekeeping_cpumask ( type ) , smp_processor_id ());
4354 if (cpu < nr_cpu_ids )
4455 return cpu ;
4556
46- cpu = cpumask_any_and_distribute (housekeeping . cpumasks [ type ] , cpu_online_mask );
57+ cpu = cpumask_any_and_distribute (housekeeping_cpumask ( type ) , cpu_online_mask );
4758 if (likely (cpu < nr_cpu_ids ))
4859 return cpu ;
4960 /*
@@ -59,28 +70,18 @@ int housekeeping_any_cpu(enum hk_type type)
5970}
6071EXPORT_SYMBOL_GPL (housekeeping_any_cpu );
6172
62- const struct cpumask * housekeeping_cpumask (enum hk_type type )
63- {
64- if (static_branch_unlikely (& housekeeping_overridden ))
65- if (housekeeping .flags & BIT (type ))
66- return housekeeping .cpumasks [type ];
67- return cpu_possible_mask ;
68- }
69- EXPORT_SYMBOL_GPL (housekeeping_cpumask );
70-
7173void housekeeping_affine (struct task_struct * t , enum hk_type type )
7274{
7375 if (static_branch_unlikely (& housekeeping_overridden ))
7476 if (housekeeping .flags & BIT (type ))
75- set_cpus_allowed_ptr (t , housekeeping . cpumasks [ type ] );
77+ set_cpus_allowed_ptr (t , housekeeping_cpumask ( type ) );
7678}
7779EXPORT_SYMBOL_GPL (housekeeping_affine );
7880
7981bool housekeeping_test_cpu (int cpu , enum hk_type type )
8082{
81- if (static_branch_unlikely (& housekeeping_overridden ))
82- if (housekeeping .flags & BIT (type ))
83- return cpumask_test_cpu (cpu , housekeeping .cpumasks [type ]);
83+ if (static_branch_unlikely (& housekeeping_overridden ) && housekeeping .flags & BIT (type ))
84+ return cpumask_test_cpu (cpu , housekeeping_cpumask (type ));
8485 return true;
8586}
8687EXPORT_SYMBOL_GPL (housekeeping_test_cpu );
@@ -96,20 +97,33 @@ void __init housekeeping_init(void)
9697
9798 if (housekeeping .flags & HK_FLAG_KERNEL_NOISE )
9899 sched_tick_offload_init ();
99-
100+ /*
101+ * Realloc with a proper allocator so that any cpumask update
102+ * can indifferently free the old version with kfree().
103+ */
100104 for_each_set_bit (type , & housekeeping .flags , HK_TYPE_MAX ) {
105+ struct cpumask * omask , * nmask = kmalloc (cpumask_size (), GFP_KERNEL );
106+
107+ if (WARN_ON_ONCE (!nmask ))
108+ return ;
109+
110+ omask = rcu_dereference (housekeeping .cpumasks [type ]);
111+
101112 /* We need at least one CPU to handle housekeeping work */
102- WARN_ON_ONCE (cpumask_empty (housekeeping .cpumasks [type ]));
113+ WARN_ON_ONCE (cpumask_empty (omask ));
114+ cpumask_copy (nmask , omask );
115+ RCU_INIT_POINTER (housekeeping .cpumasks [type ], nmask );
116+ memblock_free (omask , cpumask_size ());
103117 }
104118}
105119
106120static void __init housekeeping_setup_type (enum hk_type type ,
107121 cpumask_var_t housekeeping_staging )
108122{
123+ struct cpumask * mask = memblock_alloc_or_panic (cpumask_size (), SMP_CACHE_BYTES );
109124
110- alloc_bootmem_cpumask_var (& housekeeping .cpumasks [type ]);
111- cpumask_copy (housekeeping .cpumasks [type ],
112- housekeeping_staging );
125+ cpumask_copy (mask , housekeeping_staging );
126+ RCU_INIT_POINTER (housekeeping .cpumasks [type ], mask );
113127}
114128
115129static int __init housekeeping_setup (char * str , unsigned long flags )
@@ -162,7 +176,7 @@ static int __init housekeeping_setup(char *str, unsigned long flags)
162176
163177 for_each_set_bit (type , & iter_flags , HK_TYPE_MAX ) {
164178 if (!cpumask_equal (housekeeping_staging ,
165- housekeeping . cpumasks [ type ] )) {
179+ housekeeping_cpumask ( type ) )) {
166180 pr_warn ("Housekeeping: nohz_full= must match isolcpus=\n" );
167181 goto free_housekeeping_staging ;
168182 }
0 commit comments