summaryrefslogtreecommitdiffstats
path: root/kernel/printk/printk.c
diff options
context:
space:
mode:
authorPetr Mladek <pmladek@suse.com>2018-08-14 13:36:15 +0200
committerPetr Mladek <pmladek@suse.com>2018-08-14 13:36:15 +0200
commit9f68cb579115faa211ae067b4628cf11162783fb (patch)
tree051146dd180af1b8a368d1a53b78c78920e15f64 /kernel/printk/printk.c
parentlib/vsprintf: Do not handle %pO[^F] as %px (diff)
parentprintk/nmi: Prevent deadlock when accessing the main log buffer in NMI (diff)
downloadlinux-9f68cb579115faa211ae067b4628cf11162783fb.tar.xz
linux-9f68cb579115faa211ae067b4628cf11162783fb.zip
Merge branch 'for-4.19-nmi' into for-linus
Diffstat (limited to 'kernel/printk/printk.c')
-rw-r--r--kernel/printk/printk.c57
1 files changed, 35 insertions, 22 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index e2cb0fc18e2d..9a63aeeaaf5d 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1829,28 +1829,16 @@ static size_t log_output(int facility, int level, enum log_flags lflags, const c
return log_store(facility, level, lflags, 0, dict, dictlen, text, text_len);
}
-asmlinkage int vprintk_emit(int facility, int level,
- const char *dict, size_t dictlen,
- const char *fmt, va_list args)
+/* Must be called under logbuf_lock. */
+int vprintk_store(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, va_list args)
{
static char textbuf[LOG_LINE_MAX];
char *text = textbuf;
size_t text_len;
enum log_flags lflags = 0;
- unsigned long flags;
- int printed_len;
- bool in_sched = false;
-
- if (level == LOGLEVEL_SCHED) {
- level = LOGLEVEL_DEFAULT;
- in_sched = true;
- }
-
- boot_delay_msec(level);
- printk_delay();
- /* This stops the holder of console_sem just where we want him */
- logbuf_lock_irqsave(flags);
/*
* The printf needs to come first; we need the syslog
* prefix which might be passed-in as a parameter.
@@ -1894,8 +1882,29 @@ asmlinkage int vprintk_emit(int facility, int level,
if (suppress_message_printing(level))
lflags |= LOG_NOCONS;
- printed_len = log_output(facility, level, lflags, dict, dictlen, text, text_len);
+ return log_output(facility, level, lflags,
+ dict, dictlen, text, text_len);
+}
+asmlinkage int vprintk_emit(int facility, int level,
+ const char *dict, size_t dictlen,
+ const char *fmt, va_list args)
+{
+ int printed_len;
+ bool in_sched = false;
+ unsigned long flags;
+
+ if (level == LOGLEVEL_SCHED) {
+ level = LOGLEVEL_DEFAULT;
+ in_sched = true;
+ }
+
+ boot_delay_msec(level);
+ printk_delay();
+
+ /* This stops the holder of console_sem just where we want him */
+ logbuf_lock_irqsave(flags);
+ printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args);
logbuf_unlock_irqrestore(flags);
/* If called from the scheduler, we can not call up(). */
@@ -2884,16 +2893,20 @@ void wake_up_klogd(void)
preempt_enable();
}
-int vprintk_deferred(const char *fmt, va_list args)
+void defer_console_output(void)
{
- int r;
-
- r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
-
preempt_disable();
__this_cpu_or(printk_pending, PRINTK_PENDING_OUTPUT);
irq_work_queue(this_cpu_ptr(&wake_up_klogd_work));
preempt_enable();
+}
+
+int vprintk_deferred(const char *fmt, va_list args)
+{
+ int r;
+
+ r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, 0, fmt, args);
+ defer_console_output();
return r;
}