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

Fix locking bug in "acquire_console_semaphore_for_printk()"

When I cleaned up printk() and split up the printk locking logic in
commit 266c2e0abeca649fa6667a1a427ad1da507c6375 ("Make printk() console
semaphore accesses sensible") I had incorrectly moved the call to
have_callable_console() outside of the console semaphore.

That was buggy. The console semaphore protects the console_drivers list
that is used by have_callable_console().

Thanks go to Bongani Hlope who saw this as a hang on shutdown and reboot
and bisected the bug to the right commit, and tested this patch. See

http://lkml.org/lkml/2008/4/11/315

Bisected-and-tested-by: Bongani Hlope <bonganilinux@mweb.co.za>
Cc: Alexey Dobriyan <adobriyan@gmail.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>

+15 -2
+15 -2
kernel/printk.c
··· 643 643 { 644 644 int retval = 0; 645 645 646 - if (can_use_console(cpu)) 647 - retval = !try_acquire_console_sem(); 646 + if (!try_acquire_console_sem()) { 647 + retval = 1; 648 + 649 + /* 650 + * If we can't use the console, we need to release 651 + * the console semaphore by hand to avoid flushing 652 + * the buffer. We need to hold the console semaphore 653 + * in order to do this test safely. 654 + */ 655 + if (!can_use_console(cpu)) { 656 + console_locked = 0; 657 + up(&console_sem); 658 + retval = 0; 659 + } 660 + } 648 661 printk_cpu = UINT_MAX; 649 662 spin_unlock(&logbuf_lock); 650 663 return retval;