aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char/mem.c
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-05-02 20:29:41 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-07 20:03:27 -0400
commite11fea92e13fb91c50bacca799a6131c81929986 (patch)
tree3b9204f4eccc6b488b843d6d00e65dc982c50160 /drivers/char/mem.c
parent7ff9554bb578ba02166071d2d487b7fc7d860d62 (diff)
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 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>
Diffstat (limited to 'drivers/char/mem.c')
-rw-r--r--drivers/char/mem.c61
1 files changed, 1 insertions, 60 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c
index cf56614479ef..0e7fbfcbd6e6 100644
--- a/drivers/char/mem.c
+++ b/drivers/char/mem.c
@@ -807,65 +807,6 @@ static const struct file_operations oldmem_fops = {
807}; 807};
808#endif 808#endif
809 809
810static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv,
811 unsigned long count, loff_t pos)
812{
813 char *buf, *line;
814 int i;
815 int level = default_message_loglevel;
816 int facility = 1; /* LOG_USER */
817 size_t len = iov_length(iv, count);
818 ssize_t ret = len;
819
820 if (len > 1024)
821 return -EINVAL;
822 buf = kmalloc(len+1, GFP_KERNEL);
823 if (buf == NULL)
824 return -ENOMEM;
825
826 line = buf;
827 for (i = 0; i < count; i++) {
828 if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len))
829 goto out;
830 line += iv[i].iov_len;
831 }
832
833 /*
834 * Extract and skip the syslog prefix <[0-9]*>. Coming from userspace
835 * the decimal value represents 32bit, the lower 3 bit are the log
836 * level, the rest are the log facility.
837 *
838 * If no prefix or no userspace facility is specified, we
839 * enforce LOG_USER, to be able to reliably distinguish
840 * kernel-generated messages from userspace-injected ones.
841 */
842 line = buf;
843 if (line[0] == '<') {
844 char *endp = NULL;
845
846 i = simple_strtoul(line+1, &endp, 10);
847 if (endp && endp[0] == '>') {
848 level = i & 7;
849 if (i >> 3)
850 facility = i >> 3;
851 endp++;
852 len -= endp - line;
853 line = endp;
854 }
855 }
856 line[len] = '\0';
857
858 printk_emit(facility, level, NULL, 0, "%s", line);
859out:
860 kfree(buf);
861 return ret;
862}
863
864static const struct file_operations kmsg_fops = {
865 .aio_write = kmsg_writev,
866 .llseek = noop_llseek,
867};
868
869static const struct memdev { 810static const struct memdev {
870 const char *name; 811 const char *name;
871 umode_t mode; 812 umode_t mode;
@@ -884,7 +825,7 @@ static const struct memdev {
884 [7] = { "full", 0666, &full_fops, NULL }, 825 [7] = { "full", 0666, &full_fops, NULL },
885 [8] = { "random", 0666, &random_fops, NULL }, 826 [8] = { "random", 0666, &random_fops, NULL },
886 [9] = { "urandom", 0666, &urandom_fops, NULL }, 827 [9] = { "urandom", 0666, &urandom_fops, NULL },
887 [11] = { "kmsg", 0, &kmsg_fops, NULL }, 828 [11] = { "kmsg", 0644, &kmsg_fops, NULL },
888#ifdef CONFIG_CRASH_DUMP 829#ifdef CONFIG_CRASH_DUMP
889 [12] = { "oldmem", 0, &oldmem_fops, NULL }, 830 [12] = { "oldmem", 0, &oldmem_fops, NULL },
890#endif 831#endif