All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH POC 0/4] printk: Several fixes of cont buffer and console handling
@ 2016-07-15 16:58 Petr Mladek
  2016-07-15 16:58 ` [PATCH POC 1/4] printk: Prepeparation for fake cont buffers Petr Mladek
                   ` (3 more replies)
  0 siblings, 4 replies; 9+ messages in thread
From: Petr Mladek @ 2016-07-15 16:58 UTC (permalink / raw)
  To: Andrew Morton, Sergey Senozhatsky
  Cc: Jiri Kosina, Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park,
	linux-kernel, Petr Mladek

This patch set is a working POC how to reduce mess with partially
printed lines. In addition, it fixes some races when replying logbuffer
on new consoles.

It can be applied on top of v12 of the async printk patches, see
https://lkml.kernel.org/g/20160513131848.2087-1-sergey.senozhatsky@gmail.com
But it is basically independent on the async printk stuff.

I wanted to see how my proposal could look like in practice
https://lkml.kernel.org/g/20160712162809.GE32373@pathway.suse.cz


IMPORTANT: I have vacation next two weeks and will not have much access
to the newtwork. I wanted to sent what I had before leaving. The last
patch is not much tested. Feel free to take it, rework it yourself
or just send your opinion.

Petr Mladek (4):
  printk: Prepeparation for fake cont buffers
  printk: Do not block cont buffer by partially flushed lines
  printk: Flush the cont buffer after the other lines
  printk: Correctly replay buffer log for a new console

 kernel/printk/printk.c | 235 +++++++++++++++++++++++++++----------------------
 1 file changed, 128 insertions(+), 107 deletions(-)

-- 
1.8.5.6

^ permalink raw reply	[flat|nested] 9+ messages in thread

* [PATCH POC 1/4] printk: Prepeparation for fake cont buffers
  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 ` 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
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 9+ messages in thread
From: Petr Mladek @ 2016-07-15 16:58 UTC (permalink / raw)
  To: Andrew Morton, Sergey Senozhatsky
  Cc: Jiri Kosina, Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park,
	linux-kernel, Petr Mladek

Parts of the line can be premilitary flushed to the console
by console_cont_flush(). When this happen, the cont buffer
could not be used for new lines until the rest of the original
line is flushed. This might cause unnecessary fragmentation
of continuous lines.

This patch is a preparation step to create fake cont buffers
using the information already stored into the main ring buffer.

Most of the existing elements are newly stored via a pointer to
struct printk_log. Also the buffer is changed to a pointer.

The information about the number of characters pushed to the
console is moved to a global variable because it is a global
state.

The patch does not change the existing logic and behavior
any way.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 90 ++++++++++++++++++++++++++++----------------------
 1 file changed, 50 insertions(+), 40 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 4ae2797ec10a..71e96aae98e7 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -1511,55 +1511,63 @@ static inline void printk_delay(void)
 	}
 }
 
+
 /*
  * Continuation lines are buffered, and not committed to the record buffer
  * until the line is complete, or a race forces it. The line fragments
  * though, are printed immediately to the consoles to ensure everything has
  * reached the console in case of a kernel crash.
  */
-static struct cont {
-	char buf[LOG_LINE_MAX];
-	size_t len;			/* length == 0 means unused buffer */
-	size_t cons;			/* bytes written to console */
+struct cont {
 	struct task_struct *owner;	/* task of first print*/
-	u64 ts_nsec;			/* time of first print */
-	u8 level;			/* log level of first message */
-	u8 facility;			/* log facility of first message */
-	enum log_flags flags;		/* prefix, newline flags */
+	struct printk_log *msg;		/* more info about the stored text */
+	char *buf;			/* buffer to the stored text */
 	bool flushed:1;			/* buffer sealed and committed */
-} cont;
+};
+
+/* bytes written to console */
+static size_t cont_console_len;
+
+static struct printk_log cont_msg;
+static char cont_buf[LOG_LINE_MAX];
+
+static struct cont cont = {
+	.msg = &cont_msg,
+	.buf = cont_buf,
+};
 
 static void cont_flush(enum log_flags flags)
 {
 	if (cont.flushed)
 		return;
-	if (cont.len == 0)
+	if (cont.msg->text_len == 0)
 		return;
 
-	if (cont.cons) {
+	if (cont_console_len) {
 		/*
 		 * If a fragment of this line was directly flushed to the
 		 * console; wait for the console to pick up the rest of the
 		 * line. LOG_NOCONS suppresses a duplicated output.
 		 */
-		log_store(cont.facility, cont.level, flags | LOG_NOCONS,
-			  cont.ts_nsec, NULL, 0, cont.buf, cont.len);
-		cont.flags = flags;
+		log_store(cont.msg->facility, cont.msg->level,
+			  flags | LOG_NOCONS, cont.msg->ts_nsec,
+			  NULL, 0, cont.buf, cont.msg->text_len);
+		cont.msg->flags = flags;
 		cont.flushed = true;
 	} else {
 		/*
 		 * If no fragment of this line ever reached the console,
 		 * just submit it to the store and free the buffer.
 		 */
-		log_store(cont.facility, cont.level, flags, 0,
-			  NULL, 0, cont.buf, cont.len);
-		cont.len = 0;
+		log_store(cont.msg->facility, cont.msg->level, flags, 0,
+			  NULL, 0, cont.buf, cont.msg->text_len);
+		cont.msg->text_len = 0;
 	}
 }
 
 static bool cont_add(int facility, int level, const char *text, size_t len)
 {
-	if (cont.len && cont.flushed)
+	if (cont.msg->text_len && cont.flushed)
 		return false;
 
 	/*
@@ -1567,25 +1575,26 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 	 * continuation.  See nr_ext_console_drivers definition.  Also, if
 	 * the line gets too long, split it up in separate records.
 	 */
-	if (nr_ext_console_drivers || cont.len + len > sizeof(cont.buf)) {
+	if (nr_ext_console_drivers ||
+	    cont.msg->text_len + len > sizeof(cont_buf)) {
 		cont_flush(LOG_CONT);
 		return false;
 	}
 
-	if (!cont.len) {
-		cont.facility = facility;
-		cont.level = level;
+	if (!cont.msg->text_len) {
 		cont.owner = current;
-		cont.ts_nsec = local_clock();
-		cont.flags = 0;
-		cont.cons = 0;
+		cont.msg->facility = facility;
+		cont.msg->level = level;
+		cont.msg->ts_nsec = local_clock();
+		cont.msg->flags = 0;
 		cont.flushed = false;
+		cont_console_len = 0;
 	}
 
-	memcpy(cont.buf + cont.len, text, len);
-	cont.len += len;
+	memcpy(cont.buf + cont.msg->text_len, text, len);
+	cont.msg->text_len += len;
 
-	if (cont.len > (sizeof(cont.buf) * 80) / 100)
+	if (cont.msg->text_len > (sizeof(cont_buf) * 80) / 100)
 		cont_flush(LOG_CONT);
 
 	return true;
@@ -1596,25 +1605,25 @@ static size_t cont_print_text(char *text, size_t size)
 	size_t textlen = 0;
 	size_t len;
 
-	if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) {
-		textlen += print_time(cont.ts_nsec, text);
+	if (cont_console_len == 0 && (console_prev & LOG_NEWLINE)) {
+		textlen += print_time(cont.msg->ts_nsec, text);
 		size -= textlen;
 	}
 
-	len = cont.len - cont.cons;
+	len = cont.msg->text_len - cont_console_len;
 	if (len > 0) {
 		if (len+1 > size)
 			len = size-1;
-		memcpy(text + textlen, cont.buf + cont.cons, len);
+		memcpy(text + textlen, cont.buf + cont_console_len, len);
 		textlen += len;
-		cont.cons = cont.len;
+		cont_console_len = cont.msg->text_len;
 	}
 
 	if (cont.flushed) {
-		if (cont.flags & LOG_NEWLINE)
+		if (cont.msg->flags & LOG_NEWLINE)
 			text[textlen++] = '\n';
 		/* got everything, release buffer */
-		cont.len = 0;
+		cont.msg->text_len = 0;
 	}
 	return textlen;
 }
@@ -1738,7 +1747,8 @@ asmlinkage int vprintk_emit(int facility, int level,
 		 * Flush the conflicting buffer. An earlier newline was missing,
 		 * or another task also prints continuation lines.
 		 */
-		if (cont.len && (lflags & LOG_PREFIX || cont.owner != current))
+		if (cont.msg->text_len &&
+		    (lflags & LOG_PREFIX || cont.owner != current))
 			cont_flush(LOG_NEWLINE);
 
 		/* buffer line if possible, otherwise store it right away */
@@ -1759,7 +1769,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 		 * If the preceding printk was from a different task and missed
 		 * a newline, flush and append the newline.
 		 */
-		if (cont.len) {
+		if (cont.msg->text_len) {
 			if (cont.owner == current && !(lflags & LOG_PREFIX))
 				stored = cont_add(facility, level, text,
 						  text_len);
@@ -2201,7 +2211,7 @@ static void console_cont_flush(char *text, size_t size)
 
 	raw_spin_lock_irqsave(&logbuf_lock, flags);
 
-	if (!cont.len)
+	if (!cont.msg->text_len)
 		goto out;
 
 	/*
@@ -2209,13 +2219,13 @@ static void console_cont_flush(char *text, size_t size)
 	 * busy. The earlier ones need to be printed before this one, we
 	 * did not flush any fragment so far, so just let it queue up.
 	 */
-	if (console_seq < log_next_seq && !cont.cons)
+	if (console_seq < log_next_seq && !cont_console_len)
 		goto out;
 
 	len = cont_print_text(text, size);
 	raw_spin_unlock(&logbuf_lock);
 	stop_critical_timings();
-	call_console_drivers(cont.level, NULL, 0, text, len);
+	call_console_drivers(cont.msg->level, NULL, 0, text, len);
 	start_critical_timings();
 	local_irq_restore(flags);
 	return;
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH POC 2/4] printk: Do not block cont buffer by partially flushed lines
  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 16:59 ` 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 ` [PATCH POC 4/4] printk: Correctly replay buffer log for a new console Petr Mladek
  3 siblings, 2 replies; 9+ messages in thread
From: Petr Mladek @ 2016-07-15 16:59 UTC (permalink / raw)
  To: Andrew Morton, Sergey Senozhatsky
  Cc: Jiri Kosina, Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park,
	linux-kernel, Petr Mladek

Parts of the line can be preliminary flushed to the console
by console_cont_flush(). When this happen, the cont buffer
could not be used for new lines until the rest of the original
line is flushed. This might cause unnecessary fragmentation
of continuous lines.

But there is always only one partially flushed line. We do not
need any per line LOG_NOCONS flag. Instead, we could simply
remember the related sequence number.

Also we could construct a fake cont structure from the
information stored in the ring buffer.

Therefore, we could always flush the log buffer and make
the whole logic easier.

Finally, it makes perfect sense to use the time stamp
of the first continuous fragment. This is why cont_flush()
can be so trivial now.

Signed-off-by: Petr Mladek <pmladek@suse.com>
---
 kernel/printk/printk.c | 123 ++++++++++++++++++++-----------------------------
 1 file changed, 49 insertions(+), 74 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 71e96aae98e7..7d93ac263006 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -222,7 +222,6 @@ static int console_may_schedule;
  */
 
 enum log_flags {
-	LOG_NOCONS	= 1,	/* already flushed, do not print to console */
 	LOG_NEWLINE	= 2,	/* text ended with a newline */
 	LOG_PREFIX	= 4,	/* text started with a prefix */
 	LOG_CONT	= 8,	/* text is a fragment of a continuation line */
@@ -1522,11 +1521,12 @@ struct cont {
 	struct task_struct *owner;	/* task of first print*/
 	struct printk_log *msg;		/* more info about the stored text */
 	char *buf;			/* buffer to the stored text */
-	bool flushed:1;			/* buffer sealed and committed */
 };
 
 /* bytes written to console */
 static size_t cont_console_len;
+/* sequence number related to the partially flushed line */
+static u64 cont_console_seq;
 
 static struct printk_log cont_msg;
 static char cont_buf[LOG_LINE_MAX];
@@ -1538,38 +1538,16 @@ static struct cont cont = {
 
 static void cont_flush(enum log_flags flags)
 {
-	if (cont.flushed)
-		return;
 	if (cont.msg->text_len == 0)
 		return;
 
-	if (cont_console_len) {
-		/*
-		 * If a fragment of this line was directly flushed to the
-		 * console; wait for the console to pick up the rest of the
-		 * line. LOG_NOCONS suppresses a duplicated output.
-		 */
-		log_store(cont.msg->facility, cont.msg->level,
-			  flags | LOG_NOCONS, cont.msg->ts_nsec,
-			  NULL, 0, cont.buf, cont.msg->text_len);
-		cont.msg->flags = flags;
-		cont.flushed = true;
-	} else {
-		/*
-		 * If no fragment of this line ever reached the console,
-		 * just submit it to the store and free the buffer.
-		 */
-		log_store(cont.msg->facility, cont.msg->level, flags, 0,
-			  NULL, 0, cont.buf, cont.msg->text_len);
-		cont.msg->text_len = 0;
-	}
+	log_store(cont.msg->facility, cont.msg->level, flags,
+		  cont.msg->ts_nsec, NULL, 0, cont.buf, cont.msg->text_len);
+	cont.msg->text_len = 0;
 }
 
 static bool cont_add(int facility, int level, const char *text, size_t len)
 {
-	if (cont.msg->text_len && cont.flushed)
-		return false;
-
 	/*
 	 * If ext consoles are present, flush and skip in-kernel
 	 * continuation.  See nr_ext_console_drivers definition.  Also, if
@@ -1587,8 +1565,6 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 		cont.msg->level = level;
 		cont.msg->ts_nsec = local_clock();
 		cont.msg->flags = 0;
-		cont.flushed = false;
-		cont_console_len = 0;
 	}
 
 	memcpy(cont.buf + cont.msg->text_len, text, len);
@@ -1600,31 +1576,29 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 	return true;
 }
 
-static size_t cont_print_text(char *text, size_t size)
+static size_t cont_print_text(struct cont *cont, char *text, size_t size)
 {
 	size_t textlen = 0;
 	size_t len;
 
 	if (cont_console_len == 0 && (console_prev & LOG_NEWLINE)) {
-		textlen += print_time(cont.msg->ts_nsec, text);
+		textlen += print_time(cont->msg->ts_nsec, text);
 		size -= textlen;
 	}
 
-	len = cont.msg->text_len - cont_console_len;
+	len = cont->msg->text_len - cont_console_len;
 	if (len > 0) {
 		if (len+1 > size)
 			len = size-1;
-		memcpy(text + textlen, cont.buf + cont_console_len, len);
+		memcpy(text + textlen, cont->buf + cont_console_len, len);
 		textlen += len;
-		cont_console_len = cont.msg->text_len;
+		cont_console_len = cont->msg->text_len;
+		cont_console_seq = console_seq;
 	}
 
-	if (cont.flushed) {
-		if (cont.msg->flags & LOG_NEWLINE)
-			text[textlen++] = '\n';
-		/* got everything, release buffer */
-		cont.msg->text_len = 0;
-	}
+	if (cont->msg->flags & LOG_NEWLINE)
+		text[textlen++] = '\n';
+
 	return textlen;
 }
 
@@ -1917,7 +1891,6 @@ static struct cont {
 	size_t len;
 	size_t cons;
 	u8 level;
-	bool flushed:1;
 } cont;
 static char *log_text(const struct printk_log *msg) { return NULL; }
 static char *log_dict(const struct printk_log *msg) { return NULL; }
@@ -2215,14 +2188,13 @@ static void console_cont_flush(char *text, size_t size)
 		goto out;
 
 	/*
-	 * We still queue earlier records, likely because the console was
-	 * busy. The earlier ones need to be printed before this one, we
-	 * did not flush any fragment so far, so just let it queue up.
+	 * If the partially printed line is already stored in
+	 * the ring buffer, it will be handled with the other lines.
 	 */
-	if (console_seq < log_next_seq && !cont_console_len)
+	if (console_seq < log_next_seq)
 		goto out;
 
-	len = cont_print_text(text, size);
+	len = cont_print_text(&cont, text, size);
 	raw_spin_unlock(&logbuf_lock);
 	stop_critical_timings();
 	call_console_drivers(cont.msg->level, NULL, 0, text, len);
@@ -2312,40 +2284,43 @@ again:
 		} else {
 			len = 0;
 		}
-skip:
+
 		if (console_seq == log_next_seq)
 			break;
 
 		msg = log_from_idx(console_idx);
-		if (msg->flags & LOG_NOCONS) {
-			/*
-			 * Skip record we have buffered and already printed
-			 * directly to the console when we received it.
-			 */
-			console_idx = log_next(console_idx);
-			console_seq++;
-			/*
-			 * We will get here again when we register a new
-			 * CON_PRINTBUFFER console. Clear the flag so we
-			 * will properly dump everything later.
-			 */
-			msg->flags &= ~LOG_NOCONS;
-			console_prev = msg->flags;
-			goto skip;
-		}
-
 		level = msg->level;
-		len += msg_print_text(msg, console_prev, false,
-				      text + len, sizeof(text) - len);
-		if (nr_ext_console_drivers) {
-			ext_len = msg_print_ext_header(ext_text,
-						sizeof(ext_text),
-						msg, console_seq, console_prev);
-			ext_len += msg_print_ext_body(ext_text + ext_len,
-						sizeof(ext_text) - ext_len,
-						log_dict(msg), msg->dict_len,
-						log_text(msg), msg->text_len);
+
+		/*
+		 * 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) {
+			struct cont fake_cont;
+
+			fake_cont.owner = NULL;
+			fake_cont.msg = msg;
+			fake_cont.buf = log_text(msg);
+
+			len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
+
+			cont_console_len = 0;
+			cont_console_seq = 0;
+		} else {
+			len += msg_print_text(msg, console_prev, false,
+					      text + len, sizeof(text) - len);
+			if (nr_ext_console_drivers) {
+				ext_len = msg_print_ext_header(ext_text,
+							       sizeof(ext_text),
+							       msg, console_seq, console_prev);
+				ext_len += msg_print_ext_body(ext_text + ext_len,
+							      sizeof(ext_text) - ext_len,
+							      log_dict(msg), msg->dict_len,
+							      log_text(msg), msg->text_len);
+			}
 		}
+
 		console_idx = log_next(console_idx);
 		console_seq++;
 		console_prev = msg->flags;
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH POC 3/4] printk: Flush the cont buffer after the other lines
  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 16:59 ` [PATCH POC 2/4] printk: Do not block cont buffer by partially flushed lines Petr Mladek
@ 2016-07-15 16:59 ` Petr Mladek
  2016-07-15 16:59 ` [PATCH POC 4/4] printk: Correctly replay buffer log for a new console Petr Mladek
  3 siblings, 0 replies; 9+ messages in thread
From: Petr Mladek @ 2016-07-15 16:59 UTC (permalink / raw)
  To: Andrew Morton, Sergey Senozhatsky
  Cc: Jiri Kosina, Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park,
	linux-kernel, Petr Mladek

The cont buffer is not longer blocked until the rest of
the line is stored. Instead, the remaining part of the line
is printed from the ring buffer in the normal cycle.

Therefore console_cont_flush() always prints only
the very last line and it makes sense to call it
after the main cycle.

Note that it is safe to modify exclusive_console
and console_locked variables without the logbuf_lock.
They both are primary synchronized by the console_sem.
---
 kernel/printk/printk.c | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 7d93ac263006..a920cc36c24e 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2258,9 +2258,6 @@ again:
 		return;
 	}
 
-	/* flush buffered message fragment immediately to console */
-	console_cont_flush(text, sizeof(text));
-
 	for (;;) {
 		struct printk_log *msg;
 		size_t ext_len = 0;
@@ -2334,14 +2331,17 @@ again:
 		if (do_cond_resched)
 			cond_resched();
 	}
-	console_locked = 0;
+
+	raw_spin_unlock(&logbuf_lock);
+
+	/* flush buffered message fragment immediately to console */
+	console_cont_flush(text, sizeof(text));
 
 	/* Release the exclusive_console once it is used */
 	if (unlikely(exclusive_console))
 		exclusive_console = NULL;
 
-	raw_spin_unlock(&logbuf_lock);
-
+	console_locked = 0;
 	up_console_sem();
 
 	/*
-- 
1.8.5.6

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH POC 4/4] printk: Correctly replay buffer log for a new console
  2016-07-15 16:58 [PATCH POC 0/4] printk: Several fixes of cont buffer and console handling Petr Mladek
                   ` (2 preceding siblings ...)
  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
  2016-07-15 18:27   ` kbuild test robot
  3 siblings, 1 reply; 9+ messages in thread
From: Petr Mladek @ 2016-07-15 16:59 UTC (permalink / raw)
  To: Andrew Morton, Sergey Senozhatsky
  Cc: Jiri Kosina, Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park,
	linux-kernel, Petr Mladek

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

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH POC 1/4] printk: Prepeparation for fake cont buffers
  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
  0 siblings, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2016-07-15 18:26 UTC (permalink / raw)
  To: Petr Mladek
  Cc: kbuild-all, Andrew Morton, Sergey Senozhatsky, Jiri Kosina,
	Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park, linux-kernel,
	Petr Mladek

[-- Attachment #1: Type: text/plain, Size: 1991 bytes --]

Hi,

[auto build test ERROR on v4.7-rc7]
[cannot apply to next-20160715]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Petr-Mladek/printk-Several-fixes-of-cont-buffer-and-console-handling/20160716-012724
config: i386-tinyconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   kernel/printk/printk.c: In function 'console_cont_flush':
>> kernel/printk/printk.c:2177:11: error: 'struct cont' has no member named 'msg'
     if (!cont.msg->text_len)
              ^
>> kernel/printk/printk.c:2185:37: error: 'cont_console_len' undeclared (first use in this function)
     if (console_seq < log_next_seq && !cont_console_len)
                                        ^~~~~~~~~~~~~~~~
   kernel/printk/printk.c:2185:37: note: each undeclared identifier is reported only once for each function it appears in
   kernel/printk/printk.c:2191:27: error: 'struct cont' has no member named 'msg'
     call_console_drivers(cont.msg->level, NULL, 0, text, len);
                              ^

vim +2177 kernel/printk/printk.c

  2171	{
  2172		unsigned long flags;
  2173		size_t len;
  2174	
  2175		raw_spin_lock_irqsave(&logbuf_lock, flags);
  2176	
> 2177		if (!cont.msg->text_len)
  2178			goto out;
  2179	
  2180		/*
  2181		 * We still queue earlier records, likely because the console was
  2182		 * busy. The earlier ones need to be printed before this one, we
  2183		 * did not flush any fragment so far, so just let it queue up.
  2184		 */
> 2185		if (console_seq < log_next_seq && !cont_console_len)
  2186			goto out;
  2187	
  2188		len = cont_print_text(text, size);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6334 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH POC 4/4] printk: Correctly replay buffer log for a new console
  2016-07-15 16:59 ` [PATCH POC 4/4] printk: Correctly replay buffer log for a new console Petr Mladek
@ 2016-07-15 18:27   ` kbuild test robot
  0 siblings, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2016-07-15 18:27 UTC (permalink / raw)
  To: Petr Mladek
  Cc: kbuild-all, Andrew Morton, Sergey Senozhatsky, Jiri Kosina,
	Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park, linux-kernel,
	Petr Mladek

[-- Attachment #1: Type: text/plain, Size: 7433 bytes --]

Hi,

[auto build test ERROR on v4.7-rc7]
[cannot apply to next-20160715]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Petr-Mladek/printk-Several-fixes-of-cont-buffer-and-console-handling/20160716-012724
config: i386-tinyconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All errors (new ones prefixed by >>):

   kernel/printk/printk.c: In function 'console_cont_flush':
   kernel/printk/printk.c:2153:11: error: 'struct cont' has no member named 'msg'
     if (!cont->msg->text_len)
              ^~
   kernel/printk/printk.c:2163:24: error: passing argument 1 of 'cont_print_text' from incompatible pointer type [-Werror=incompatible-pointer-types]
     len = cont_print_text(cont, text, size);
                           ^~~~
   kernel/printk/printk.c:1875:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2163:30: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast [-Wint-conversion]
     len = cont_print_text(cont, text, size);
                                 ^~~~
   kernel/printk/printk.c:1875:15: note: expected 'size_t {aka unsigned int}' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2163:8: error: too many arguments to function 'cont_print_text'
     len = cont_print_text(cont, text, size);
           ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:1875:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2164:14: error: 'struct cont' has no member named 'msg'
     level = cont->msg->level;
                 ^~
   kernel/printk/printk.c: In function 'console_unlock':
   kernel/printk/printk.c:2262:7: error: 'cont_console_len' undeclared (first use in this function)
      if (cont_console_len &&
          ^~~~~~~~~~~~~~~~
   kernel/printk/printk.c:2262:7: note: each undeclared identifier is reported only once for each function it appears in
   kernel/printk/printk.c:2263:7: error: 'cont_console_seq' undeclared (first use in this function)
          cont_console_seq == console_seq &&
          ^~~~~~~~~~~~~~~~
   kernel/printk/printk.c:2267:13: error: 'struct cont' has no member named 'owner'
       fake_cont.owner = NULL;
                ^
   kernel/printk/printk.c:2268:13: error: 'struct cont' has no member named 'msg'
       fake_cont.msg = msg;
                ^
   kernel/printk/printk.c:2269:13: error: 'struct cont' has no member named 'buf'
       fake_cont.buf = log_text(msg);
                ^
   kernel/printk/printk.c:2271:27: error: passing argument 1 of 'cont_print_text' from incompatible pointer type [-Werror=incompatible-pointer-types]
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
                              ^
   kernel/printk/printk.c:1875:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2271:39: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast [-Wint-conversion]
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
                                          ^~~~
   kernel/printk/printk.c:1875:15: note: expected 'size_t {aka unsigned int}' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2271:11: error: too many arguments to function 'cont_print_text'
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
              ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:1875:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   In file included from arch/x86/include/asm/string.h:2:0,
                    from include/linux/string.h:18,
                    from include/linux/dynamic_debug.h:111,
                    from include/linux/printk.h:289,
                    from include/linux/kernel.h:13,
                    from kernel/printk/printk.c:19:
>> kernel/printk/printk.c:2315:24: error: 'cont_msg' undeclared (first use in this function)
        memcpy(&fake_msg, &cont_msg, sizeof(fake_msg));
                           ^
   arch/x86/include/asm/string_32.h:182:45: note: in definition of macro 'memcpy'
    #define memcpy(t, f, n) __builtin_memcpy(t, f, n)
                                                ^
   kernel/printk/printk.c:2316:14: error: 'struct cont' has no member named 'buf'
        fake_cont.buf = cont_buf;
                 ^
>> kernel/printk/printk.c:2316:21: error: 'cont_buf' undeclared (first use in this function)
        fake_cont.buf = cont_buf;
                        ^~~~~~~~
   kernel/printk/printk.c:2320:14: error: 'struct cont' has no member named 'buf'
        fake_cont.buf = log_text(msg);
                 ^
   kernel/printk/printk.c:2322:13: error: 'struct cont' has no member named 'msg'
       fake_cont.msg = &fake_msg;
                ^
   kernel/printk/printk.c:2326:26: error: passing argument 1 of 'cont_print_text' from incompatible pointer type [-Werror=incompatible-pointer-types]
       len = cont_print_text(&fake_cont, text, sizeof(text));
                             ^
   kernel/printk/printk.c:1875:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2326:38: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast [-Wint-conversion]
       len = cont_print_text(&fake_cont, text, sizeof(text));
                                         ^~~~
   kernel/printk/printk.c:1875:15: note: expected 'size_t {aka unsigned int}' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2326:10: error: too many arguments to function 'cont_print_text'
       len = cont_print_text(&fake_cont, text, sizeof(text));
             ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:1875:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/cont_msg +2315 kernel/printk/printk.c

  2309				struct cont fake_cont;
  2310				size_t len;
  2311				int level;
  2312	
  2313				raw_spin_lock(&logbuf_lock);
  2314				if (console_seq == log_next_seq) {
> 2315					memcpy(&fake_msg, &cont_msg, sizeof(fake_msg));
> 2316					fake_cont.buf = cont_buf;
  2317				} else {
  2318					msg = log_from_idx(console_idx);
  2319					memcpy(&fake_msg, msg, sizeof(fake_msg));

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6334 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH POC 2/4] printk: Do not block cont buffer by partially flushed lines
  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
  1 sibling, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2016-07-15 18:31 UTC (permalink / raw)
  To: Petr Mladek
  Cc: kbuild-all, Andrew Morton, Sergey Senozhatsky, Jiri Kosina,
	Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park, linux-kernel,
	Petr Mladek

[-- Attachment #1: Type: text/plain, Size: 8824 bytes --]

Hi,

[auto build test ERROR on v4.7-rc7]
[cannot apply to next-20160715]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Petr-Mladek/printk-Several-fixes-of-cont-buffer-and-console-handling/20160716-012724
config: i386-tinyconfig (attached as .config)
compiler: gcc-6 (Debian 6.1.1-1) 6.1.1 20160430
reproduce:
        # save the attached .config to linux build tree
        make ARCH=i386 

All error/warnings (new ones prefixed by >>):

   kernel/printk/printk.c: In function 'console_cont_flush':
   kernel/printk/printk.c:2150:11: error: 'struct cont' has no member named 'msg'
     if (!cont.msg->text_len)
              ^
>> kernel/printk/printk.c:2160:24: error: passing argument 1 of 'cont_print_text' from incompatible pointer type [-Werror=incompatible-pointer-types]
     len = cont_print_text(&cont, text, size);
                           ^
   kernel/printk/printk.c:1873:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
>> kernel/printk/printk.c:2160:31: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast [-Wint-conversion]
     len = cont_print_text(&cont, text, size);
                                  ^~~~
   kernel/printk/printk.c:1873:15: note: expected 'size_t {aka unsigned int}' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
>> kernel/printk/printk.c:2160:8: error: too many arguments to function 'cont_print_text'
     len = cont_print_text(&cont, text, size);
           ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:1873:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2163:27: error: 'struct cont' has no member named 'msg'
     call_console_drivers(cont.msg->level, NULL, 0, text, len);
                              ^
   kernel/printk/printk.c: In function 'console_unlock':
   kernel/printk/printk.c:2262:7: error: 'cont_console_len' undeclared (first use in this function)
      if (cont_console_len && cont_console_seq == console_seq) {
          ^~~~~~~~~~~~~~~~
   kernel/printk/printk.c:2262:7: note: each undeclared identifier is reported only once for each function it appears in
>> kernel/printk/printk.c:2262:27: error: 'cont_console_seq' undeclared (first use in this function)
      if (cont_console_len && cont_console_seq == console_seq) {
                              ^~~~~~~~~~~~~~~~
>> kernel/printk/printk.c:2265:13: error: 'struct cont' has no member named 'owner'
       fake_cont.owner = NULL;
                ^
   kernel/printk/printk.c:2266:13: error: 'struct cont' has no member named 'msg'
       fake_cont.msg = msg;
                ^
>> kernel/printk/printk.c:2267:13: error: 'struct cont' has no member named 'buf'
       fake_cont.buf = log_text(msg);
                ^
   kernel/printk/printk.c:2269:27: error: passing argument 1 of 'cont_print_text' from incompatible pointer type [-Werror=incompatible-pointer-types]
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
                              ^
   kernel/printk/printk.c:1873:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2269:39: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast [-Wint-conversion]
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
                                          ^~~~
   kernel/printk/printk.c:1873:15: note: expected 'size_t {aka unsigned int}' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:2269:11: error: too many arguments to function 'cont_print_text'
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
              ^~~~~~~~~~~~~~~
   kernel/printk/printk.c:1873:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/cont_print_text +2160 kernel/printk/printk.c

  2144	{
  2145		unsigned long flags;
  2146		size_t len;
  2147	
  2148		raw_spin_lock_irqsave(&logbuf_lock, flags);
  2149	
> 2150		if (!cont.msg->text_len)
  2151			goto out;
  2152	
  2153		/*
  2154		 * If the partially printed line is already stored in
  2155		 * the ring buffer, it will be handled with the other lines.
  2156		 */
  2157		if (console_seq < log_next_seq)
  2158			goto out;
  2159	
> 2160		len = cont_print_text(&cont, text, size);
  2161		raw_spin_unlock(&logbuf_lock);
  2162		stop_critical_timings();
> 2163		call_console_drivers(cont.msg->level, NULL, 0, text, len);
  2164		start_critical_timings();
  2165		local_irq_restore(flags);
  2166		return;
  2167	out:
  2168		raw_spin_unlock_irqrestore(&logbuf_lock, flags);
  2169	}
  2170	
  2171	/**
  2172	 * console_unlock - unlock the console system
  2173	 *
  2174	 * Releases the console_lock which the caller holds on the console system
  2175	 * and the console driver list.
  2176	 *
  2177	 * While the console_lock was held, console output may have been buffered
  2178	 * by printk().  If this is the case, console_unlock(); emits
  2179	 * the output prior to releasing the lock.
  2180	 *
  2181	 * If there is output waiting, we wake /dev/kmsg and syslog() users.
  2182	 *
  2183	 * console_unlock(); may be called from any context.
  2184	 */
  2185	void console_unlock(void)
  2186	{
  2187		static char ext_text[CONSOLE_EXT_LOG_MAX];
  2188		static char text[LOG_LINE_MAX + PREFIX_MAX];
  2189		static u64 seen_seq;
  2190		unsigned long flags;
  2191		bool wake_klogd = false;
  2192		bool do_cond_resched, retry;
  2193	
  2194		if (console_suspended) {
  2195			up_console_sem();
  2196			return;
  2197		}
  2198	
  2199		/*
  2200		 * Console drivers are called under logbuf_lock, so
  2201		 * @console_may_schedule should be cleared before; however, we may
  2202		 * end up dumping a lot of lines, for example, if called from
  2203		 * console registration path, and should invoke cond_resched()
  2204		 * between lines if allowable.  Not doing so can cause a very long
  2205		 * scheduling stall on a slow console leading to RCU stall and
  2206		 * softlockup warnings which exacerbate the issue with more
  2207		 * messages practically incapacitating the system.
  2208		 */
  2209		do_cond_resched = console_may_schedule;
  2210		console_may_schedule = 0;
  2211	
  2212	again:
  2213		/*
  2214		 * We released the console_sem lock, so we need to recheck if
  2215		 * cpu is online and (if not) is there at least one CON_ANYTIME
  2216		 * console.
  2217		 */
  2218		if (!can_use_console()) {
  2219			console_locked = 0;
  2220			up_console_sem();
  2221			return;
  2222		}
  2223	
  2224		/* flush buffered message fragment immediately to console */
  2225		console_cont_flush(text, sizeof(text));
  2226	
  2227		for (;;) {
  2228			struct printk_log *msg;
  2229			size_t ext_len = 0;
  2230			size_t len;
  2231			int level;
  2232	
  2233			raw_spin_lock_irqsave(&logbuf_lock, flags);
  2234			if (seen_seq != log_next_seq) {
  2235				wake_klogd = true;
  2236				seen_seq = log_next_seq;
  2237			}
  2238	
  2239			if (console_seq < log_first_seq) {
  2240				len = sprintf(text, "** %u printk messages dropped ** ",
  2241					      (unsigned)(log_first_seq - console_seq));
  2242	
  2243				/* messages are gone, move to first one */
  2244				console_seq = log_first_seq;
  2245				console_idx = log_first_idx;
  2246				console_prev = 0;
  2247			} else {
  2248				len = 0;
  2249			}
  2250	
  2251			if (console_seq == log_next_seq)
  2252				break;
  2253	
  2254			msg = log_from_idx(console_idx);
  2255			level = msg->level;
  2256	
  2257			/*
  2258			 * The line might be already partially printed from the cont
  2259			 * buffer. In this case, flush the rest using a fake
  2260			 * cont buffer.
  2261			 */
> 2262			if (cont_console_len && cont_console_seq == console_seq) {
  2263				struct cont fake_cont;
  2264	
> 2265				fake_cont.owner = NULL;
  2266				fake_cont.msg = msg;
> 2267				fake_cont.buf = log_text(msg);
  2268	
  2269				len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
  2270	

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 6334 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH POC 2/4] printk: Do not block cont buffer by partially flushed lines
  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
  1 sibling, 0 replies; 9+ messages in thread
From: kbuild test robot @ 2016-07-15 22:08 UTC (permalink / raw)
  To: Petr Mladek
  Cc: kbuild-all, Andrew Morton, Sergey Senozhatsky, Jiri Kosina,
	Jan Kara, Tejun Heo, Tetsuo Handa, Byungchul Park, linux-kernel,
	Petr Mladek

[-- Attachment #1: Type: text/plain, Size: 4977 bytes --]

Hi,

[auto build test WARNING on v4.7-rc7]
[cannot apply to next-20160715]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Petr-Mladek/printk-Several-fixes-of-cont-buffer-and-console-handling/20160716-012724
config: ia64-allnoconfig (attached as .config)
compiler: ia64-linux-gcc (GCC) 4.9.0
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=ia64 

All warnings (new ones prefixed by >>):

   kernel/printk/printk.c: In function 'console_cont_flush':
   kernel/printk/printk.c:2150:11: error: 'struct cont' has no member named 'msg'
     if (!cont.msg->text_len)
              ^
>> kernel/printk/printk.c:2160:8: warning: passing argument 1 of 'cont_print_text' from incompatible pointer type
     len = cont_print_text(&cont, text, size);
           ^
   kernel/printk/printk.c:1873:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^
   kernel/printk/printk.c:2160:8: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast
     len = cont_print_text(&cont, text, size);
           ^
   kernel/printk/printk.c:1873:15: note: expected 'size_t' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^
   kernel/printk/printk.c:2160:8: error: too many arguments to function 'cont_print_text'
     len = cont_print_text(&cont, text, size);
           ^
   kernel/printk/printk.c:1873:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^
   kernel/printk/printk.c:2163:27: error: 'struct cont' has no member named 'msg'
     call_console_drivers(cont.msg->level, NULL, 0, text, len);
                              ^
   kernel/printk/printk.c: In function 'console_unlock':
   kernel/printk/printk.c:2262:7: error: 'cont_console_len' undeclared (first use in this function)
      if (cont_console_len && cont_console_seq == console_seq) {
          ^
   kernel/printk/printk.c:2262:7: note: each undeclared identifier is reported only once for each function it appears in
   kernel/printk/printk.c:2262:27: error: 'cont_console_seq' undeclared (first use in this function)
      if (cont_console_len && cont_console_seq == console_seq) {
                              ^
   kernel/printk/printk.c:2265:13: error: 'struct cont' has no member named 'owner'
       fake_cont.owner = NULL;
                ^
   kernel/printk/printk.c:2266:13: error: 'struct cont' has no member named 'msg'
       fake_cont.msg = msg;
                ^
   kernel/printk/printk.c:2267:13: error: 'struct cont' has no member named 'buf'
       fake_cont.buf = log_text(msg);
                ^
   kernel/printk/printk.c:2269:11: warning: passing argument 1 of 'cont_print_text' from incompatible pointer type
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
              ^
   kernel/printk/printk.c:1873:15: note: expected 'char *' but argument is of type 'struct cont *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^
   kernel/printk/printk.c:2269:11: warning: passing argument 2 of 'cont_print_text' makes integer from pointer without a cast
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
              ^
   kernel/printk/printk.c:1873:15: note: expected 'size_t' but argument is of type 'char *'
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^
   kernel/printk/printk.c:2269:11: error: too many arguments to function 'cont_print_text'
       len += cont_print_text(&fake_cont, text + len, sizeof(text) - len);
              ^
   kernel/printk/printk.c:1873:15: note: declared here
    static size_t cont_print_text(char *text, size_t size) { return 0; }
                  ^

vim +/cont_print_text +2160 kernel/printk/printk.c

  2144	{
  2145		unsigned long flags;
  2146		size_t len;
  2147	
  2148		raw_spin_lock_irqsave(&logbuf_lock, flags);
  2149	
> 2150		if (!cont.msg->text_len)
  2151			goto out;
  2152	
  2153		/*
  2154		 * If the partially printed line is already stored in
  2155		 * the ring buffer, it will be handled with the other lines.
  2156		 */
  2157		if (console_seq < log_next_seq)
  2158			goto out;
  2159	
> 2160		len = cont_print_text(&cont, text, size);
  2161		raw_spin_unlock(&logbuf_lock);
  2162		stop_critical_timings();
  2163		call_console_drivers(cont.msg->level, NULL, 0, text, len);

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation

[-- Attachment #2: .config.gz --]
[-- Type: application/octet-stream, Size: 5611 bytes --]

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2016-07-15 22:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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 ` [PATCH POC 4/4] printk: Correctly replay buffer log for a new console Petr Mladek
2016-07-15 18:27   ` kbuild test robot

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.