From: Petr Mladek <pmladek@suse.com>
To: Andrew Morton <akpm@linux-foundation.org>,
Sergey Senozhatsky <sergey.senozhatsky.work@gmail.com>
Cc: Jiri Kosina <jkosina@suse.com>, Jan Kara <jack@suse.com>,
Tejun Heo <tj@kernel.org>,
Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp>,
Byungchul Park <byungchul.park@lge.com>,
linux-kernel@vger.kernel.org, Petr Mladek <pmladek@suse.com>
Subject: [PATCH POC 4/4] printk: Correctly replay buffer log for a new console
Date: Fri, 15 Jul 2016 18:59:02 +0200 [thread overview]
Message-ID: <1468601942-18482-5-git-send-email-pmladek@suse.com> (raw)
In-Reply-To: <1468601942-18482-1-git-send-email-pmladek@suse.com>
There are several problems with replying the log buffer
when a new console is added.
Only the end of partially flushed line is printed on
the new console. But this end of the line is not longer
printed on the other consoles. In fact, any new line
are printed only on the new console until the replay
is finished.
This patch tries to fix all the above mentioned problems.
The replay finishes when the original sequence number
is reached. Only the already printed piece of the
continuous line is printed. The rest will be printed
when all consoles are enabled again.
Signed-off-by: Petr Mladek <pmladek@suse.com>
---
kernel/printk/printk.c | 68 ++++++++++++++++++++++++++++++++++++++------------
1 file changed, 52 insertions(+), 16 deletions(-)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index a920cc36c24e..d117e7b1244d 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -134,9 +134,11 @@ static int __down_trylock_console_sem(unsigned long ip)
static int console_locked, console_suspended;
/*
- * If exclusive_console is non-NULL then only this console is to be printed to.
+ * If exclusive_console is non-NULL then only this console is to be printed to
+ * and only until the given sequence number.
*/
static struct console *exclusive_console;
+static u64 exclusive_console_seq_stop;
/*
* Array of consoles built from command line options (console=)
@@ -2177,14 +2179,15 @@ static inline int can_use_console(void)
return cpu_online(raw_smp_processor_id()) || have_callable_console();
}
-static void console_cont_flush(char *text, size_t size)
+static void console_cont_flush(struct cont *cont,char *text, size_t size)
{
unsigned long flags;
+ u8 level;
size_t len;
raw_spin_lock_irqsave(&logbuf_lock, flags);
- if (!cont.msg->text_len)
+ if (!cont->msg->text_len)
goto out;
/*
@@ -2194,10 +2197,11 @@ static void console_cont_flush(char *text, size_t size)
if (console_seq < log_next_seq)
goto out;
- len = cont_print_text(&cont, text, size);
+ len = cont_print_text(cont, text, size);
+ level = cont->msg->level;
raw_spin_unlock(&logbuf_lock);
stop_critical_timings();
- call_console_drivers(cont.msg->level, NULL, 0, text, len);
+ call_console_drivers(level, NULL, 0, text, len);
start_critical_timings();
local_irq_restore(flags);
return;
@@ -2282,18 +2286,19 @@ again:
len = 0;
}
+ if (exclusive_console &&
+ console_seq == exclusive_console_seq_stop)
+ break;
+
if (console_seq == log_next_seq)
break;
msg = log_from_idx(console_idx);
level = msg->level;
- /*
- * The line might be already partially printed from the cont
- * buffer. In this case, flush the rest using a fake
- * cont buffer.
- */
- if (cont_console_len && cont_console_seq == console_seq) {
+ if (cont_console_len &&
+ cont_console_seq == console_seq &&
+ !exclusive_console) {
struct cont fake_cont;
fake_cont.owner = NULL;
@@ -2317,7 +2322,6 @@ again:
log_text(msg), msg->text_len);
}
}
-
console_idx = log_next(console_idx);
console_seq++;
console_prev = msg->flags;
@@ -2334,12 +2338,43 @@ again:
raw_spin_unlock(&logbuf_lock);
- /* flush buffered message fragment immediately to console */
- console_cont_flush(text, sizeof(text));
+ if (unlikely(exclusive_console)) {
+ /* Replay also the partially flushed cont buffer */
+ if (cont_console_seq) {
+ struct printk_log fake_msg;
+ struct printk_log *msg;
+ struct cont fake_cont;
+ size_t len;
+ int level;
+
+ raw_spin_lock(&logbuf_lock);
+ if (console_seq == log_next_seq) {
+ memcpy(&fake_msg, &cont_msg, sizeof(fake_msg));
+ fake_cont.buf = cont_buf;
+ } else {
+ msg = log_from_idx(console_idx);
+ memcpy(&fake_msg, msg, sizeof(fake_msg));
+ fake_cont.buf = log_text(msg);
+ }
+ fake_cont.msg = &fake_msg;
+ fake_msg.text_len = cont_console_len;
+ cont_console_len = 0;
+
+ len = cont_print_text(&fake_cont, text, sizeof(text));
+ level = fake_msg.level;
+
+ raw_spin_unlock(&logbuf_lock);
+
+ stop_critical_timings(); /* don't trace print latency */
+ call_console_drivers(level, NULL, 0, text, len);
+ start_critical_timings();
+ }
- /* Release the exclusive_console once it is used */
- if (unlikely(exclusive_console))
exclusive_console = NULL;
+ } else {
+ /* Flush buffered message fragment immediately to console */
+ console_cont_flush(&cont, text, sizeof(text));
+ }
console_locked = 0;
up_console_sem();
@@ -2626,6 +2661,7 @@ void register_console(struct console *newcon)
* the already-registered consoles.
*/
exclusive_console = newcon;
+ exclusive_console_seq_stop = console_seq;
}
console_unlock();
console_sysfs_notify();
--
1.8.5.6
next prev parent reply other threads:[~2016-07-15 16:59 UTC|newest]
Thread overview: 9+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-15 16:58 [PATCH POC 0/4] printk: Several fixes of cont buffer and console handling Petr Mladek
2016-07-15 16:58 ` [PATCH POC 1/4] printk: Prepeparation for fake cont buffers Petr Mladek
2016-07-15 18:26 ` kbuild test robot
2016-07-15 16:59 ` [PATCH POC 2/4] printk: Do not block cont buffer by partially flushed lines Petr Mladek
2016-07-15 18:31 ` kbuild test robot
2016-07-15 22:08 ` kbuild test robot
2016-07-15 16:59 ` [PATCH POC 3/4] printk: Flush the cont buffer after the other lines Petr Mladek
2016-07-15 16:59 ` Petr Mladek [this message]
2016-07-15 18:27 ` [PATCH POC 4/4] printk: Correctly replay buffer log for a new console kbuild test robot
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1468601942-18482-5-git-send-email-pmladek@suse.com \
--to=pmladek@suse.com \
--cc=akpm@linux-foundation.org \
--cc=byungchul.park@lge.com \
--cc=jack@suse.com \
--cc=jkosina@suse.com \
--cc=linux-kernel@vger.kernel.org \
--cc=penguin-kernel@I-love.SAKURA.ne.jp \
--cc=sergey.senozhatsky.work@gmail.com \
--cc=tj@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®