[PATCH 1/2] printk: Make continuation flags from /dev/kmsg useful again

From: James Byrne
Date: Tue Nov 19 2019 - 12:08:59 EST


Commit 5aa068ea4082 ("printk: remove games with previous record flags")
abolished the practice of setting the log flag to 'c' for the first
continuation line and '+' for subsequent lines. Since this change all
continuation lines are flagged with 'c' and '+' is never used.

>From the point of view of a consumer of /dev/kmsg, the behaviour now
is not very useful because you cannot join lines together based on the
'c' flag since you do not know whether a line starting with 'c' was
actually a continuation of the previous line or not.

This commit changes the flag field emitted in /dev/kmsg to expose the
log buffer flags in a more useful way:

- If LOG_NEWLINE=1 and LOG_CONT=0 the flag will be '-', meaning this is
a single self-contained line.
- If LOG_NEWLINE=0 and LOG_CONT=0 the flag will be 'c', meaning that
this is potentially the start of a sequence of continuation lines.
- If LOG_NEWLINE=0 and LOG_CONT=1 the flag will be '+', meaning that
this is the middle of a sequence of continuation lines.
- If LOG_NEWLINE=1 and LOG_CONT=1 the flag will be '*', meaning that
this is the end of a sequence of continuation lines.

This allows a consumer to concatenate continuations in a straightforward
manner.

Signed-off-by: James Byrne <james.byrne@xxxxxxxxxxxxxxxxx>
---

Documentation/ABI/testing/dev-kmsg | 14 ++++++++------
kernel/printk/printk.c | 19 +++++++++++++++++--
2 files changed, 25 insertions(+), 8 deletions(-)

diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg
index f307506eb54c..6326deeaf5e3 100644
--- a/Documentation/ABI/testing/dev-kmsg
+++ b/Documentation/ABI/testing/dev-kmsg
@@ -90,12 +90,14 @@ Description: The /dev/kmsg character device node provides userspace access
+sound:card0 - subsystem:devname

The flags field carries '-' by default. A 'c' indicates a
- fragment of a line. Note, that these hints about continuation
- lines are not necessarily correct, and the stream could be
- interleaved with unrelated messages, but merging the lines in
- the output usually produces better human readable results. A
- similar logic is used internally when messages are printed to
- the console, /proc/kmsg or the syslog() syscall.
+ fragment of a line. Following fragments are flagged with '+'
+ and the final fragment in a sequence is flagged with '*'. Note
+ that these hints about continuation lines are not necessarily
+ correct, and the stream could be interleaved with unrelated
+ messages, but merging the lines in the output usually produces
+ better human readable results. A similar logic is used
+ internally when messages are printed to the console, /proc/kmsg
+ or the syslog() syscall.

By default, kernel tries to avoid fragments by concatenating
when it can and fragments are rare; however, when extended
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index ca65327a6de8..a3db7f5e56d9 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -715,7 +715,7 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,
struct printk_log *msg, u64 seq)
{
u64 ts_usec = msg->ts_nsec;
- char caller[20];
+ char flag, caller[20];
#ifdef CONFIG_PRINTK_CALLER
u32 id = msg->caller_id;

@@ -727,9 +727,24 @@ static ssize_t msg_print_ext_header(char *buf, size_t size,

do_div(ts_usec, 1000);

+ switch (msg->flags & (LOG_CONT|LOG_NEWLINE)) {
+ case LOG_CONT|LOG_NEWLINE:
+ flag = '*';
+ break;
+ case LOG_CONT:
+ flag = '+';
+ break;
+ case LOG_NEWLINE:
+ flag = '-';
+ break;
+ default:
+ flag = 'c';
+ break;
+ }
+
return scnprintf(buf, size, "%u,%llu,%llu,%c%s;",
(msg->facility << 3) | msg->level, seq, ts_usec,
- msg->flags & LOG_CONT ? 'c' : '-', caller);
+ flag, caller);
}

static ssize_t msg_print_ext_body(char *buf, size_t size,
--
2.24.0