On 21/10/16 13:50, Petr Mladek wrote:
kdb_trap_printk allows to pass normal printk() messages to kdb via
vkdb_printk(). For example, it is used to get backtrace using
the classic show_stack(), see kdb_show_stack().
vkdb_printf() tries to avoid a potential infinite loop by disabling
the trap. But this approach is racy, for example:
CPU1 CPU2
vkdb_printf()
// assume that kdb_trap_printk == 0
saved_trap_printk = kdb_trap_printk;
kdb_trap_printk = 0;
kdb_show_stack()
kdb_trap_printk++;
When kdb is running any of the commands that use kdb_trap_printk there
is a single active CPU and the other CPUs should be in a holding pen
inside kgdb_cpu_enter().
The only time this is violated is when there is a timeout waiting for
the other CPUs to report to the holding pen.
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index d5e397315473..db73e33811e7 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1941,7 +1941,9 @@ int vprintk_default(const char *fmt, va_list args)
int r;
#ifdef CONFIG_KGDB_KDB
- if (unlikely(kdb_trap_printk)) {
+ /* Allow to pass printk() to kdb but avoid a recursion. */
+ if (unlikely(kdb_trap_printk &&
+ kdb_printf_cpu != smp_processor_id())) {
Firstly, why !=?
Secondly, if kdb_trap_printk is set and the "wrong" CPU calls printk
then we have an opportunity to trap a rouge processor in the holding pen
meaning the test should probably be part of vkdb_printk() anyway.
Daniel.