diff options
author | Kay Sievers <kay.sievers@vrfy.org> | 2011-04-06 22:29:20 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2011-04-19 19:59:58 -0400 |
commit | 7e5b58bcbcb3d7518389c1d82fb6e926f5a9f72c (patch) | |
tree | a4096c1355beb0bfcdc9ea8bb041c3a7da1149b2 | |
parent | 47296b1962ead8301488f0dbe8424c7db7eac635 (diff) |
printk: /dev/kmsg - properly support writev() to avoid interleaved printk() lines
printk: /dev/kmsg - properly support writev() to avoid interleaved printk lines
We should avoid calling printk() in a loop, when we pass a single
string to /dev/kmsg with writev().
Cc: Lennart Poettering <lennart@poettering.net>
Signed-off-by: Kay Sievers <kay.sievers@vrfy.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/char/mem.c | 41 |
1 files changed, 26 insertions, 15 deletions
diff --git a/drivers/char/mem.c b/drivers/char/mem.c index 436a99017998..78923a9f5345 100644 --- a/drivers/char/mem.c +++ b/drivers/char/mem.c | |||
@@ -806,29 +806,40 @@ static const struct file_operations oldmem_fops = { | |||
806 | }; | 806 | }; |
807 | #endif | 807 | #endif |
808 | 808 | ||
809 | static ssize_t kmsg_write(struct file *file, const char __user *buf, | 809 | static ssize_t kmsg_writev(struct kiocb *iocb, const struct iovec *iv, |
810 | size_t count, loff_t *ppos) | 810 | unsigned long count, loff_t pos) |
811 | { | 811 | { |
812 | char *tmp; | 812 | char *line, *p; |
813 | ssize_t ret; | 813 | int len, i; |
814 | ssize_t ret = -EFAULT; | ||
814 | 815 | ||
815 | tmp = kmalloc(count + 1, GFP_KERNEL); | 816 | len = iov_length(iv, count); |
816 | if (tmp == NULL) | 817 | line = p = kmalloc(len + 1, GFP_KERNEL); |
818 | if (line == NULL) | ||
817 | return -ENOMEM; | 819 | return -ENOMEM; |
818 | ret = -EFAULT; | 820 | |
819 | if (!copy_from_user(tmp, buf, count)) { | 821 | /* |
820 | tmp[count] = 0; | 822 | * copy all vectors into a single string, to ensure we do |
821 | ret = printk("%s", tmp); | 823 | * not interleave our log line with other printk calls |
822 | if (ret > count) | 824 | */ |
823 | /* printk can add a prefix */ | 825 | for (i = 0; i < count; i++) { |
824 | ret = count; | 826 | if (copy_from_user(p, iv[i].iov_base, iv[i].iov_len)) |
827 | goto out; | ||
828 | p += iv[i].iov_len; | ||
825 | } | 829 | } |
826 | kfree(tmp); | 830 | p[0] = '\0'; |
831 | |||
832 | ret = printk("%s", line); | ||
833 | /* printk can add a prefix */ | ||
834 | if (ret > len) | ||
835 | ret = len; | ||
836 | out: | ||
837 | kfree(line); | ||
827 | return ret; | 838 | return ret; |
828 | } | 839 | } |
829 | 840 | ||
830 | static const struct file_operations kmsg_fops = { | 841 | static const struct file_operations kmsg_fops = { |
831 | .write = kmsg_write, | 842 | .aio_write = kmsg_writev, |
832 | .llseek = noop_llseek, | 843 | .llseek = noop_llseek, |
833 | }; | 844 | }; |
834 | 845 | ||