1 From ffdb28902359d97bbf24eaa25d7b1585a0f91142 Mon Sep 17 00:00:00 2001
2 From: Sasha Levin <sashal@kernel.org>
3 Date: Wed, 7 Feb 2024 14:47:03 +0106
4 Subject: dump_stack: Do not get cpu_sync for panic CPU
6 From: John Ogness <john.ogness@linutronix.de>
8 [ Upstream commit 7412dc6d55eed6b76180e40ac3601412ebde29bd ]
10 dump_stack() is called in panic(). If for some reason another CPU
11 is holding the printk_cpu_sync and is unable to release it, the
12 panic CPU will be unable to continue and print the stacktrace.
14 Since non-panic CPUs are not allowed to store new printk messages
15 anyway, there is no need to synchronize the stacktrace output in
18 For the panic CPU, do not get the printk_cpu_sync because it is
19 not needed and avoids a potential deadlock scenario in panic().
21 Link: https://lore.kernel.org/lkml/ZcIGKU8sxti38Kok@alley
22 Signed-off-by: John Ogness <john.ogness@linutronix.de>
23 Reviewed-by: Petr Mladek <pmladek@suse.com>
24 Link: https://lore.kernel.org/r/20240207134103.1357162-15-john.ogness@linutronix.de
25 Signed-off-by: Petr Mladek <pmladek@suse.com>
26 Signed-off-by: Sasha Levin <sashal@kernel.org>
28 include/linux/printk.h | 2 ++
29 kernel/printk/internal.h | 1 -
30 lib/dump_stack.c | 16 +++++++++++++---
31 3 files changed, 15 insertions(+), 4 deletions(-)
33 diff --git a/include/linux/printk.h b/include/linux/printk.h
34 index 8ef499ab3c1ed..955e31860095e 100644
35 --- a/include/linux/printk.h
36 +++ b/include/linux/printk.h
37 @@ -273,6 +273,8 @@ static inline void printk_trigger_flush(void)
41 +bool this_cpu_in_panic(void);
44 extern int __printk_cpu_sync_try_get(void);
45 extern void __printk_cpu_sync_wait(void);
46 diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h
47 index ac2d9750e5f81..6c2afee5ef620 100644
48 --- a/kernel/printk/internal.h
49 +++ b/kernel/printk/internal.h
50 @@ -130,7 +130,6 @@ struct printk_message {
53 bool other_cpu_in_panic(void);
54 -bool this_cpu_in_panic(void);
55 bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
56 bool is_extended, bool may_supress);
58 diff --git a/lib/dump_stack.c b/lib/dump_stack.c
59 index 83471e81501a7..222c6d6c8281a 100644
60 --- a/lib/dump_stack.c
61 +++ b/lib/dump_stack.c
62 @@ -96,15 +96,25 @@ static void __dump_stack(const char *log_lvl)
64 asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
66 + bool in_panic = this_cpu_in_panic();
70 * Permit this cpu to perform nested stack dumps while serialising
71 - * against other CPUs
72 + * against other CPUs, unless this CPU is in panic.
74 + * When in panic, non-panic CPUs are not permitted to store new
75 + * printk messages so there is no need to synchronize the output.
76 + * This avoids potential deadlock in panic() if another CPU is
77 + * holding and unable to release the printk_cpu_sync.
79 - printk_cpu_sync_get_irqsave(flags);
81 + printk_cpu_sync_get_irqsave(flags);
83 __dump_stack(log_lvl);
84 - printk_cpu_sync_put_irqrestore(flags);
87 + printk_cpu_sync_put_irqrestore(flags);
89 EXPORT_SYMBOL(dump_stack_lvl);