diff options
author | Jan Kara <jack@suse.cz> | 2014-06-04 19:11:37 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-04 19:54:17 -0400 |
commit | 939f04bec1a4ef6ba4370b0f34b01decc844b1b1 (patch) | |
tree | 1da1d9914daa6d19813589502f458c7a24e737e0 /kernel | |
parent | bd8d7cf5b8410fe98eba06a9aaa90efe88815d8a (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.c | 29 |
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 | */ |
1426 | static inline int can_use_console(unsigned int cpu) | 1425 | static 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 | */ |
1437 | static int console_trylock_for_printk(unsigned int cpu) | 1436 | static 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(); | ||
1720 | out_restore_irqs: | ||
1721 | local_irq_restore(flags); | ||
1722 | 1729 | ||
1723 | return printed_len; | 1730 | return printed_len; |
1724 | } | 1731 | } |