diff options
author | Sergey Senozhatsky <sergey.senozhatsky@gmail.com> | 2018-10-01 22:38:35 -0400 |
---|---|---|
committer | Petr Mladek <pmladek@suse.com> | 2018-10-12 04:03:39 -0400 |
commit | 3ac37a93fa9217e576bebfd4ba3e80edaaeb2289 (patch) | |
tree | 5ac022d5c88ad6842a498ed57d9de4cacd01a01b | |
parent | 9627808d2d409279cea3fb334212d04a83ff6371 (diff) |
printk: lock/unlock console only for new logbuf entries
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>
-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 f717656c0fac..e9a7e50ed60a 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c | |||
@@ -1890,8 +1890,9 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1890 | const char *fmt, va_list args) | 1890 | const char *fmt, va_list args) |
1891 | { | 1891 | { |
1892 | int printed_len; | 1892 | int printed_len; |
1893 | bool in_sched = false; | 1893 | bool in_sched = false, pending_output; |
1894 | unsigned long flags; | 1894 | unsigned long flags; |
1895 | u64 curr_log_seq; | ||
1895 | 1896 | ||
1896 | if (level == LOGLEVEL_SCHED) { | 1897 | if (level == LOGLEVEL_SCHED) { |
1897 | level = LOGLEVEL_DEFAULT; | 1898 | level = LOGLEVEL_DEFAULT; |
@@ -1903,11 +1904,13 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1903 | 1904 | ||
1904 | /* This stops the holder of console_sem just where we want him */ | 1905 | /* This stops the holder of console_sem just where we want him */ |
1905 | logbuf_lock_irqsave(flags); | 1906 | logbuf_lock_irqsave(flags); |
1907 | curr_log_seq = log_next_seq; | ||
1906 | printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); | 1908 | printed_len = vprintk_store(facility, level, dict, dictlen, fmt, args); |
1909 | pending_output = (curr_log_seq != log_next_seq); | ||
1907 | logbuf_unlock_irqrestore(flags); | 1910 | logbuf_unlock_irqrestore(flags); |
1908 | 1911 | ||
1909 | /* If called from the scheduler, we can not call up(). */ | 1912 | /* If called from the scheduler, we can not call up(). */ |
1910 | if (!in_sched) { | 1913 | if (!in_sched && pending_output) { |
1911 | /* | 1914 | /* |
1912 | * Disable preemption to avoid being preempted while holding | 1915 | * Disable preemption to avoid being preempted while holding |
1913 | * console_sem which would prevent anyone from printing to | 1916 | * console_sem which would prevent anyone from printing to |
@@ -1924,7 +1927,8 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1924 | preempt_enable(); | 1927 | preempt_enable(); |
1925 | } | 1928 | } |
1926 | 1929 | ||
1927 | wake_up_klogd(); | 1930 | if (pending_output) |
1931 | wake_up_klogd(); | ||
1928 | return printed_len; | 1932 | return printed_len; |
1929 | } | 1933 | } |
1930 | EXPORT_SYMBOL(vprintk_emit); | 1934 | EXPORT_SYMBOL(vprintk_emit); |