diff options
author | Petr Mladek <pmladek@suse.com> | 2018-08-14 13:36:15 +0200 |
---|---|---|
committer | Petr Mladek <pmladek@suse.com> | 2018-08-14 13:36:15 +0200 |
commit | 9f68cb579115faa211ae067b4628cf11162783fb (patch) | |
tree | 051146dd180af1b8a368d1a53b78c78920e15f64 /kernel/printk/printk.c | |
parent | lib/vsprintf: Do not handle %pO[^F] as %px (diff) | |
parent | printk/nmi: Prevent deadlock when accessing the main log buffer in NMI (diff) | |
download | linux-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.c | 57 |
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; } |