diff options
author | Sergey Senozhatsky <sergey.senozhatsky@gmail.com> | 2018-10-02 11:38:35 +0900 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2019-12-01 09:16:13 +0100 |
commit | 90d73768ddb6eac2df86c60072fbfe4d87e1d051 (patch) | |
tree | e3ddd740475911f60ecd1f39bbd4d09b5882738c /kernel/printk | |
parent | 8888689bd43356f17750992e3723e3271a6abeee (diff) | |
download | linux-stable-90d73768ddb6eac2df86c60072fbfe4d87e1d051.tar.gz linux-stable-90d73768ddb6eac2df86c60072fbfe4d87e1d051.tar.bz2 linux-stable-90d73768ddb6eac2df86c60072fbfe4d87e1d051.zip |
printk: lock/unlock console only for new logbuf entries
[ Upstream commit 3ac37a93fa9217e576bebfd4ba3e80edaaeb2289 ]
Prior to commit 5c2992ee7fd8a29 ("printk: remove console flushing special
cases for partial buffered lines") we would do console_cont_flush()
for each pr_cont() to print cont fragments, so console_unlock() would
actually print data:
pr_cont();
console_lock();
console_unlock()
console_cont_flush(); // print cont fragment
...
pr_cont();
console_lock();
console_unlock()
console_cont_flush(); // print cont fragment
We don't do console_cont_flush() anymore, so when we do pr_cont()
console_unlock() does nothing (unless we flushed the cont buffer):
pr_cont();
console_lock();
console_unlock(); // noop
...
pr_cont();
console_lock();
console_unlock(); // noop
...
pr_cont();
cont_flush();
console_lock();
console_unlock(); // print data
We also wakeup klogd purposelessly for pr_cont() output - un-flushed
cont buffer is not stored in log_buf; there is nothing to pull.
Thus we can console_lock()/console_unlock()/wake_up_klogd() only when
we know that we log_store()-ed a message and there is something to
print to the consoles/syslog.
Link: http://lkml.kernel.org/r/20181002023836.4487-3-sergey.senozhatsky@gmail.com
To: Steven Rostedt <rostedt@goodmis.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Dmitriy Vyukov <dvyukov@google.com>
Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Cc: Tejun Heo <tj@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: LKML <linux-kernel@vger.kernel.org>
Cc: Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'kernel/printk')
-rw-r--r-- | kernel/printk/printk.c | 10 |
1 files changed, 7 insertions, 3 deletions
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index c7b3d5489937..59ceaed1aeed 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1901,8 +1901,9 @@ asmlinkage int vprintk_emit(int facility, int level, const char *fmt, va_list args) { int printed_len; - bool in_sched = false; + bool in_sched = false, pending_output; unsigned long flags; + u64 curr_log_seq; if (level == LOGLEVEL_SCHED) { level = LOGLEVEL_DEFAULT; @@ -1914,11 +1915,13 @@ asmlinkage int vprintk_emit(int facility, int level, /* This stops the holder of console_sem just where we want him */ logbuf_lock_irqsave(flags); + curr_log_seq = log_next_seq; printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); + pending_output = (curr_log_seq != log_next_seq); logbuf_unlock_irqrestore(flags); /* If called from the scheduler, we can not call up(). */ - if (!in_sched) { + if (!in_sched && pending_output) { /* * Disable preemption to avoid being preempted while holding * console_sem which would prevent anyone from printing to @@ -1935,7 +1938,8 @@ asmlinkage int vprintk_emit(int facility, int level, preempt_enable(); } - wake_up_klogd(); + if (pending_output) + wake_up_klogd(); return printed_len; } EXPORT_SYMBOL(vprintk_emit); |