diff options
author | Kay Sievers <kay@vrfy.org> | 2012-07-16 21:35:30 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-07-16 21:35:30 -0400 |
commit | d39f3d77c9b1fe7cc33a14beb4a4849af0a4ac22 (patch) | |
tree | bf3a4fd34aa850a5f30f966dfd98a40a424f6b9a /kernel | |
parent | 96efedf1491cdf0616e5e4fff0711cebf20f69c7 (diff) |
kmsg - export "continuation record" flag to /dev/kmsg
In some cases we are forced to store individual records for a continuation
line print.
Export a flag to allow the external re-construction of the line. The flag
allows us to apply a similar logic externally which is used internally when
the console, /proc/kmsg or the syslog() output is printed.
$ cat /dev/kmsg
4,165,0,-;Free swap = 0kB
4,166,0,-;Total swap = 0kB
6,167,0,c;[
4,168,0,+;0
4,169,0,+;1
4,170,0,+;2
4,171,0,+;3
4,172,0,+;]
6,173,0,-;[0 1 2 3 ]
6,174,0,-;Console: colour VGA+ 80x25
6,175,0,-;console [tty0] enabled
Signed-off-by: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/printk.c | 23 |
1 files changed, 21 insertions, 2 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index 6c3d5bf14da2..a41106e19077 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -361,6 +361,7 @@ static void log_store(int facility, int level, | |||
361 | struct devkmsg_user { | 361 | struct devkmsg_user { |
362 | u64 seq; | 362 | u64 seq; |
363 | u32 idx; | 363 | u32 idx; |
364 | enum log_flags prev; | ||
364 | struct mutex lock; | 365 | struct mutex lock; |
365 | char buf[8192]; | 366 | char buf[8192]; |
366 | }; | 367 | }; |
@@ -426,6 +427,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
426 | struct log *msg; | 427 | struct log *msg; |
427 | u64 ts_usec; | 428 | u64 ts_usec; |
428 | size_t i; | 429 | size_t i; |
430 | char cont = '-'; | ||
429 | size_t len; | 431 | size_t len; |
430 | ssize_t ret; | 432 | ssize_t ret; |
431 | 433 | ||
@@ -463,8 +465,25 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
463 | msg = log_from_idx(user->idx); | 465 | msg = log_from_idx(user->idx); |
464 | ts_usec = msg->ts_nsec; | 466 | ts_usec = msg->ts_nsec; |
465 | do_div(ts_usec, 1000); | 467 | do_div(ts_usec, 1000); |
466 | len = sprintf(user->buf, "%u,%llu,%llu;", | 468 | |
467 | (msg->facility << 3) | msg->level, user->seq, ts_usec); | 469 | /* |
470 | * If we couldn't merge continuation line fragments during the print, | ||
471 | * export the stored flags to allow an optional external merge of the | ||
472 | * records. Merging the records isn't always neccessarily correct, like | ||
473 | * when we hit a race during printing. In most cases though, it produces | ||
474 | * better readable output. 'c' in the record flags mark the first | ||
475 | * fragment of a line, '+' the following. | ||
476 | */ | ||
477 | if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT)) | ||
478 | cont = 'c'; | ||
479 | else if ((msg->flags & LOG_CONT) || | ||
480 | ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX))) | ||
481 | cont = '+'; | ||
482 | |||
483 | len = sprintf(user->buf, "%u,%llu,%llu,%c;", | ||
484 | (msg->facility << 3) | msg->level, | ||
485 | user->seq, ts_usec, cont); | ||
486 | user->prev = msg->flags; | ||
468 | 487 | ||
469 | /* escape non-printable characters */ | 488 | /* escape non-printable characters */ |
470 | for (i = 0; i < msg->text_len; i++) { | 489 | for (i = 0; i < msg->text_len; i++) { |