kmsg: export printk records to the /dev/kmsg interface
Subsystems (2)
PATCH 1/1 kmsg: export printk records to the /dev/kmsg interface
From: Kay Sievers <[email protected]>
Subject: kmsg: export printk records to the /dev/kmsg interface
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
--- drivers/char/mem.c | 61 --------- include/linux/printk.h | 2 kernel/printk.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 316 insertions(+), 60 deletions(-)
drivers/char/mem.c +1 -60
@@ -807,65 +807,6 @@ static const struct file_operations oldm };#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;
@@ -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
include/linux/printk.h +2 -0
@@ -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 ,
kernel/printk.c +313 -0
331 lines not on this page · raw message