All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] printk: more log flag simplification
@ 2014-07-22 14:01 Alex Elder
  2014-07-22 14:01 ` [PATCH v2 1/2] printk: kill LOG_CONT Alex Elder
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Alex Elder @ 2014-07-22 14:01 UTC (permalink / raw)
  To: akpm; +Cc: kay, pmladek, bp, john.stultz, jack, linux-kernel

This series eliminates the LOG_CONT entirely from the printk/log code.
It builds on another series, posted earlier today:
    http://www.spinics.net/lists/kernel/msg1791665.html
This series was originally longer, but in review I was reminded
that some of the simplifications I had done were not valid.

The first patch exploits the fact that LOG_CONT and LOG_NEWLINE
are inverses, and uses LOG_NEWLINE (or its negation) anywhere
LOG_CONT is used.  As a result, LOG_CONT is no longer needed, so
it's eliminated.

The second patch improves some comments and makes a few small
code cleanups, now that it's gone through this transformation.

					-Alex

This series is available here:
    http://git.linaro.org/landing-teams/working/broadcom/kernel.git
    Branch review/more-printk-flags-v2
It is based on branch review/printk-flags-v6 in that same repository.

Alex Elder (2):
  printk: kill LOG_CONT
  printk: improve some commentary; tidy up

 kernel/printk/printk.c | 99 ++++++++++++++++++++++++++++++--------------------
 1 file changed, 59 insertions(+), 40 deletions(-)

-- 
1.9.1


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

* [PATCH v2 1/2] printk: kill LOG_CONT
  2014-07-22 14:01 [PATCH v2 0/2] printk: more log flag simplification Alex Elder
@ 2014-07-22 14:01 ` Alex Elder
  2014-07-22 14:01 ` [PATCH v2 2/2] printk: improve some commentary; tidy up Alex Elder
  2014-07-22 14:24 ` [PATCH v2 0/2] printk: more log flag simplification Borislav Petkov
  2 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2014-07-22 14:01 UTC (permalink / raw)
  To: akpm; +Cc: kay, pmladek, bp, john.stultz, jack, linux-kernel

The LOG_CONT and LOG_NEWLINE flags are mutually exclusive, i.e.,
the presence of LOG_NEWLINE implies the absense of LOG_CONT, and
vice-versa.  As a result, wherever LOG_CONT is used, we can
equivalently substitute !LOG_NEWLINE; and we can use LOG_NEWLINE
wherever !LOG_CONT is used.

Switch to using LOG_NEWLINE only, and get rid of LOG_CONT.  Make
some refinements on a nearby block of comments.

Signed-off-by: Alex Elder <elder@linaro.org>
---
 kernel/printk/printk.c | 42 +++++++++++++++++++++---------------------
 1 file changed, 21 insertions(+), 21 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 6848e7d..49c9238 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -211,7 +211,6 @@ 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 */
 };
 
 struct printk_log {
@@ -613,22 +612,25 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
 	do_div(ts_usec, 1000);
 
 	/*
-	 * If we couldn't merge continuation line fragments during the print,
-	 * export the stored flags to allow an optional external merge of the
-	 * records. Merging the records isn't always necessarily correct, like
-	 * when we hit a race during printing. In most cases though, it produces
-	 * better readable output. 'c' in the record flags mark the first
-	 * fragment of a line, '+' the following.
+	 * Sometimes it's necessary to flush an incomplete record to the log.
+	 * When this happens, consecutive records should be merged to produce
+	 * a logically complete message.
+	 *
+	 * Indicate this to user space with a flag character.  A 'c' indicates
+	 * the first of a series of incomplete log records.  A '+' indicates
+	 * a record that should be merged with one or more earlier records.
+	 * And a '-' indicates a "normal" self-contained single record.
 	 */
-	if ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))
+	if (!(user->prev & LOG_NEWLINE) && !(msg->flags & LOG_PREFIX))
 		cont = '+';
-	else if (msg->flags & LOG_CONT)
+	else if (!(msg->flags & LOG_NEWLINE))
 		cont = 'c';
 	else
 		cont = '-';
 
 	/* Insert a newline if the previous line was not terminated properly */
-	insert_newline = (user->prev & LOG_CONT) && (msg->flags & LOG_PREFIX);
+	insert_newline = !(user->prev & LOG_NEWLINE) &&
+			    (msg->flags & LOG_PREFIX);
 	len = sprintf(user->buf, "%s%u,%llu,%llu,%c;",
 		      insert_newline ? "\n" : "",
 		      (msg->facility << 3) | msg->level,
@@ -1007,13 +1009,13 @@ static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
 	bool newline = true;
 	size_t len = 0;
 
-	if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))
+	if (!(prev & LOG_NEWLINE) && !(msg->flags & LOG_PREFIX))
 		prefix = false;
 
-	if (msg->flags & LOG_CONT)
+	if (!(msg->flags & LOG_NEWLINE))
 		newline = false;
 
-	if ((prev & LOG_CONT) && (msg->flags & LOG_PREFIX) && len < size) {
+	if (!(prev & LOG_NEWLINE) && (msg->flags & LOG_PREFIX) && len < size) {
 		if (buf)
 			buf[len++] = '\n';
 		else
@@ -1081,7 +1083,7 @@ static int syslog_print(char __user *buf, int size)
 			 */
 			syslog_seq = log_first_seq;
 			syslog_idx = log_first_idx;
-			syslog_prev &= LOG_NEWLINE|LOG_CONT;
+			syslog_prev &= LOG_NEWLINE;
 			syslog_partial = 0;
 		}
 		if (syslog_seq == log_next_seq) {
@@ -1210,7 +1212,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
 				 */
 				seq = log_first_seq;
 				idx = log_first_idx;
-				prev &= LOG_NEWLINE|LOG_CONT;
+				prev &= LOG_NEWLINE;
 			}
 		}
 	}
@@ -1319,7 +1321,7 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
 			 */
 			syslog_seq = log_first_seq;
 			syslog_idx = log_first_idx;
-			syslog_prev &= LOG_NEWLINE|LOG_CONT;
+			syslog_prev &= LOG_NEWLINE;
 			syslog_partial = 0;
 		}
 		if (from_file) {
@@ -1534,7 +1536,7 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 
 	if (cont.len + len > sizeof(cont.buf)) {
 		/* the line gets too long, split it up in separate records */
-		cont_flush(LOG_CONT);
+		cont_flush(0);
 		return false;
 	}
 
@@ -1552,7 +1554,7 @@ static bool cont_add(int facility, int level, const char *text, size_t len)
 	cont.len += len;
 
 	if (cont.len > (sizeof(cont.buf) * 80) / 100)
-		cont_flush(LOG_CONT);
+		cont_flush(0);
 
 	return true;
 }
@@ -1665,8 +1667,6 @@ asmlinkage int vprintk_emit(int facility, int level,
 	if (text_len && text[text_len-1] == '\n') {
 		text_len--;
 		lflags = LOG_NEWLINE;
-	} else {
-		lflags = LOG_CONT;
 	}
 
 	/* strip kernel syslog prefix and extract log level or control flags */
@@ -2167,7 +2167,7 @@ again:
 		if (console_seq < log_first_seq) {
 			len = sprintf(text,
 				      "%s** %u printk messages dropped **\n",
-				      (console_prev & LOG_CONT) ? "\n" : "",
+				      (console_prev & LOG_NEWLINE) ? "" : "\n",
 				      (unsigned)(log_first_seq - console_seq));
 			/* Messages are gone, move to first one. */
 			console_seq = log_first_seq;
-- 
1.9.1


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

* [PATCH v2 2/2] printk: improve some commentary; tidy up
  2014-07-22 14:01 [PATCH v2 0/2] printk: more log flag simplification Alex Elder
  2014-07-22 14:01 ` [PATCH v2 1/2] printk: kill LOG_CONT Alex Elder
@ 2014-07-22 14:01 ` Alex Elder
  2014-07-22 14:24 ` [PATCH v2 0/2] printk: more log flag simplification Borislav Petkov
  2 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2014-07-22 14:01 UTC (permalink / raw)
  To: akpm; +Cc: kay, pmladek, bp, john.stultz, jack, linux-kernel

Add some comments to explain how the log flags are used to control
how records get formatted.  Also add and refine some comments in
vprintk_emit().

Now that we're done fixing up log record flags, simplify how they're
used in computing some local variable values in msg_print_text().

Use a local variable "flush_cont" in vprintk_emit() to factor out a
common expression used later in that function.

Signed-off-by: Alex Elder <elder@linaro.org>
---
 kernel/printk/printk.c | 63 ++++++++++++++++++++++++++++++++------------------
 1 file changed, 41 insertions(+), 22 deletions(-)

diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index 49c9238..cecdc1b 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -141,6 +141,12 @@ EXPORT_SYMBOL(console_set_on_cmdline);
 static int console_may_schedule;
 
 /*
+ * Each call to printk() fills a record in a circular log buffer.
+ * The contents of the log buffer are read by various subsystems
+ * (including the console subsystem), each of which formats the
+ * content of log buffers for human consumption.  Flags in each
+ * log record are used to track formatting-related state.
+ *
  * The printk log buffer consists of a chain of concatenated variable
  * length records. Every record starts with a record header, containing
  * the overall length of the record.
@@ -150,7 +156,7 @@ static int console_may_schedule;
  * are stored..
  *
  * If the heads indicate available messages, the length in the header
- * tells the start next message. A length == 0 for the next message
+ * tells the start of the next message. A length == 0 for the next message
  * indicates a wrap-around to the beginning of the buffer.
  *
  * Every record carries the monotonic timestamp in microseconds, as well as
@@ -192,6 +198,16 @@ static int console_may_schedule;
  *         67                           "g"
  *   0032     00 00 00                  padding to next message header
  *
+ * If a printk() call contains no newline, its content is saved in a
+ * special "cont" buffer rather than being written directly into the
+ * log.  One or more follow-in printk() calls from the same source
+ * can then be combined into a single newline-terminated message (if
+ * possible) before the combined result is saved into a log record.
+ * Occasionally a buffered/partial message needs to be flushed to
+ * the log before the logically next printk() call is seen.  When
+ * this occurs, the incomplete record (with no LOG_NEWLINE) will
+ * be followed by a new record marked LOG_PREFIX.
+ *
  * The 'struct printk_log' buffer header must never be directly exported to
  * userspace, it is a kernel-private implementation detail that might
  * need to be changed in the future, when the requirements change.
@@ -1005,17 +1021,14 @@ static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev,
 {
 	const char *text = log_text(msg);
 	size_t text_size = msg->text_len;
-	bool prefix = true;
-	bool newline = true;
 	size_t len = 0;
+	bool prefix;
+	bool newline;
 
-	if (!(prev & LOG_NEWLINE) && !(msg->flags & LOG_PREFIX))
-		prefix = false;
-
-	if (!(msg->flags & LOG_NEWLINE))
-		newline = false;
-
-	if (!(prev & LOG_NEWLINE) && (msg->flags & LOG_PREFIX) && len < size) {
+	prefix = (prev & LOG_NEWLINE) || (msg->flags & LOG_PREFIX);
+	newline = !!(msg->flags & LOG_NEWLINE);
+	/* Insert a newline if we're terminating the previous line early */
+	if (prefix && !(prev & LOG_NEWLINE) && len < size) {
 		if (buf)
 			buf[len++] = '\n';
 		else
@@ -1600,6 +1613,7 @@ asmlinkage int vprintk_emit(int facility, int level,
 	int this_cpu;
 	int printed_len = 0;
 	bool in_sched = false;
+	bool flush_cont = false;
 	/* cpu currently holding logbuf_lock in this function */
 	static volatile unsigned int logbuf_cpu = UINT_MAX;
 
@@ -1698,12 +1712,16 @@ asmlinkage int vprintk_emit(int facility, int level,
 	if (dict)
 		lflags = LOG_PREFIX|LOG_NEWLINE;
 
+	/*
+	 * If the previous printk() call had no newline, it will be buffered.
+	 * If the buffered message was produced by someone else, or if this
+	 * call is forcing a new record, we will need to flush the buffer
+	 * rather than merge this message into it.
+	 */
+	flush_cont = (cont.owner != current) || (lflags & LOG_PREFIX);
 	if (!(lflags & LOG_NEWLINE)) {
-		/*
-		 * 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 the buffered record conflicts, flush it first. */
+		if (cont.len && flush_cont)
 			cont_flush(LOG_NEWLINE);
 
 		/* buffer line if possible, otherwise store it right away */
@@ -1716,20 +1734,21 @@ asmlinkage int vprintk_emit(int facility, int level,
 		bool stored = false;
 
 		/*
-		 * If an earlier newline was missing and it was the same task,
-		 * either merge it with the current buffer and flush, or if
-		 * there was a race with interrupts (prefix == true) then just
-		 * flush it out and store this line separately.
-		 * If the preceding printk was from a different task and missed
-		 * a newline, flush and append the newline.
+		 * If there's a buffered message, try to merge with
+		 * it, then flush whatever's buffered to the log.
 		 */
 		if (cont.len) {
-			if (cont.owner == current && !(lflags & LOG_PREFIX))
+			if (!flush_cont)
 				stored = cont_add(facility, level, text,
 						  text_len);
 			cont_flush(LOG_NEWLINE);
 		}
 
+		/*
+		 * Record how much we just formatted.  If cont_add() didn't
+		 * combine this message with the buffered one we still have
+		 * to store this one to the log.
+		 */
 		if (stored)
 			printed_len += text_len;
 		else
-- 
1.9.1


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

* Re: [PATCH v2 0/2] printk: more log flag simplification
  2014-07-22 14:01 [PATCH v2 0/2] printk: more log flag simplification Alex Elder
  2014-07-22 14:01 ` [PATCH v2 1/2] printk: kill LOG_CONT Alex Elder
  2014-07-22 14:01 ` [PATCH v2 2/2] printk: improve some commentary; tidy up Alex Elder
@ 2014-07-22 14:24 ` Borislav Petkov
  2014-07-22 15:55   ` Alex Elder
  2 siblings, 1 reply; 5+ messages in thread
From: Borislav Petkov @ 2014-07-22 14:24 UTC (permalink / raw)
  To: Alex Elder; +Cc: akpm, kay, pmladek, john.stultz, jack, linux-kernel

On Tue, Jul 22, 2014 at 09:01:55AM -0500, Alex Elder wrote:
> This series eliminates the LOG_CONT entirely from the printk/log code.
> It builds on another series, posted earlier today:
>     http://www.spinics.net/lists/kernel/msg1791665.html
> This series was originally longer, but in review I was reminded
> that some of the simplifications I had done were not valid.
> 
> The first patch exploits the fact that LOG_CONT and LOG_NEWLINE
> are inverses, and uses LOG_NEWLINE (or its negation) anywhere
> LOG_CONT is used.  As a result, LOG_CONT is no longer needed, so
> it's eliminated.
> 
> The second patch improves some comments and makes a few small
> code cleanups, now that it's gone through this transformation.

This is getting ridiculous - you've been spamming me with printk patches
like crazy every day! I told you to wait a bit with a resend until
people have had a chance to review them, but you don't seem to care.

Would you please remove me from your CC list?

Thank you.

-- 
Regards/Gruss,
    Boris.

Sent from a fat crate under my desk. Formatting is fine.
--

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

* Re: [PATCH v2 0/2] printk: more log flag simplification
  2014-07-22 14:24 ` [PATCH v2 0/2] printk: more log flag simplification Borislav Petkov
@ 2014-07-22 15:55   ` Alex Elder
  0 siblings, 0 replies; 5+ messages in thread
From: Alex Elder @ 2014-07-22 15:55 UTC (permalink / raw)
  To: Borislav Petkov; +Cc: akpm, kay, pmladek, john.stultz, jack, linux-kernel

On 07/22/2014 09:24 AM, Borislav Petkov wrote:
> On Tue, Jul 22, 2014 at 09:01:55AM -0500, Alex Elder wrote:
>> This series eliminates the LOG_CONT entirely from the printk/log code.
>> It builds on another series, posted earlier today:
>>     http://www.spinics.net/lists/kernel/msg1791665.html
>> This series was originally longer, but in review I was reminded
>> that some of the simplifications I had done were not valid.
>>
>> The first patch exploits the fact that LOG_CONT and LOG_NEWLINE
>> are inverses, and uses LOG_NEWLINE (or its negation) anywhere
>> LOG_CONT is used.  As a result, LOG_CONT is no longer needed, so
>> it's eliminated.
>>
>> The second patch improves some comments and makes a few small
>> code cleanups, now that it's gone through this transformation.
> 
> This is getting ridiculous - you've been spamming me with printk patches
> like crazy every day! I told you to wait a bit with a resend until
> people have had a chance to review them, but you don't seem to care.
> 
> Would you please remove me from your CC list?

Yes.	-Alex

> Thank you.
> 


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

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

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-07-22 14:01 [PATCH v2 0/2] printk: more log flag simplification Alex Elder
2014-07-22 14:01 ` [PATCH v2 1/2] printk: kill LOG_CONT Alex Elder
2014-07-22 14:01 ` [PATCH v2 2/2] printk: improve some commentary; tidy up Alex Elder
2014-07-22 14:24 ` [PATCH v2 0/2] printk: more log flag simplification Borislav Petkov
2014-07-22 15:55   ` Alex Elder

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.