diff options
-rw-r--r-- | Documentation/ABI/testing/dev-kmsg | 29 | ||||
-rw-r--r-- | kernel/printk.c | 23 |
2 files changed, 41 insertions, 11 deletions
diff --git a/Documentation/ABI/testing/dev-kmsg b/Documentation/ABI/testing/dev-kmsg index 281ecc5f9709..7e7e07a82e0e 100644 --- a/Documentation/ABI/testing/dev-kmsg +++ b/Documentation/ABI/testing/dev-kmsg | |||
@@ -58,16 +58,18 @@ Description: The /dev/kmsg character device node provides userspace access | |||
58 | 58 | ||
59 | The output format consists of a prefix carrying the syslog | 59 | The output format consists of a prefix carrying the syslog |
60 | prefix including priority and facility, the 64 bit message | 60 | prefix including priority and facility, the 64 bit message |
61 | sequence number and the monotonic timestamp in microseconds. | 61 | sequence number and the monotonic timestamp in microseconds, |
62 | The values are separated by a ','. Future extensions might | 62 | and a flag field. All fields are separated by a ','. |
63 | add more comma separated values before the terminating ';'. | 63 | |
64 | Unknown values should be gracefully ignored. | 64 | Future extensions might add more comma separated values before |
65 | the terminating ';'. Unknown fields and values should be | ||
66 | gracefully ignored. | ||
65 | 67 | ||
66 | The human readable text string starts directly after the ';' | 68 | The human readable text string starts directly after the ';' |
67 | and is terminated by a '\n'. Untrusted values derived from | 69 | and is terminated by a '\n'. Untrusted values derived from |
68 | hardware or other facilities are printed, therefore | 70 | hardware or other facilities are printed, therefore |
69 | all non-printable characters in the log message are escaped | 71 | all non-printable characters and '\' itself in the log message |
70 | by "\x00" C-style hex encoding. | 72 | are escaped by "\x00" C-style hex encoding. |
71 | 73 | ||
72 | A line starting with ' ', is a continuation line, adding | 74 | A line starting with ' ', is a continuation line, adding |
73 | key/value pairs to the log message, which provide the machine | 75 | key/value pairs to the log message, which provide the machine |
@@ -75,11 +77,11 @@ Description: The /dev/kmsg character device node provides userspace access | |||
75 | userspace. | 77 | userspace. |
76 | 78 | ||
77 | Example: | 79 | Example: |
78 | 7,160,424069;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored) | 80 | 7,160,424069,-;pci_root PNP0A03:00: host bridge window [io 0x0000-0x0cf7] (ignored) |
79 | SUBSYSTEM=acpi | 81 | SUBSYSTEM=acpi |
80 | DEVICE=+acpi:PNP0A03:00 | 82 | DEVICE=+acpi:PNP0A03:00 |
81 | 6,339,5140900;NET: Registered protocol family 10 | 83 | 6,339,5140900,-;NET: Registered protocol family 10 |
82 | 30,340,5690716;udevd[80]: starting version 181 | 84 | 30,340,5690716,-;udevd[80]: starting version 181 |
83 | 85 | ||
84 | The DEVICE= key uniquely identifies devices the following way: | 86 | The DEVICE= key uniquely identifies devices the following way: |
85 | b12:8 - block dev_t | 87 | b12:8 - block dev_t |
@@ -87,4 +89,13 @@ Description: The /dev/kmsg character device node provides userspace access | |||
87 | n8 - netdev ifindex | 89 | n8 - netdev ifindex |
88 | +sound:card0 - subsystem:devname | 90 | +sound:card0 - subsystem:devname |
89 | 91 | ||
92 | The flags field carries '-' by default. A 'c' indicates a | ||
93 | fragment of a line. All following fragments are flagged with | ||
94 | '+'. Note, that these hints about continuation lines are not | ||
95 | neccessarily correct, and the stream could be interleaved with | ||
96 | unrelated messages, but merging the lines in the output | ||
97 | usually produces better human readable results. A similar | ||
98 | logic is used internally when messages are printed to the | ||
99 | console, /proc/kmsg or the syslog() syscall. | ||
100 | |||
90 | Users: dmesg(1), userspace kernel log consumers | 101 | Users: dmesg(1), userspace kernel log consumers |
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++) { |