Loading kernel/printk/printk.c +54 −1 Original line number Diff line number Diff line Loading @@ -93,6 +93,12 @@ EXPORT_SYMBOL_GPL(console_drivers); */ int __read_mostly suppress_printk; /* * During panic, heavy printk by other CPUs can delay the * panic and risk deadlock on console resources. */ static int __read_mostly suppress_panic_printk; #ifdef CONFIG_LOCKDEP static struct lockdep_map console_lock_dep_map = { .name = "console_lock" Loading Loading @@ -258,6 +264,11 @@ static void __up_console_sem(unsigned long ip) } #define up_console_sem() __up_console_sem(_RET_IP_) static bool panic_in_progress(void) { return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID); } /* * This is used for debugging the mess that is the VT code by * keeping track if we have the console semaphore held. It's Loading Loading @@ -1844,6 +1855,16 @@ static int console_trylock_spinning(void) if (console_trylock()) return 1; /* * It's unsafe to spin once a panic has begun. If we are the * panic CPU, we may have already halted the owner of the * console_sem. If we are not the panic CPU, then we should * avoid taking console_sem, so the panic CPU has a better * chance of cleanly acquiring it later. */ if (panic_in_progress()) return 0; printk_safe_enter_irqsave(flags); raw_spin_lock(&console_owner_lock); Loading Loading @@ -2219,6 +2240,10 @@ asmlinkage int vprintk_emit(int facility, int level, if (unlikely(suppress_printk)) return 0; if (unlikely(suppress_panic_printk) && atomic_read(&panic_cpu) != raw_smp_processor_id()) return 0; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; Loading Loading @@ -2586,6 +2611,25 @@ static int have_callable_console(void) return 0; } /* * Return true when this CPU should unlock console_sem without pushing all * messages to the console. This reduces the chance that the console is * locked when the panic CPU tries to use it. */ static bool abandon_console_lock_in_panic(void) { if (!panic_in_progress()) return false; /* * We can use raw_smp_processor_id() here because it is impossible for * the task to be migrated to the panic_cpu, or away from it. If * panic_cpu has already been set, and we're not currently executing on * that CPU, then we never will be. */ return atomic_read(&panic_cpu) != raw_smp_processor_id(); } /* * Can we actually use the console at this time on this cpu? * Loading Loading @@ -2616,6 +2660,7 @@ void console_unlock(void) { static char ext_text[CONSOLE_EXT_LOG_MAX]; static char text[CONSOLE_LOG_MAX]; static int panic_console_dropped; unsigned long flags; bool do_cond_resched, retry; struct printk_info info; Loading Loading @@ -2670,6 +2715,10 @@ void console_unlock(void) if (console_seq != r.info->seq) { console_dropped += r.info->seq - console_seq; console_seq = r.info->seq; if (panic_in_progress() && panic_console_dropped++ > 10) { suppress_panic_printk = 1; pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); } } if (suppress_message_printing(r.info->level)) { Loading Loading @@ -2729,6 +2778,10 @@ void console_unlock(void) if (handover) return; /* Allow panic_cpu to take over the consoles safely */ if (abandon_console_lock_in_panic()) break; if (do_cond_resched) cond_resched(); } Loading @@ -2746,7 +2799,7 @@ void console_unlock(void) * flush, no worries. */ retry = prb_read_valid(prb, next_seq, NULL); if (retry && console_trylock()) if (retry && !abandon_console_lock_in_panic() && console_trylock()) goto again; } EXPORT_SYMBOL(console_unlock); Loading Loading
kernel/printk/printk.c +54 −1 Original line number Diff line number Diff line Loading @@ -93,6 +93,12 @@ EXPORT_SYMBOL_GPL(console_drivers); */ int __read_mostly suppress_printk; /* * During panic, heavy printk by other CPUs can delay the * panic and risk deadlock on console resources. */ static int __read_mostly suppress_panic_printk; #ifdef CONFIG_LOCKDEP static struct lockdep_map console_lock_dep_map = { .name = "console_lock" Loading Loading @@ -258,6 +264,11 @@ static void __up_console_sem(unsigned long ip) } #define up_console_sem() __up_console_sem(_RET_IP_) static bool panic_in_progress(void) { return unlikely(atomic_read(&panic_cpu) != PANIC_CPU_INVALID); } /* * This is used for debugging the mess that is the VT code by * keeping track if we have the console semaphore held. It's Loading Loading @@ -1844,6 +1855,16 @@ static int console_trylock_spinning(void) if (console_trylock()) return 1; /* * It's unsafe to spin once a panic has begun. If we are the * panic CPU, we may have already halted the owner of the * console_sem. If we are not the panic CPU, then we should * avoid taking console_sem, so the panic CPU has a better * chance of cleanly acquiring it later. */ if (panic_in_progress()) return 0; printk_safe_enter_irqsave(flags); raw_spin_lock(&console_owner_lock); Loading Loading @@ -2219,6 +2240,10 @@ asmlinkage int vprintk_emit(int facility, int level, if (unlikely(suppress_printk)) return 0; if (unlikely(suppress_panic_printk) && atomic_read(&panic_cpu) != raw_smp_processor_id()) return 0; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; in_sched = true; Loading Loading @@ -2586,6 +2611,25 @@ static int have_callable_console(void) return 0; } /* * Return true when this CPU should unlock console_sem without pushing all * messages to the console. This reduces the chance that the console is * locked when the panic CPU tries to use it. */ static bool abandon_console_lock_in_panic(void) { if (!panic_in_progress()) return false; /* * We can use raw_smp_processor_id() here because it is impossible for * the task to be migrated to the panic_cpu, or away from it. If * panic_cpu has already been set, and we're not currently executing on * that CPU, then we never will be. */ return atomic_read(&panic_cpu) != raw_smp_processor_id(); } /* * Can we actually use the console at this time on this cpu? * Loading Loading @@ -2616,6 +2660,7 @@ void console_unlock(void) { static char ext_text[CONSOLE_EXT_LOG_MAX]; static char text[CONSOLE_LOG_MAX]; static int panic_console_dropped; unsigned long flags; bool do_cond_resched, retry; struct printk_info info; Loading Loading @@ -2670,6 +2715,10 @@ void console_unlock(void) if (console_seq != r.info->seq) { console_dropped += r.info->seq - console_seq; console_seq = r.info->seq; if (panic_in_progress() && panic_console_dropped++ > 10) { suppress_panic_printk = 1; pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n"); } } if (suppress_message_printing(r.info->level)) { Loading Loading @@ -2729,6 +2778,10 @@ void console_unlock(void) if (handover) return; /* Allow panic_cpu to take over the consoles safely */ if (abandon_console_lock_in_panic()) break; if (do_cond_resched) cond_resched(); } Loading @@ -2746,7 +2799,7 @@ void console_unlock(void) * flush, no worries. */ retry = prb_read_valid(prb, next_seq, NULL); if (retry && console_trylock()) if (retry && !abandon_console_lock_in_panic() && console_trylock()) goto again; } EXPORT_SYMBOL(console_unlock); Loading