mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 10:45:49 +00:00
dump_stack: Do not get cpu_sync for panic CPU
[ Upstream commit 7412dc6d55
]
dump_stack() is called in panic(). If for some reason another CPU
is holding the printk_cpu_sync and is unable to release it, the
panic CPU will be unable to continue and print the stacktrace.
Since non-panic CPUs are not allowed to store new printk messages
anyway, there is no need to synchronize the stacktrace output in
a panic situation.
For the panic CPU, do not get the printk_cpu_sync because it is
not needed and avoids a potential deadlock scenario in panic().
Link: https://lore.kernel.org/lkml/ZcIGKU8sxti38Kok@alley
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20240207134103.1357162-15-john.ogness@linutronix.de
Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
365224c74c
commit
a63a05db13
@ -273,6 +273,8 @@ static inline void printk_trigger_flush(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool this_cpu_in_panic(void);
|
||||||
|
|
||||||
#ifdef CONFIG_SMP
|
#ifdef CONFIG_SMP
|
||||||
extern int __printk_cpu_sync_try_get(void);
|
extern int __printk_cpu_sync_try_get(void);
|
||||||
extern void __printk_cpu_sync_wait(void);
|
extern void __printk_cpu_sync_wait(void);
|
||||||
|
@ -130,7 +130,6 @@ struct printk_message {
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool other_cpu_in_panic(void);
|
bool other_cpu_in_panic(void);
|
||||||
bool this_cpu_in_panic(void);
|
|
||||||
bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
|
bool printk_get_next_message(struct printk_message *pmsg, u64 seq,
|
||||||
bool is_extended, bool may_supress);
|
bool is_extended, bool may_supress);
|
||||||
|
|
||||||
|
@ -96,15 +96,25 @@ static void __dump_stack(const char *log_lvl)
|
|||||||
*/
|
*/
|
||||||
asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
|
asmlinkage __visible void dump_stack_lvl(const char *log_lvl)
|
||||||
{
|
{
|
||||||
|
bool in_panic = this_cpu_in_panic();
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Permit this cpu to perform nested stack dumps while serialising
|
* Permit this cpu to perform nested stack dumps while serialising
|
||||||
* against other CPUs
|
* against other CPUs, unless this CPU is in panic.
|
||||||
|
*
|
||||||
|
* When in panic, non-panic CPUs are not permitted to store new
|
||||||
|
* printk messages so there is no need to synchronize the output.
|
||||||
|
* This avoids potential deadlock in panic() if another CPU is
|
||||||
|
* holding and unable to release the printk_cpu_sync.
|
||||||
*/
|
*/
|
||||||
printk_cpu_sync_get_irqsave(flags);
|
if (!in_panic)
|
||||||
|
printk_cpu_sync_get_irqsave(flags);
|
||||||
|
|
||||||
__dump_stack(log_lvl);
|
__dump_stack(log_lvl);
|
||||||
printk_cpu_sync_put_irqrestore(flags);
|
|
||||||
|
if (!in_panic)
|
||||||
|
printk_cpu_sync_put_irqrestore(flags);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(dump_stack_lvl);
|
EXPORT_SYMBOL(dump_stack_lvl);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user