diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-15 16:09:54 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2008-04-15 16:09:54 -0400 |
commit | 093a07e2fdfaddab7fc7d4adc76cc569c86603d7 (patch) | |
tree | baaa4d86680347a0687ebfbe133d7b253b88102c /kernel/printk.c | |
parent | 0de19a456cb59106420864927fdec152310f70b6 (diff) |
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>
Diffstat (limited to 'kernel/printk.c')
-rw-r--r-- | kernel/printk.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index c46a20a19a15..bdd4ea8c3f2b 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -643,8 +643,21 @@ static int acquire_console_semaphore_for_printk(unsigned int cpu) | |||
643 | { | 643 | { |
644 | int retval = 0; | 644 | int retval = 0; |
645 | 645 | ||
646 | if (can_use_console(cpu)) | 646 | if (!try_acquire_console_sem()) { |
647 | retval = !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 | printk_cpu = UINT_MAX; | 661 | printk_cpu = UINT_MAX; |
649 | spin_unlock(&logbuf_lock); | 662 | spin_unlock(&logbuf_lock); |
650 | return retval; | 663 | return retval; |