Skip to content

Commit

Permalink
kmsg: export printk records to the /dev/kmsg interface
Browse files Browse the repository at this point in the history
Support for multiple concurrent readers of /dev/kmsg, with read(),
seek(), poll() support. Output of message sequence numbers, to allow
userspace log consumers to reliably reconnect and reconstruct their
state at any given time. After open("/dev/kmsg"), read() always
returns *all* buffered records. If only future messages should be
read, SEEK_END can be used. In case records get overwritten while
/dev/kmsg is held open, or records get faster overwritten than they
are read, the next read() will return -EPIPE and the current reading
position gets updated to the next available record. The passed
sequence numbers allow the log consumer to calculate the amount of
lost messages.

  [root@mop ~]# cat /dev/kmsg
  5,0,0;Linux version 3.4.0-rc1+ (kay@mop) (gcc version 4.7.0 20120315 ...
  6,159,423091;ACPI: PCI Root Bridge [PCI0] (domain 0000 [bus 00-ff])
  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,341,6081421;FDC 0 is a S82078B
  6,345,6154686;microcode: CPU0 sig=0x623, pf=0x0, revision=0x0
  7,346,6156968;sr 1:0:0:0: Attached scsi CD-ROM sr0
   SUBSYSTEM=scsi
   DEVICE=+scsi:1:0:0:0
  6,347,6289375;microcode: CPU1 sig=0x623, pf=0x0, revision=0x0

Cc: Karel Zak <kzak@redhat.com>
Tested-by: William Douglas <william.douglas@intel.com>
Signed-off-by: Kay Sievers <kay@vrfy.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
kaysievers authored and gregkh committed May 8, 2012
1 parent 7ff9554 commit e11fea9
Show file tree
Hide file tree
Showing 3 changed files with 316 additions and 60 deletions.
61 changes: 1 addition & 60 deletions drivers/char/mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -807,65 +807,6 @@ static const struct file_operations oldmem_fops = {
};
#endif

static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
unsigned long count, loff_t pos)
{
char *buf, *line;
int i;
int level = default_message_loglevel;
int facility = 1; /* LOG_USER */
size_t len = iov_length(iv, count);
ssize_t ret = len;

if (len > 1024)
return -EINVAL;
buf = kmalloc(len+1, GFP_KERNEL);
if (buf == NULL)
return -ENOMEM;

line = buf;
for (i = 0; i < count; i++) {
if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len))
goto out;
line += iv[i].iov_len;
}

/*
* Extract and skip the syslog prefix <[0-9]*>. Coming from userspace
* the decimal value represents 32bit, the lower 3 bit are the log
* level, the rest are the log facility.
*
* If no prefix or no userspace facility is specified, we
* enforce LOG_USER, to be able to reliably distinguish
* kernel-generated messages from userspace-injected ones.
*/
line = buf;
if (line[0] == '<') {
char *endp = NULL;

i = simple_strtoul(line+1, &endp, 10);
if (endp && endp[0] == '>') {
level = i & 7;
if (i >> 3)
facility = i >> 3;
endp++;
len -= endp - line;
line = endp;
}
}
line[len] = '\0';

printk_emit(facility, level, NULL, 0, "%s", line);
out:
kfree(buf);
return ret;
}

static const struct file_operations kmsg_fops = {
.aio_write = kmsg_writev,
.llseek = noop_llseek,
};

static const struct memdev {
const char *name;
umode_t mode;
Expand All @@ -884,7 +825,7 @@ static const struct memdev {
[7] = { "full", 0666, &full_fops, NULL },
[8] = { "random", 0666, &random_fops, NULL },
[9] = { "urandom", 0666, &urandom_fops, NULL },
[11] = { "kmsg", 0, &kmsg_fops, NULL },
[11] = { "kmsg", 0644, &kmsg_fops, NULL },
#ifdef CONFIG_CRASH_DUMP
[12] = { "oldmem", 0, &oldmem_fops, NULL },
#endif
Expand Down
2 changes: 2 additions & 0 deletions include/linux/printk.h
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ extern void dump_stack(void) __cold;
no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
#endif

extern const struct file_operations kmsg_fops;

enum {
DUMP_PREFIX_NONE,
DUMP_PREFIX_ADDRESS,
Expand Down
Loading

0 comments on commit e11fea9

Please sign in to comment.