[PATCH 2/2] printk: factor out can_printk_async()

From: Sergey Senozhatsky
Date: Wed Dec 30 2015 - 23:39:58 EST


console_unlock() can be called directly or indirectly by a user
space process, so it can end up doing call_console_drivers() loop,
which will hold it from returning back to user-space from a syscall
for unpredictable amount of time.

Factor out can_printk_async() function, which queues an irq work and
sets a PRINTK_PENDING_OUTPUT pending bit (if we can do async printk).
vprintk_emit() already does it, add can_printk_async() call to
console_unlock() for !PF_KTHREAD processes.
---
kernel/printk/printk.c | 42 ++++++++++++++++++++++++++++--------------
1 file changed, 28 insertions(+), 14 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 47a70a2..7d3a8e1 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -355,6 +355,26 @@ int printk_deferred(const char *fmt, ...)
return r;
}

+static bool can_printk_async(bool sync)
+{
+ /*
+ * By default we print message to console asynchronously so that kernel
+ * doesn't get stalled due to slow serial console. That can lead to
+ * softlockups, lost interrupts, or userspace timing out under heavy
+ * printing load.
+ *
+ * However we resort to synchronous printing of messages during early
+ * boot, when oops is in progress, or when synchronous printing was
+ * explicitely requested by kernel parameter.
+ */
+ if (keventd_up() && !oops_in_progress && !sync) {
+ __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
+ irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
+ return true;
+ }
+ return false;
+}
+
/* Return log buffer address */
char *log_buf_addr_get(void)
{
@@ -1889,20 +1909,7 @@ asmlinkage int vprintk_emit(int facility, int level,
logbuf_cpu = UINT_MAX;
raw_spin_unlock(&logbuf_lock);
lockdep_on();
- /*
- * By default we print message to console asynchronously so that kernel
- * doesn't get stalled due to slow serial console. That can lead to
- * softlockups, lost interrupts, or userspace timing out under heavy
- * printing load.
- *
- * However we resort to synchronous printing of messages during early
- * boot, when oops is in progress, or when synchronous printing was
- * explicitely requested by kernel parameter.
- */
- if (keventd_up() && !oops_in_progress && !sync_print) {
- __this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
- irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
- } else
+ if (!can_printk_async(sync_print))
sync_print = true;
local_irq_restore(flags);

@@ -2328,6 +2335,13 @@ void console_unlock(void)
return;
}

+ if (!(current->flags & PF_KTHREAD) &&
+ can_printk_async(printk_sync)) {
+ console_locked = 0;
+ up_console_sem();
+ return;
+ }
+
/*
* Console drivers are called under logbuf_lock, so
* @console_may_schedule should be cleared before; however, we may
--
2.6.4


--4Ckj6UjgE2iN1+kY--
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/