Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'printk-for-5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux

Pull printk fixes from Petr Mladek:
"Make the global console_sem available for CPU that is handling panic()
or shutdown.

This is an old problem when an existing console lock owner might block
console output, but it became more visible with the kthreads"

* tag 'printk-for-5.19-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux:
printk: Wait for the global console lock when the system is going down
printk: Block console kthreads when direct printing will be required

+50 -1
+5
include/linux/printk.h
··· 173 173 extern void printk_prefer_direct_exit(void); 174 174 175 175 extern bool pr_flush(int timeout_ms, bool reset_on_progress); 176 + extern void try_block_console_kthreads(int timeout_ms); 176 177 177 178 /* 178 179 * Please don't use printk_ratelimit(), because it shares ratelimiting state ··· 236 235 static inline bool pr_flush(int timeout_ms, bool reset_on_progress) 237 236 { 238 237 return true; 238 + } 239 + 240 + static inline void try_block_console_kthreads(int timeout_ms) 241 + { 239 242 } 240 243 241 244 static inline int printk_ratelimit(void)
+2
kernel/panic.c
··· 297 297 * unfortunately means it may not be hardened to work in a 298 298 * panic situation. 299 299 */ 300 + try_block_console_kthreads(10000); 300 301 smp_send_stop(); 301 302 } else { 302 303 /* ··· 305 304 * kmsg_dump, we will need architecture dependent extra 306 305 * works in addition to stopping other CPUs. 307 306 */ 307 + try_block_console_kthreads(10000); 308 308 crash_smp_send_stop(); 309 309 } 310 310
+2
kernel/printk/internal.h
··· 20 20 LOG_CONT = 8, /* text is a fragment of a continuation line */ 21 21 }; 22 22 23 + extern bool block_console_kthreads; 24 + 23 25 __printf(4, 0) 24 26 int vprintk_store(int facility, int level, 25 27 const struct dev_printk_info *dev_info,
+7 -1
kernel/printk/printk.c
··· 250 250 #define console_kthread_printing_exit() \ 251 251 atomic_dec(&console_kthreads_active) 252 252 253 + /* Block console kthreads to avoid processing new messages. */ 254 + bool block_console_kthreads; 255 + 253 256 /* 254 257 * Helper macros to handle lockdep when locking/unlocking console_sem. We use 255 258 * macros instead of functions so that _RET_IP_ contains useful information. ··· 3732 3729 return true; 3733 3730 3734 3731 if (con->blocked || 3735 - console_kthreads_atomically_blocked()) { 3732 + console_kthreads_atomically_blocked() || 3733 + block_console_kthreads || 3734 + system_state > SYSTEM_RUNNING || 3735 + oops_in_progress) { 3736 3736 return false; 3737 3737 } 3738 3738
+32
kernel/printk/printk_safe.c
··· 8 8 #include <linux/smp.h> 9 9 #include <linux/cpumask.h> 10 10 #include <linux/printk.h> 11 + #include <linux/console.h> 11 12 #include <linux/kprobes.h> 13 + #include <linux/delay.h> 12 14 13 15 #include "internal.h" 14 16 ··· 52 50 return vprintk_default(fmt, args); 53 51 } 54 52 EXPORT_SYMBOL(vprintk); 53 + 54 + /** 55 + * try_block_console_kthreads() - Try to block console kthreads and 56 + * make the global console_lock() avaialble 57 + * 58 + * @timeout_ms: The maximum time (in ms) to wait. 59 + * 60 + * Prevent console kthreads from starting processing new messages. Wait 61 + * until the global console_lock() become available. 62 + * 63 + * Context: Can be called in any context. 64 + */ 65 + void try_block_console_kthreads(int timeout_ms) 66 + { 67 + block_console_kthreads = true; 68 + 69 + /* Do not wait when the console lock could not be safely taken. */ 70 + if (this_cpu_read(printk_context) || in_nmi()) 71 + return; 72 + 73 + while (timeout_ms > 0) { 74 + if (console_trylock()) { 75 + console_unlock(); 76 + return; 77 + } 78 + 79 + udelay(1000); 80 + timeout_ms -= 1; 81 + } 82 + }
+2
kernel/reboot.c
··· 82 82 { 83 83 blocking_notifier_call_chain(&reboot_notifier_list, SYS_RESTART, cmd); 84 84 system_state = SYSTEM_RESTART; 85 + try_block_console_kthreads(10000); 85 86 usermodehelper_disable(); 86 87 device_shutdown(); 87 88 } ··· 271 270 blocking_notifier_call_chain(&reboot_notifier_list, 272 271 (state == SYSTEM_HALT) ? SYS_HALT : SYS_POWER_OFF, NULL); 273 272 system_state = state; 273 + try_block_console_kthreads(10000); 274 274 usermodehelper_disable(); 275 275 device_shutdown(); 276 276 }