aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2014-06-04 19:11:37 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-04 19:54:17 -0400
commit939f04bec1a4ef6ba4370b0f34b01decc844b1b1 (patch)
tree1da1d9914daa6d19813589502f458c7a24e737e0 /kernel
parentbd8d7cf5b8410fe98eba06a9aaa90efe88815d8a (diff)
printk: enable interrupts before calling console_trylock_for_printk()
We need interrupts disabled when calling console_trylock_for_printk() only so that cpu id we pass to can_use_console() remains valid (for other things console_sem provides all the exclusion we need and deadlocks on console_sem due to interrupts are impossible because we use down_trylock()). However if we are rescheduled, we are guaranteed to run on an online cpu so we can easily just get the cpu id in can_use_console(). We can lose a bit of performance when we enable interrupts in vprintk_emit() and then disable them again in console_unlock() but OTOH it can somewhat reduce interrupt latency caused by console_unlock() especially since later in the patch series we will want to spin on console_sem in console_trylock_for_printk(). Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/printk/printk.c29
1 files changed, 18 insertions, 11 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 5ba37f813723..4e22230f1f6c 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1418,10 +1418,9 @@ static int have_callable_console(void)
1418/* 1418/*
1419 * Can we actually use the console at this time on this cpu? 1419 * Can we actually use the console at this time on this cpu?
1420 * 1420 *
1421 * Console drivers may assume that per-cpu resources have 1421 * Console drivers may assume that per-cpu resources have been allocated. So
1422 * been allocated. So unless they're explicitly marked as 1422 * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
1423 * being able to cope (CON_ANYTIME) don't call them until 1423 * call them until this CPU is officially up.
1424 * this CPU is officially up.
1425 */ 1424 */
1426static inline int can_use_console(unsigned int cpu) 1425static inline int can_use_console(unsigned int cpu)
1427{ 1426{
@@ -1434,8 +1433,10 @@ static inline int can_use_console(unsigned int cpu)
1434 * console_lock held, and 'console_locked' set) if it 1433 * console_lock held, and 'console_locked' set) if it
1435 * is successful, false otherwise. 1434 * is successful, false otherwise.
1436 */ 1435 */
1437static int console_trylock_for_printk(unsigned int cpu) 1436static int console_trylock_for_printk(void)
1438{ 1437{
1438 unsigned int cpu = smp_processor_id();
1439
1439 if (!console_trylock()) 1440 if (!console_trylock())
1440 return 0; 1441 return 0;
1441 /* 1442 /*
@@ -1605,7 +1606,8 @@ asmlinkage int vprintk_emit(int facility, int level,
1605 */ 1606 */
1606 if (!oops_in_progress && !lockdep_recursing(current)) { 1607 if (!oops_in_progress && !lockdep_recursing(current)) {
1607 recursion_bug = 1; 1608 recursion_bug = 1;
1608 goto out_restore_irqs; 1609 local_irq_restore(flags);
1610 return 0;
1609 } 1611 }
1610 zap_locks(); 1612 zap_locks();
1611 } 1613 }
@@ -1708,17 +1710,22 @@ asmlinkage int vprintk_emit(int facility, int level,
1708 1710
1709 logbuf_cpu = UINT_MAX; 1711 logbuf_cpu = UINT_MAX;
1710 raw_spin_unlock(&logbuf_lock); 1712 raw_spin_unlock(&logbuf_lock);
1713 lockdep_on();
1714 local_irq_restore(flags);
1715
1716 /*
1717 * Disable preemption to avoid being preempted while holding
1718 * console_sem which would prevent anyone from printing to console
1719 */
1720 preempt_disable();
1711 /* 1721 /*
1712 * Try to acquire and then immediately release the console semaphore. 1722 * Try to acquire and then immediately release the console semaphore.
1713 * The release will print out buffers and wake up /dev/kmsg and syslog() 1723 * The release will print out buffers and wake up /dev/kmsg and syslog()
1714 * users. 1724 * users.
1715 */ 1725 */
1716 if (console_trylock_for_printk(this_cpu)) 1726 if (console_trylock_for_printk())
1717 console_unlock(); 1727 console_unlock();
1718 1728 preempt_enable();
1719 lockdep_on();
1720out_restore_irqs:
1721 local_irq_restore(flags);
1722 1729
1723 return printed_len; 1730 return printed_len;
1724} 1731}