aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2012-05-13 17:30:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2012-05-14 11:42:22 -0400
commit3ce9a7c0ac28561567fadedf1a99272e4970f740 (patch)
tree8a3e9bd983941e75943d0a11dacdd85bce7e5c83 /kernel
parent1fce677971e29ceaa7c569741fa9c685a7b1052a (diff)
printk() - restore prefix/timestamp printing for multi-newline strings
Calls like: printk("\n *** DEADLOCK ***\n\n"); will print 3 properly indented, separated, syslog + timestamp prefixed lines in the log output. Reported-By: Sasha Levin <levinsasha928@gmail.com> Signed-off-by: Kay Sievers <kay@vrfy.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/printk.c127
1 files changed, 76 insertions, 51 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index c42faf97404a..915a8be10b5f 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -448,7 +448,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
448 448
449 /* escape non-printable characters */ 449 /* escape non-printable characters */
450 for (i = 0; i < msg->text_len; i++) { 450 for (i = 0; i < msg->text_len; i++) {
451 char c = log_text(msg)[i]; 451 unsigned char c = log_text(msg)[i];
452 452
453 if (c < ' ' || c >= 128) 453 if (c < ' ' || c >= 128)
454 len += sprintf(user->buf + len, "\\x%02x", c); 454 len += sprintf(user->buf + len, "\\x%02x", c);
@@ -461,7 +461,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf,
461 bool line = true; 461 bool line = true;
462 462
463 for (i = 0; i < msg->dict_len; i++) { 463 for (i = 0; i < msg->dict_len; i++) {
464 char c = log_dict(msg)[i]; 464 unsigned char c = log_dict(msg)[i];
465 465
466 if (line) { 466 if (line) {
467 user->buf[len++] = ' '; 467 user->buf[len++] = ' ';
@@ -785,56 +785,81 @@ static bool printk_time;
785#endif 785#endif
786module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR); 786module_param_named(time, printk_time, bool, S_IRUGO | S_IWUSR);
787 787
788static size_t prepend_timestamp(unsigned long long t, char *buf) 788static size_t print_prefix(const struct log *msg, bool syslog, char *buf)
789{ 789{
790 unsigned long rem_ns; 790 size_t len = 0;
791 791
792 if (!printk_time) 792 if (syslog) {
793 return 0; 793 if (buf) {
794 len += sprintf(buf, "<%u>", msg->level);
795 } else {
796 len += 3;
797 if (msg->level > 9)
798 len++;
799 if (msg->level > 99)
800 len++;
801 }
802 }
794 803
795 if (!buf) 804 if (printk_time) {
796 return 15; 805 if (buf) {
806 unsigned long long ts = msg->ts_nsec;
807 unsigned long rem_nsec = do_div(ts, 1000000000);
797 808
798 rem_ns = do_div(t, 1000000000); 809 len += sprintf(buf + len, "[%5lu.%06lu] ",
810 (unsigned long) ts, rem_nsec / 1000);
811 } else {
812 len += 15;
813 }
814 }
799 815
800 return sprintf(buf, "[%5lu.%06lu] ", 816 return len;
801 (unsigned long) t, rem_ns / 1000);
802} 817}
803 818
804static int syslog_print_line(u32 idx, char *text, size_t size) 819static size_t msg_print_text(const struct log *msg, bool syslog,
820 char *buf, size_t size)
805{ 821{
806 struct log *msg; 822 const char *text = log_text(msg);
807 size_t len; 823 size_t text_size = msg->text_len;
824 size_t len = 0;
808 825
809 msg = log_from_idx(idx); 826 do {
810 if (!text) { 827 const char *next = memchr(text, '\n', text_size);
811 /* calculate length only */ 828 size_t text_len;
812 len = 3;
813 829
814 if (msg->level > 9) 830 if (next) {
815 len++; 831 text_len = next - text;
816 if (msg->level > 99) 832 next++;
817 len++; 833 text_size -= next - text;
818 len += prepend_timestamp(0, NULL); 834 } else {
835 text_len = text_size;
836 }
819 837
820 len += msg->text_len; 838 if (buf) {
821 len++; 839 if (print_prefix(msg, syslog, NULL) +
822 return len; 840 text_len + 1>= size - len)
823 } 841 break;
842
843 len += print_prefix(msg, syslog, buf + len);
844 memcpy(buf + len, text, text_len);
845 len += text_len;
846 buf[len++] = '\n';
847 } else {
848 /* SYSLOG_ACTION_* buffer size only calculation */
849 len += print_prefix(msg, syslog, NULL);
850 len += text_len + 1;
851 }
852
853 text = next;
854 } while (text);
824 855
825 len = sprintf(text, "<%u>", msg->level);
826 len += prepend_timestamp(msg->ts_nsec, text + len);
827 if (len + msg->text_len > size)
828 return -EINVAL;
829 memcpy(text + len, log_text(msg), msg->text_len);
830 len += msg->text_len;
831 text[len++] = '\n';
832 return len; 856 return len;
833} 857}
834 858
835static int syslog_print(char __user *buf, int size) 859static int syslog_print(char __user *buf, int size)
836{ 860{
837 char *text; 861 char *text;
862 struct log *msg;
838 int len; 863 int len;
839 864
840 text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); 865 text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
@@ -847,7 +872,8 @@ static int syslog_print(char __user *buf, int size)
847 syslog_seq = log_first_seq; 872 syslog_seq = log_first_seq;
848 syslog_idx = log_first_idx; 873 syslog_idx = log_first_idx;
849 } 874 }
850 len = syslog_print_line(syslog_idx, text, LOG_LINE_MAX); 875 msg = log_from_idx(syslog_idx);
876 len = msg_print_text(msg, true, text, LOG_LINE_MAX);
851 syslog_idx = log_next(syslog_idx); 877 syslog_idx = log_next(syslog_idx);
852 syslog_seq++; 878 syslog_seq++;
853 raw_spin_unlock_irq(&logbuf_lock); 879 raw_spin_unlock_irq(&logbuf_lock);
@@ -887,14 +913,18 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
887 seq = clear_seq; 913 seq = clear_seq;
888 idx = clear_idx; 914 idx = clear_idx;
889 while (seq < log_next_seq) { 915 while (seq < log_next_seq) {
890 len += syslog_print_line(idx, NULL, 0); 916 struct log *msg = log_from_idx(idx);
917
918 len += msg_print_text(msg, true, NULL, 0);
891 idx = log_next(idx); 919 idx = log_next(idx);
892 seq++; 920 seq++;
893 } 921 }
894 seq = clear_seq; 922 seq = clear_seq;
895 idx = clear_idx; 923 idx = clear_idx;
896 while (len > size && seq < log_next_seq) { 924 while (len > size && seq < log_next_seq) {
897 len -= syslog_print_line(idx, NULL, 0); 925 struct log *msg = log_from_idx(idx);
926
927 len -= msg_print_text(msg, true, NULL, 0);
898 idx = log_next(idx); 928 idx = log_next(idx);
899 seq++; 929 seq++;
900 } 930 }
@@ -904,9 +934,10 @@ static int syslog_print_all(char __user *buf, int size, bool clear)
904 934
905 len = 0; 935 len = 0;
906 while (len >= 0 && seq < next_seq) { 936 while (len >= 0 && seq < next_seq) {
937 struct log *msg = log_from_idx(idx);
907 int textlen; 938 int textlen;
908 939
909 textlen = syslog_print_line(idx, text, LOG_LINE_MAX); 940 textlen = msg_print_text(msg, true, text, LOG_LINE_MAX);
910 if (textlen < 0) { 941 if (textlen < 0) {
911 len = textlen; 942 len = textlen;
912 break; 943 break;
@@ -1044,7 +1075,9 @@ int do_syslog(int type, char __user *buf, int len, bool from_file)
1044 seq = syslog_seq; 1075 seq = syslog_seq;
1045 idx = syslog_idx; 1076 idx = syslog_idx;
1046 while (seq < log_next_seq) { 1077 while (seq < log_next_seq) {
1047 error += syslog_print_line(idx, NULL, 0); 1078 struct log *msg = log_from_idx(idx);
1079
1080 error += msg_print_text(msg, true, NULL, 0);
1048 idx = log_next(idx); 1081 idx = log_next(idx);
1049 seq++; 1082 seq++;
1050 } 1083 }
@@ -1439,10 +1472,8 @@ static struct log *log_from_idx(u32 idx) { return NULL; }
1439static u32 log_next(u32 idx) { return 0; } 1472static u32 log_next(u32 idx) { return 0; }
1440static char *log_text(const struct log *msg) { return NULL; } 1473static char *log_text(const struct log *msg) { return NULL; }
1441static void call_console_drivers(int level, const char *text, size_t len) {} 1474static void call_console_drivers(int level, const char *text, size_t len) {}
1442static size_t prepend_timestamp(unsigned long long t, char *buf) 1475static size_t msg_print_text(const struct log *msg, bool syslog,
1443{ 1476 char *buf, size_t size) { return 0; }
1444 return 0;
1445}
1446 1477
1447#endif /* CONFIG_PRINTK */ 1478#endif /* CONFIG_PRINTK */
1448 1479
@@ -1750,7 +1781,7 @@ again:
1750 for (;;) { 1781 for (;;) {
1751 struct log *msg; 1782 struct log *msg;
1752 static char text[LOG_LINE_MAX]; 1783 static char text[LOG_LINE_MAX];
1753 size_t len, l; 1784 size_t len;
1754 int level; 1785 int level;
1755 1786
1756 raw_spin_lock_irqsave(&logbuf_lock, flags); 1787 raw_spin_lock_irqsave(&logbuf_lock, flags);
@@ -1771,13 +1802,7 @@ again:
1771 msg = log_from_idx(console_idx); 1802 msg = log_from_idx(console_idx);
1772 level = msg->level & 7; 1803 level = msg->level & 7;
1773 1804
1774 len = prepend_timestamp(msg->ts_nsec, text); 1805 len = msg_print_text(msg, false, text, sizeof(text));
1775 l = msg->text_len;
1776 if (len + l + 1 >= sizeof(text))
1777 l = sizeof(text) - len - 1;
1778 memcpy(text + len, log_text(msg), l);
1779 len += l;
1780 text[len++] = '\n';
1781 1806
1782 console_idx = log_next(console_idx); 1807 console_idx = log_next(console_idx);
1783 console_seq++; 1808 console_seq++;