mirror of
https://github.com/linux-msm/laptops-kernel.git
synced 2026-08-13 14:19:53 -07:00
smp: Alloc percpu csd data in smpcfd_prepare_cpu() only once
smp_call_function_many_cond() uses per-CPU CSD objects when queueing callbacks to remote CPUs, and the wait path later dereferences those CSDs from csd_lock_wait(). Making the wait path preemptible allows the initiating task to be preempted or migrated before it waits for completion. A target CPU can be offlined in that window. If smpcfd_dead_cpu() frees the target CPU's per-CPU CSD storage, csd_lock_wait() can later dereference freed memory. One way to protect the CSD storage is to free it via RCU or after a synchronization step in the CPU offline path, but that would add unnecessary complexity and can delay CPU shutdown. Allocate the per-CPU CSD storage the first time a CPU comes up and keep it allocated when the CPU is offlined. This allows csd_lock_wait() to access the CSD even when the target CPU is offlined after preemption is re-enabled and before the wait is invoked. Signed-off-by: Chuyi Zhou <zhouchuyi@bytedance.com> Signed-off-by: Thomas Gleixner <tglx@kernel.org> Tested-by: Paul E. McKenney <paulmck@kernel.org> Reviewed-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de> Acked-by: Muchun Song <muchun.song@linux.dev> Link: https://patch.msgid.link/20260709122933.4021501-6-zhouchuyi@bytedance.com
This commit is contained in:
committed by
Thomas Gleixner
parent
9a560af15f
commit
9f483e5b2f
+8
-2
@@ -64,7 +64,14 @@ int smpcfd_prepare_cpu(unsigned int cpu)
|
||||
free_cpumask_var(cfd->cpumask);
|
||||
return -ENOMEM;
|
||||
}
|
||||
cfd->csd = alloc_percpu(call_single_data_t);
|
||||
|
||||
/*
|
||||
* Allocate the per-CPU CSD the first time a CPU comes up. It is
|
||||
* not freed when the CPU is offlined, so csd_lock_wait() can access
|
||||
* it even when the CPU was offlined after preemption was re-enabled.
|
||||
*/
|
||||
if (!cfd->csd)
|
||||
cfd->csd = alloc_percpu(call_single_data_t);
|
||||
if (!cfd->csd) {
|
||||
free_cpumask_var(cfd->cpumask);
|
||||
free_cpumask_var(cfd->cpumask_ipi);
|
||||
@@ -80,7 +87,6 @@ int smpcfd_dead_cpu(unsigned int cpu)
|
||||
|
||||
free_cpumask_var(cfd->cpumask);
|
||||
free_cpumask_var(cfd->cpumask_ipi);
|
||||
free_percpu(cfd->csd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user