Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d39f3d77 authored by Kay Sievers's avatar Kay Sievers Committed by Greg Kroah-Hartman
Browse files

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: default avatarKay Sievers <kay@vrfy.org>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 96efedf1
Loading
Loading
Loading
Loading
+20 −9
Original line number Diff line number Diff line
@@ -58,16 +58,18 @@ Description: The /dev/kmsg character device node provides userspace access

		The output format consists of a prefix carrying the syslog
		prefix including priority and facility, the 64 bit message
		sequence number and the monotonic timestamp in microseconds.
		The values are separated by a ','. Future extensions might
		add more comma separated values before the terminating ';'.
		Unknown values should be gracefully ignored.
		sequence number and the monotonic timestamp in microseconds,
		and a flag field. All fields are separated by a ','.

		Future extensions might add more comma separated values before
		the terminating ';'. Unknown fields and values should be
		gracefully ignored.

		The human readable text string starts directly after the ';'
		and is terminated by a '\n'. Untrusted values derived from
		hardware or other facilities are printed, therefore
		all non-printable characters in the log message are escaped
		by "\x00" C-style hex encoding.
		all non-printable characters and '\' itself in the log message
		are escaped by "\x00" C-style hex encoding.

		A line starting with ' ', is a continuation line, adding
		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
		userspace.

		Example:
		7,160,424069;pci_root PNP0A03:00: host bridge window [io  0x0000-0x0cf7] (ignored)
		7,160,424069,-;pci_root PNP0A03:00: host bridge window [io  0x0000-0x0cf7] (ignored)
		 SUBSYSTEM=acpi
		 DEVICE=+acpi:PNP0A03:00
		6,339,5140900;NET: Registered protocol family 10
		30,340,5690716;udevd[80]: starting version 181
		6,339,5140900,-;NET: Registered protocol family 10
		30,340,5690716,-;udevd[80]: starting version 181

		The DEVICE= key uniquely identifies devices the following way:
		  b12:8        - block dev_t
@@ -87,4 +89,13 @@ Description: The /dev/kmsg character device node provides userspace access
		  n8           - netdev ifindex
		  +sound:card0 - subsystem:devname

		The flags field carries '-' by default. A 'c' indicates a
		fragment of a line. All following fragments are flagged with
		'+'. Note, that these hints about continuation lines are not
		neccessarily 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.

Users:		dmesg(1), userspace kernel log consumers
+21 −2
Original line number Diff line number Diff line
@@ -361,6 +361,7 @@ static void log_store(int facility, int level,
struct devkmsg_user {
	u64 seq;
	u32 idx;
	enum log_flags prev;
	struct mutex lock;
	char buf[8192];
};
@@ -426,6 +427,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
	struct log *msg;
	u64 ts_usec;
	size_t i;
	char cont = '-';
	size_t len;
	ssize_t ret;

@@ -463,8 +465,25 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
	msg = log_from_idx(user->idx);
	ts_usec = msg->ts_nsec;
	do_div(ts_usec, 1000);
	len = sprintf(user->buf, "%u,%llu,%llu;",
		      (msg->facility << 3) | msg->level, user->seq, ts_usec);

	/*
	 * 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 neccessarily 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.
	 */
	if (msg->flags & LOG_CONT && !(user->prev & LOG_CONT))
		cont = 'c';
	else if ((msg->flags & LOG_CONT) ||
		 ((user->prev & LOG_CONT) && !(msg->flags & LOG_PREFIX)))
		cont = '+';

	len = sprintf(user->buf, "%u,%llu,%llu,%c;",
		      (msg->facility << 3) | msg->level,
		      user->seq, ts_usec, cont);
	user->prev = msg->flags;

	/* escape non-printable characters */
	for (i = 0; i < msg->text_len; i++) {