Skip to content
This repository was archived by the owner on Oct 31, 2024. It is now read-only.

Commit a4a05ce

Browse files
stkidgregkh
authored andcommitted
tracing/timerlat: Drop interface_lock in stop_kthread()
commit b484a02 upstream. stop_kthread() is the offline callback for "trace/osnoise:online", since commit 5bfbcd1 ("tracing/timerlat: Add interface_lock around clearing of kthread in stop_kthread()"), the following ABBA deadlock scenario is introduced: T1 | T2 [BP] | T3 [AP] osnoise_hotplug_workfn() | work_for_cpu_fn() | cpuhp_thread_fun() | _cpu_down() | osnoise_cpu_die() mutex_lock(&interface_lock) | | stop_kthread() | cpus_write_lock() | mutex_lock(&interface_lock) cpus_read_lock() | cpuhp_kick_ap() | As the interface_lock here in just for protecting the "kthread" field of the osn_var, use xchg() instead to fix this issue. Also use for_each_online_cpu() back in stop_per_cpu_kthreads() as it can take cpu_read_lock() again. Cc: stable@vger.kernel.org Cc: Masami Hiramatsu <mhiramat@kernel.org> Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com> Link: https://lore.kernel.org/20240924094515.3561410-3-liwei391@huawei.com Fixes: 5bfbcd1 ("tracing/timerlat: Add interface_lock around clearing of kthread in stop_kthread()") Signed-off-by: Wei Li <liwei391@huawei.com> Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 79250de commit a4a05ce

File tree

1 file changed

+6
-7
lines changed

1 file changed

+6
-7
lines changed

kernel/trace/trace_osnoise.c

+6-7
Original file line numberDiff line numberDiff line change
@@ -1953,12 +1953,8 @@ static void stop_kthread(unsigned int cpu)
19531953
{
19541954
struct task_struct *kthread;
19551955

1956-
mutex_lock(&interface_lock);
1957-
kthread = per_cpu(per_cpu_osnoise_var, cpu).kthread;
1956+
kthread = xchg_relaxed(&(per_cpu(per_cpu_osnoise_var, cpu).kthread), NULL);
19581957
if (kthread) {
1959-
per_cpu(per_cpu_osnoise_var, cpu).kthread = NULL;
1960-
mutex_unlock(&interface_lock);
1961-
19621958
if (cpumask_test_and_clear_cpu(cpu, &kthread_cpumask) &&
19631959
!WARN_ON(!test_bit(OSN_WORKLOAD, &osnoise_options))) {
19641960
kthread_stop(kthread);
@@ -1972,7 +1968,6 @@ static void stop_kthread(unsigned int cpu)
19721968
put_task_struct(kthread);
19731969
}
19741970
} else {
1975-
mutex_unlock(&interface_lock);
19761971
/* if no workload, just return */
19771972
if (!test_bit(OSN_WORKLOAD, &osnoise_options)) {
19781973
/*
@@ -1994,8 +1989,12 @@ static void stop_per_cpu_kthreads(void)
19941989
{
19951990
int cpu;
19961991

1997-
for_each_possible_cpu(cpu)
1992+
cpus_read_lock();
1993+
1994+
for_each_online_cpu(cpu)
19981995
stop_kthread(cpu);
1996+
1997+
cpus_read_unlock();
19991998
}
20001999

20012000
/*

0 commit comments

Comments
 (0)