aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2008-03-24 22:25:08 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-03-24 22:25:08 -0400
commit266c2e0abeca649fa6667a1a427ad1da507c6375 (patch)
tree9eb832b4c5de234cc789eae00a36a1337cefe451
parent5f7b703fe2be40db5a2bf136ac9e44cf5db267cc (diff)
Make printk() console semaphore accesses sensible
The printk() logic on when/how to get the console semaphore was unreadable, this splits the code up into a few helper functions and makes it easier to follow what is going on. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--kernel/printk.c83
1 files changed, 48 insertions, 35 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index 9adc2a473e6e..c46a20a19a15 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -616,6 +616,40 @@ asmlinkage int printk(const char *fmt, ...)
616/* cpu currently holding logbuf_lock */ 616/* cpu currently holding logbuf_lock */
617static volatile unsigned int printk_cpu = UINT_MAX; 617static volatile unsigned int printk_cpu = UINT_MAX;
618 618
619/*
620 * Can we actually use the console at this time on this cpu?
621 *
622 * Console drivers may assume that per-cpu resources have
623 * been allocated. So unless they're explicitly marked as
624 * being able to cope (CON_ANYTIME) don't call them until
625 * this CPU is officially up.
626 */
627static inline int can_use_console(unsigned int cpu)
628{
629 return cpu_online(cpu) || have_callable_console();
630}
631
632/*
633 * Try to get console ownership to actually show the kernel
634 * messages from a 'printk'. Return true (and with the
635 * console_semaphore held, and 'console_locked' set) if it
636 * is successful, false otherwise.
637 *
638 * This gets called with the 'logbuf_lock' spinlock held and
639 * interrupts disabled. It should return with 'lockbuf_lock'
640 * released but interrupts still disabled.
641 */
642static int acquire_console_semaphore_for_printk(unsigned int cpu)
643{
644 int retval = 0;
645
646 if (can_use_console(cpu))
647 retval = !try_acquire_console_sem();
648 printk_cpu = UINT_MAX;
649 spin_unlock(&logbuf_lock);
650 return retval;
651}
652
619const char printk_recursion_bug_msg [] = 653const char printk_recursion_bug_msg [] =
620 KERN_CRIT "BUG: recent printk recursion!\n"; 654 KERN_CRIT "BUG: recent printk recursion!\n";
621static int printk_recursion_bug; 655static int printk_recursion_bug;
@@ -725,43 +759,22 @@ asmlinkage int vprintk(const char *fmt, va_list args)
725 log_level_unknown = 1; 759 log_level_unknown = 1;
726 } 760 }
727 761
728 if (!down_trylock(&console_sem)) { 762 /*
729 /* 763 * Try to acquire and then immediately release the
730 * We own the drivers. We can drop the spinlock and 764 * console semaphore. The release will do all the
731 * let release_console_sem() print the text, maybe ... 765 * actual magic (print out buffers, wake up klogd,
732 */ 766 * etc).
733 console_locked = 1; 767 *
734 printk_cpu = UINT_MAX; 768 * The acquire_console_semaphore_for_printk() function
735 spin_unlock(&logbuf_lock); 769 * will release 'logbuf_lock' regardless of whether it
770 * actually gets the semaphore or not.
771 */
772 if (acquire_console_semaphore_for_printk(this_cpu))
773 release_console_sem();
736 774
737 /* 775 lockdep_on();
738 * Console drivers may assume that per-cpu resources have
739 * been allocated. So unless they're explicitly marked as
740 * being able to cope (CON_ANYTIME) don't call them until
741 * this CPU is officially up.
742 */
743 if (cpu_online(smp_processor_id()) || have_callable_console()) {
744 console_may_schedule = 0;
745 release_console_sem();
746 } else {
747 /* Release by hand to avoid flushing the buffer. */
748 console_locked = 0;
749 up(&console_sem);
750 }
751 lockdep_on();
752 raw_local_irq_restore(flags);
753 } else {
754 /*
755 * Someone else owns the drivers. We drop the spinlock, which
756 * allows the semaphore holder to proceed and to call the
757 * console drivers with the output which we just produced.
758 */
759 printk_cpu = UINT_MAX;
760 spin_unlock(&logbuf_lock);
761 lockdep_on();
762out_restore_irqs: 776out_restore_irqs:
763 raw_local_irq_restore(flags); 777 raw_local_irq_restore(flags);
764 }
765 778
766 preempt_enable(); 779 preempt_enable();
767 return printed_len; 780 return printed_len;