diff options
-rw-r--r-- | kernel/printk.c | 202 |
1 files changed, 126 insertions, 76 deletions
diff --git a/kernel/printk.c b/kernel/printk.c index dba18211685e..177fa49357a5 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
@@ -194,8 +194,10 @@ static int console_may_schedule; | |||
194 | */ | 194 | */ |
195 | 195 | ||
196 | enum log_flags { | 196 | enum log_flags { |
197 | LOG_DEFAULT = 0, | 197 | LOG_NOCONS = 1, /* already flushed, do not print to console */ |
198 | LOG_NOCONS = 1, /* already flushed, do not print to console */ | 198 | LOG_NEWLINE = 2, /* text ended with a newline */ |
199 | LOG_PREFIX = 4, /* text started with a prefix */ | ||
200 | LOG_CONT = 8, /* text is a fragment of a continuation line */ | ||
199 | }; | 201 | }; |
200 | 202 | ||
201 | struct log { | 203 | struct log { |
@@ -217,6 +219,8 @@ static DEFINE_RAW_SPINLOCK(logbuf_lock); | |||
217 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ | 219 | /* the next printk record to read by syslog(READ) or /proc/kmsg */ |
218 | static u64 syslog_seq; | 220 | static u64 syslog_seq; |
219 | static u32 syslog_idx; | 221 | static u32 syslog_idx; |
222 | static enum log_flags syslog_prev; | ||
223 | static size_t syslog_partial; | ||
220 | 224 | ||
221 | /* index and sequence number of the first record stored in the buffer */ | 225 | /* index and sequence number of the first record stored in the buffer */ |
222 | static u64 log_first_seq; | 226 | static u64 log_first_seq; |
@@ -430,20 +434,20 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
430 | ret = mutex_lock_interruptible(&user->lock); | 434 | ret = mutex_lock_interruptible(&user->lock); |
431 | if (ret) | 435 | if (ret) |
432 | return ret; | 436 | return ret; |
433 | raw_spin_lock(&logbuf_lock); | 437 | raw_spin_lock_irq(&logbuf_lock); |
434 | while (user->seq == log_next_seq) { | 438 | while (user->seq == log_next_seq) { |
435 | if (file->f_flags & O_NONBLOCK) { | 439 | if (file->f_flags & O_NONBLOCK) { |
436 | ret = -EAGAIN; | 440 | ret = -EAGAIN; |
437 | raw_spin_unlock(&logbuf_lock); | 441 | raw_spin_unlock_irq(&logbuf_lock); |
438 | goto out; | 442 | goto out; |
439 | } | 443 | } |
440 | 444 | ||
441 | raw_spin_unlock(&logbuf_lock); | 445 | raw_spin_unlock_irq(&logbuf_lock); |
442 | ret = wait_event_interruptible(log_wait, | 446 | ret = wait_event_interruptible(log_wait, |
443 | user->seq != log_next_seq); | 447 | user->seq != log_next_seq); |
444 | if (ret) | 448 | if (ret) |
445 | goto out; | 449 | goto out; |
446 | raw_spin_lock(&logbuf_lock); | 450 | raw_spin_lock_irq(&logbuf_lock); |
447 | } | 451 | } |
448 | 452 | ||
449 | if (user->seq < log_first_seq) { | 453 | if (user->seq < log_first_seq) { |
@@ -451,7 +455,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
451 | user->idx = log_first_idx; | 455 | user->idx = log_first_idx; |
452 | user->seq = log_first_seq; | 456 | user->seq = log_first_seq; |
453 | ret = -EPIPE; | 457 | ret = -EPIPE; |
454 | raw_spin_unlock(&logbuf_lock); | 458 | raw_spin_unlock_irq(&logbuf_lock); |
455 | goto out; | 459 | goto out; |
456 | } | 460 | } |
457 | 461 | ||
@@ -465,7 +469,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
465 | for (i = 0; i < msg->text_len; i++) { | 469 | for (i = 0; i < msg->text_len; i++) { |
466 | unsigned char c = log_text(msg)[i]; | 470 | unsigned char c = log_text(msg)[i]; |
467 | 471 | ||
468 | if (c < ' ' || c >= 128) | 472 | if (c < ' ' || c >= 127 || c == '\\') |
469 | len += sprintf(user->buf + len, "\\x%02x", c); | 473 | len += sprintf(user->buf + len, "\\x%02x", c); |
470 | else | 474 | else |
471 | user->buf[len++] = c; | 475 | user->buf[len++] = c; |
@@ -489,7 +493,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
489 | continue; | 493 | continue; |
490 | } | 494 | } |
491 | 495 | ||
492 | if (c < ' ' || c >= 128) { | 496 | if (c < ' ' || c >= 127 || c == '\\') { |
493 | len += sprintf(user->buf + len, "\\x%02x", c); | 497 | len += sprintf(user->buf + len, "\\x%02x", c); |
494 | continue; | 498 | continue; |
495 | } | 499 | } |
@@ -501,7 +505,7 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, | |||
501 | 505 | ||
502 | user->idx = log_next(user->idx); | 506 | user->idx = log_next(user->idx); |
503 | user->seq++; | 507 | user->seq++; |
504 | raw_spin_unlock(&logbuf_lock); | 508 | raw_spin_unlock_irq(&logbuf_lock); |
505 | 509 | ||
506 | if (len > count) { | 510 | if (len > count) { |
507 | ret = -EINVAL; | 511 | ret = -EINVAL; |
@@ -528,7 +532,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) | |||
528 | if (offset) | 532 | if (offset) |
529 | return -ESPIPE; | 533 | return -ESPIPE; |
530 | 534 | ||
531 | raw_spin_lock(&logbuf_lock); | 535 | raw_spin_lock_irq(&logbuf_lock); |
532 | switch (whence) { | 536 | switch (whence) { |
533 | case SEEK_SET: | 537 | case SEEK_SET: |
534 | /* the first record */ | 538 | /* the first record */ |
@@ -552,7 +556,7 @@ static loff_t devkmsg_llseek(struct file *file, loff_t offset, int whence) | |||
552 | default: | 556 | default: |
553 | ret = -EINVAL; | 557 | ret = -EINVAL; |
554 | } | 558 | } |
555 | raw_spin_unlock(&logbuf_lock); | 559 | raw_spin_unlock_irq(&logbuf_lock); |
556 | return ret; | 560 | return ret; |
557 | } | 561 | } |
558 | 562 | ||
@@ -566,14 +570,14 @@ static unsigned int devkmsg_poll(struct file *file, poll_table *wait) | |||
566 | 570 | ||
567 | poll_wait(file, &log_wait, wait); | 571 | poll_wait(file, &log_wait, wait); |
568 | 572 | ||
569 | raw_spin_lock(&logbuf_lock); | 573 | raw_spin_lock_irq(&logbuf_lock); |
570 | if (user->seq < log_next_seq) { | 574 | if (user->seq < log_next_seq) { |
571 | /* return error when data has vanished underneath us */ | 575 | /* return error when data has vanished underneath us */ |
572 | if (user->seq < log_first_seq) | 576 | if (user->seq < log_first_seq) |
573 | ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI; | 577 | ret = POLLIN|POLLRDNORM|POLLERR|POLLPRI; |
574 | ret = POLLIN|POLLRDNORM; | 578 | ret = POLLIN|POLLRDNORM; |
575 | } | 579 | } |
576 | raw_spin_unlock(&logbuf_lock); | 580 | raw_spin_unlock_irq(&logbuf_lock); |
577 | 581 | ||
578 | return ret; | 582 | return ret; |
579 | } | 583 | } |
@@ -597,10 +601,10 @@ static int devkmsg_open(struct inode *inode, struct file *file) | |||
597 | 601 | ||
598 | mutex_init(&user->lock); | 602 | mutex_init(&user->lock); |
599 | 603 | ||
600 | raw_spin_lock(&logbuf_lock); | 604 | raw_spin_lock_irq(&logbuf_lock); |
601 | user->idx = log_first_idx; | 605 | user->idx = log_first_idx; |
602 | user->seq = log_first_seq; | 606 | user->seq = log_first_seq; |
603 | raw_spin_unlock(&logbuf_lock); | 607 | raw_spin_unlock_irq(&logbuf_lock); |
604 | 608 | ||
605 | file->private_data = user; | 609 | file->private_data = user; |
606 | return 0; | 610 | return 0; |
@@ -818,15 +822,18 @@ static size_t print_time(u64 ts, char *buf) | |||
818 | static size_t print_prefix(const struct log *msg, bool syslog, char *buf) | 822 | static size_t print_prefix(const struct log *msg, bool syslog, char *buf) |
819 | { | 823 | { |
820 | size_t len = 0; | 824 | size_t len = 0; |
825 | unsigned int prefix = (msg->facility << 3) | msg->level; | ||
821 | 826 | ||
822 | if (syslog) { | 827 | if (syslog) { |
823 | if (buf) { | 828 | if (buf) { |
824 | len += sprintf(buf, "<%u>", msg->level); | 829 | len += sprintf(buf, "<%u>", prefix); |
825 | } else { | 830 | } else { |
826 | len += 3; | 831 | len += 3; |
827 | if (msg->level > 9) | 832 | if (prefix > 999) |
828 | len++; | 833 | len += 3; |
829 | if (msg->level > 99) | 834 | else if (prefix > 99) |
835 | len += 2; | ||
836 | else if (prefix > 9) | ||
830 | len++; | 837 | len++; |
831 | } | 838 | } |
832 | } | 839 | } |
@@ -835,13 +842,26 @@ static size_t print_prefix(const struct log *msg, bool syslog, char *buf) | |||
835 | return len; | 842 | return len; |
836 | } | 843 | } |
837 | 844 | ||
838 | static size_t msg_print_text(const struct log *msg, bool syslog, | 845 | static size_t msg_print_text(const struct log *msg, enum log_flags prev, |
839 | char *buf, size_t size) | 846 | bool syslog, char *buf, size_t size) |
840 | { | 847 | { |
841 | const char *text = log_text(msg); | 848 | const char *text = log_text(msg); |
842 | size_t text_size = msg->text_len; | 849 | size_t text_size = msg->text_len; |
850 | bool prefix = true; | ||
851 | bool newline = true; | ||
843 | size_t len = 0; | 852 | size_t len = 0; |
844 | 853 | ||
854 | if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX)) | ||
855 | prefix = false; | ||
856 | |||
857 | if (msg->flags & LOG_CONT) { | ||
858 | if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE)) | ||
859 | prefix = false; | ||
860 | |||
861 | if (!(msg->flags & LOG_NEWLINE)) | ||
862 | newline = false; | ||
863 | } | ||
864 | |||
845 | do { | 865 | do { |
846 | const char *next = memchr(text, '\n', text_size); | 866 | const char *next = memchr(text, '\n', text_size); |
847 | size_t text_len; | 867 | size_t text_len; |
@@ -859,16 +879,22 @@ static size_t msg_print_text(const struct log *msg, bool syslog, | |||
859 | text_len + 1>= size - len) | 879 | text_len + 1>= size - len) |
860 | break; | 880 | break; |
861 | 881 | ||
862 | len += print_prefix(msg, syslog, buf + len); | 882 | if (prefix) |
883 | len += print_prefix(msg, syslog, buf + len); | ||
863 | memcpy(buf + len, text, text_len); | 884 | memcpy(buf + len, text, text_len); |
864 | len += text_len; | 885 | len += text_len; |
865 | buf[len++] = '\n'; | 886 | if (next || newline) |
887 | buf[len++] = '\n'; | ||
866 | } else { | 888 | } else { |
867 | /* SYSLOG_ACTION_* buffer size only calculation */ | 889 | /* SYSLOG_ACTION_* buffer size only calculation */ |
868 | len += print_prefix(msg, syslog, NULL); | 890 | if (prefix) |
869 | len += text_len + 1; | 891 | len += print_prefix(msg, syslog, NULL); |
892 | len += text_len; | ||
893 | if (next || newline) | ||
894 | len++; | ||
870 | } | 895 | } |
871 | 896 | ||
897 | prefix = true; | ||
872 | text = next; | 898 | text = next; |
873 | } while (text); | 899 | } while (text); |
874 | 900 | ||
@@ -887,22 +913,35 @@ static int syslog_print(char __user *buf, int size) | |||
887 | 913 | ||
888 | while (size > 0) { | 914 | while (size > 0) { |
889 | size_t n; | 915 | size_t n; |
916 | size_t skip; | ||
890 | 917 | ||
891 | raw_spin_lock_irq(&logbuf_lock); | 918 | raw_spin_lock_irq(&logbuf_lock); |
892 | if (syslog_seq < log_first_seq) { | 919 | if (syslog_seq < log_first_seq) { |
893 | /* messages are gone, move to first one */ | 920 | /* messages are gone, move to first one */ |
894 | syslog_seq = log_first_seq; | 921 | syslog_seq = log_first_seq; |
895 | syslog_idx = log_first_idx; | 922 | syslog_idx = log_first_idx; |
923 | syslog_prev = 0; | ||
924 | syslog_partial = 0; | ||
896 | } | 925 | } |
897 | if (syslog_seq == log_next_seq) { | 926 | if (syslog_seq == log_next_seq) { |
898 | raw_spin_unlock_irq(&logbuf_lock); | 927 | raw_spin_unlock_irq(&logbuf_lock); |
899 | break; | 928 | break; |
900 | } | 929 | } |
930 | |||
931 | skip = syslog_partial; | ||
901 | msg = log_from_idx(syslog_idx); | 932 | msg = log_from_idx(syslog_idx); |
902 | n = msg_print_text(msg, true, text, LOG_LINE_MAX); | 933 | n = msg_print_text(msg, syslog_prev, true, text, LOG_LINE_MAX); |
903 | if (n <= size) { | 934 | if (n - syslog_partial <= size) { |
935 | /* message fits into buffer, move forward */ | ||
904 | syslog_idx = log_next(syslog_idx); | 936 | syslog_idx = log_next(syslog_idx); |
905 | syslog_seq++; | 937 | syslog_seq++; |
938 | syslog_prev = msg->flags; | ||
939 | n -= syslog_partial; | ||
940 | syslog_partial = 0; | ||
941 | } else if (!len){ | ||
942 | /* partial read(), remember position */ | ||
943 | n = size; | ||
944 | syslog_partial += n; | ||
906 | } else | 945 | } else |
907 | n = 0; | 946 | n = 0; |
908 | raw_spin_unlock_irq(&logbuf_lock); | 947 | raw_spin_unlock_irq(&logbuf_lock); |
@@ -910,17 +949,15 @@ static int syslog_print(char __user *buf, int size) | |||
910 | if (!n) | 949 | if (!n) |
911 | break; | 950 | break; |
912 | 951 | ||
913 | len += n; | 952 | if (copy_to_user(buf, text + skip, n)) { |
914 | size -= n; | ||
915 | buf += n; | ||
916 | n = copy_to_user(buf - n, text, n); | ||
917 | |||
918 | if (n) { | ||
919 | len -= n; | ||
920 | if (!len) | 953 | if (!len) |
921 | len = -EFAULT; | 954 | len = -EFAULT; |
922 | break; | 955 | break; |
923 | } | 956 | } |
957 | |||
958 | len += n; | ||
959 | size -= n; | ||
960 | buf += n; | ||
924 | } | 961 | } |
925 | 962 | ||
926 | kfree(text); | 963 | kfree(text); |
@@ -941,6 +978,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
941 | u64 next_seq; | 978 | u64 next_seq; |
942 | u64 seq; | 979 | u64 seq; |
943 | u32 idx; | 980 | u32 idx; |
981 | enum log_flags prev; | ||
944 | 982 | ||
945 | if (clear_seq < log_first_seq) { | 983 | if (clear_seq < log_first_seq) { |
946 | /* messages are gone, move to first available one */ | 984 | /* messages are gone, move to first available one */ |
@@ -954,10 +992,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
954 | */ | 992 | */ |
955 | seq = clear_seq; | 993 | seq = clear_seq; |
956 | idx = clear_idx; | 994 | idx = clear_idx; |
995 | prev = 0; | ||
957 | while (seq < log_next_seq) { | 996 | while (seq < log_next_seq) { |
958 | struct log *msg = log_from_idx(idx); | 997 | struct log *msg = log_from_idx(idx); |
959 | 998 | ||
960 | len += msg_print_text(msg, true, NULL, 0); | 999 | len += msg_print_text(msg, prev, true, NULL, 0); |
961 | idx = log_next(idx); | 1000 | idx = log_next(idx); |
962 | seq++; | 1001 | seq++; |
963 | } | 1002 | } |
@@ -965,10 +1004,11 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
965 | /* move first record forward until length fits into the buffer */ | 1004 | /* move first record forward until length fits into the buffer */ |
966 | seq = clear_seq; | 1005 | seq = clear_seq; |
967 | idx = clear_idx; | 1006 | idx = clear_idx; |
1007 | prev = 0; | ||
968 | while (len > size && seq < log_next_seq) { | 1008 | while (len > size && seq < log_next_seq) { |
969 | struct log *msg = log_from_idx(idx); | 1009 | struct log *msg = log_from_idx(idx); |
970 | 1010 | ||
971 | len -= msg_print_text(msg, true, NULL, 0); | 1011 | len -= msg_print_text(msg, prev, true, NULL, 0); |
972 | idx = log_next(idx); | 1012 | idx = log_next(idx); |
973 | seq++; | 1013 | seq++; |
974 | } | 1014 | } |
@@ -977,17 +1017,19 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
977 | next_seq = log_next_seq; | 1017 | next_seq = log_next_seq; |
978 | 1018 | ||
979 | len = 0; | 1019 | len = 0; |
1020 | prev = 0; | ||
980 | while (len >= 0 && seq < next_seq) { | 1021 | while (len >= 0 && seq < next_seq) { |
981 | struct log *msg = log_from_idx(idx); | 1022 | struct log *msg = log_from_idx(idx); |
982 | int textlen; | 1023 | int textlen; |
983 | 1024 | ||
984 | textlen = msg_print_text(msg, true, text, LOG_LINE_MAX); | 1025 | textlen = msg_print_text(msg, prev, true, text, LOG_LINE_MAX); |
985 | if (textlen < 0) { | 1026 | if (textlen < 0) { |
986 | len = textlen; | 1027 | len = textlen; |
987 | break; | 1028 | break; |
988 | } | 1029 | } |
989 | idx = log_next(idx); | 1030 | idx = log_next(idx); |
990 | seq++; | 1031 | seq++; |
1032 | prev = msg->flags; | ||
991 | 1033 | ||
992 | raw_spin_unlock_irq(&logbuf_lock); | 1034 | raw_spin_unlock_irq(&logbuf_lock); |
993 | if (copy_to_user(buf + len, text, textlen)) | 1035 | if (copy_to_user(buf + len, text, textlen)) |
@@ -1000,6 +1042,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) | |||
1000 | /* messages are gone, move to next one */ | 1042 | /* messages are gone, move to next one */ |
1001 | seq = log_first_seq; | 1043 | seq = log_first_seq; |
1002 | idx = log_first_idx; | 1044 | idx = log_first_idx; |
1045 | prev = 0; | ||
1003 | } | 1046 | } |
1004 | } | 1047 | } |
1005 | } | 1048 | } |
@@ -1018,7 +1061,6 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
1018 | { | 1061 | { |
1019 | bool clear = false; | 1062 | bool clear = false; |
1020 | static int saved_console_loglevel = -1; | 1063 | static int saved_console_loglevel = -1; |
1021 | static DEFINE_MUTEX(syslog_mutex); | ||
1022 | int error; | 1064 | int error; |
1023 | 1065 | ||
1024 | error = check_syslog_permissions(type, from_file); | 1066 | error = check_syslog_permissions(type, from_file); |
@@ -1045,17 +1087,11 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
1045 | error = -EFAULT; | 1087 | error = -EFAULT; |
1046 | goto out; | 1088 | goto out; |
1047 | } | 1089 | } |
1048 | error = mutex_lock_interruptible(&syslog_mutex); | ||
1049 | if (error) | ||
1050 | goto out; | ||
1051 | error = wait_event_interruptible(log_wait, | 1090 | error = wait_event_interruptible(log_wait, |
1052 | syslog_seq != log_next_seq); | 1091 | syslog_seq != log_next_seq); |
1053 | if (error) { | 1092 | if (error) |
1054 | mutex_unlock(&syslog_mutex); | ||
1055 | goto out; | 1093 | goto out; |
1056 | } | ||
1057 | error = syslog_print(buf, len); | 1094 | error = syslog_print(buf, len); |
1058 | mutex_unlock(&syslog_mutex); | ||
1059 | break; | 1095 | break; |
1060 | /* Read/clear last kernel messages */ | 1096 | /* Read/clear last kernel messages */ |
1061 | case SYSLOG_ACTION_READ_CLEAR: | 1097 | case SYSLOG_ACTION_READ_CLEAR: |
@@ -1111,6 +1147,8 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
1111 | /* messages are gone, move to first one */ | 1147 | /* messages are gone, move to first one */ |
1112 | syslog_seq = log_first_seq; | 1148 | syslog_seq = log_first_seq; |
1113 | syslog_idx = log_first_idx; | 1149 | syslog_idx = log_first_idx; |
1150 | syslog_prev = 0; | ||
1151 | syslog_partial = 0; | ||
1114 | } | 1152 | } |
1115 | if (from_file) { | 1153 | if (from_file) { |
1116 | /* | 1154 | /* |
@@ -1120,19 +1158,20 @@ int do_syslog(int type, char __user *buf, int len, bool from_file) | |||
1120 | */ | 1158 | */ |
1121 | error = log_next_idx - syslog_idx; | 1159 | error = log_next_idx - syslog_idx; |
1122 | } else { | 1160 | } else { |
1123 | u64 seq; | 1161 | u64 seq = syslog_seq; |
1124 | u32 idx; | 1162 | u32 idx = syslog_idx; |
1163 | enum log_flags prev = syslog_prev; | ||
1125 | 1164 | ||
1126 | error = 0; | 1165 | error = 0; |
1127 | seq = syslog_seq; | ||
1128 | idx = syslog_idx; | ||
1129 | while (seq < log_next_seq) { | 1166 | while (seq < log_next_seq) { |
1130 | struct log *msg = log_from_idx(idx); | 1167 | struct log *msg = log_from_idx(idx); |
1131 | 1168 | ||
1132 | error += msg_print_text(msg, true, NULL, 0); | 1169 | error += msg_print_text(msg, prev, true, NULL, 0); |
1133 | idx = log_next(idx); | 1170 | idx = log_next(idx); |
1134 | seq++; | 1171 | seq++; |
1172 | prev = msg->flags; | ||
1135 | } | 1173 | } |
1174 | error -= syslog_partial; | ||
1136 | } | 1175 | } |
1137 | raw_spin_unlock_irq(&logbuf_lock); | 1176 | raw_spin_unlock_irq(&logbuf_lock); |
1138 | break; | 1177 | break; |
@@ -1400,10 +1439,9 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1400 | static char textbuf[LOG_LINE_MAX]; | 1439 | static char textbuf[LOG_LINE_MAX]; |
1401 | char *text = textbuf; | 1440 | char *text = textbuf; |
1402 | size_t text_len; | 1441 | size_t text_len; |
1442 | enum log_flags lflags = 0; | ||
1403 | unsigned long flags; | 1443 | unsigned long flags; |
1404 | int this_cpu; | 1444 | int this_cpu; |
1405 | bool newline = false; | ||
1406 | bool prefix = false; | ||
1407 | int printed_len = 0; | 1445 | int printed_len = 0; |
1408 | 1446 | ||
1409 | boot_delay_msec(); | 1447 | boot_delay_msec(); |
@@ -1442,7 +1480,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1442 | recursion_bug = 0; | 1480 | recursion_bug = 0; |
1443 | printed_len += strlen(recursion_msg); | 1481 | printed_len += strlen(recursion_msg); |
1444 | /* emit KERN_CRIT message */ | 1482 | /* emit KERN_CRIT message */ |
1445 | log_store(0, 2, LOG_DEFAULT, 0, | 1483 | log_store(0, 2, LOG_PREFIX|LOG_NEWLINE, 0, |
1446 | NULL, 0, recursion_msg, printed_len); | 1484 | NULL, 0, recursion_msg, printed_len); |
1447 | } | 1485 | } |
1448 | 1486 | ||
@@ -1455,7 +1493,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1455 | /* mark and strip a trailing newline */ | 1493 | /* mark and strip a trailing newline */ |
1456 | if (text_len && text[text_len-1] == '\n') { | 1494 | if (text_len && text[text_len-1] == '\n') { |
1457 | text_len--; | 1495 | text_len--; |
1458 | newline = true; | 1496 | lflags |= LOG_NEWLINE; |
1459 | } | 1497 | } |
1460 | 1498 | ||
1461 | /* strip syslog prefix and extract log level or control flags */ | 1499 | /* strip syslog prefix and extract log level or control flags */ |
@@ -1465,7 +1503,7 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1465 | if (level == -1) | 1503 | if (level == -1) |
1466 | level = text[1] - '0'; | 1504 | level = text[1] - '0'; |
1467 | case 'd': /* KERN_DEFAULT */ | 1505 | case 'd': /* KERN_DEFAULT */ |
1468 | prefix = true; | 1506 | lflags |= LOG_PREFIX; |
1469 | case 'c': /* KERN_CONT */ | 1507 | case 'c': /* KERN_CONT */ |
1470 | text += 3; | 1508 | text += 3; |
1471 | text_len -= 3; | 1509 | text_len -= 3; |
@@ -1475,22 +1513,20 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1475 | if (level == -1) | 1513 | if (level == -1) |
1476 | level = default_message_loglevel; | 1514 | level = default_message_loglevel; |
1477 | 1515 | ||
1478 | if (dict) { | 1516 | if (dict) |
1479 | prefix = true; | 1517 | lflags |= LOG_PREFIX|LOG_NEWLINE; |
1480 | newline = true; | ||
1481 | } | ||
1482 | 1518 | ||
1483 | if (!newline) { | 1519 | if (!(lflags & LOG_NEWLINE)) { |
1484 | /* | 1520 | /* |
1485 | * Flush the conflicting buffer. An earlier newline was missing, | 1521 | * Flush the conflicting buffer. An earlier newline was missing, |
1486 | * or another task also prints continuation lines. | 1522 | * or another task also prints continuation lines. |
1487 | */ | 1523 | */ |
1488 | if (cont.len && (prefix || cont.owner != current)) | 1524 | if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) |
1489 | cont_flush(); | 1525 | cont_flush(); |
1490 | 1526 | ||
1491 | /* buffer line if possible, otherwise store it right away */ | 1527 | /* buffer line if possible, otherwise store it right away */ |
1492 | if (!cont_add(facility, level, text, text_len)) | 1528 | if (!cont_add(facility, level, text, text_len)) |
1493 | log_store(facility, level, LOG_DEFAULT, 0, | 1529 | log_store(facility, level, lflags | LOG_CONT, 0, |
1494 | dict, dictlen, text, text_len); | 1530 | dict, dictlen, text, text_len); |
1495 | } else { | 1531 | } else { |
1496 | bool stored = false; | 1532 | bool stored = false; |
@@ -1502,13 +1538,13 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
1502 | * flush it out and store this line separately. | 1538 | * flush it out and store this line separately. |
1503 | */ | 1539 | */ |
1504 | if (cont.len && cont.owner == current) { | 1540 | if (cont.len && cont.owner == current) { |
1505 | if (!prefix) | 1541 | if (!(lflags & LOG_PREFIX)) |
1506 | stored = cont_add(facility, level, text, text_len); | 1542 | stored = cont_add(facility, level, text, text_len); |
1507 | cont_flush(); | 1543 | cont_flush(); |
1508 | } | 1544 | } |
1509 | 1545 | ||
1510 | if (!stored) | 1546 | if (!stored) |
1511 | log_store(facility, level, LOG_DEFAULT, 0, | 1547 | log_store(facility, level, lflags, 0, |
1512 | dict, dictlen, text, text_len); | 1548 | dict, dictlen, text, text_len); |
1513 | } | 1549 | } |
1514 | printed_len += text_len; | 1550 | printed_len += text_len; |
@@ -1607,8 +1643,8 @@ static struct cont { | |||
1607 | static struct log *log_from_idx(u32 idx) { return NULL; } | 1643 | static struct log *log_from_idx(u32 idx) { return NULL; } |
1608 | static u32 log_next(u32 idx) { return 0; } | 1644 | static u32 log_next(u32 idx) { return 0; } |
1609 | static void call_console_drivers(int level, const char *text, size_t len) {} | 1645 | static void call_console_drivers(int level, const char *text, size_t len) {} |
1610 | static size_t msg_print_text(const struct log *msg, bool syslog, | 1646 | static size_t msg_print_text(const struct log *msg, enum log_flags prev, |
1611 | char *buf, size_t size) { return 0; } | 1647 | bool syslog, char *buf, size_t size) { return 0; } |
1612 | static size_t cont_print_text(char *text, size_t size) { return 0; } | 1648 | static size_t cont_print_text(char *text, size_t size) { return 0; } |
1613 | 1649 | ||
1614 | #endif /* CONFIG_PRINTK */ | 1650 | #endif /* CONFIG_PRINTK */ |
@@ -1884,6 +1920,7 @@ void wake_up_klogd(void) | |||
1884 | /* the next printk record to write to the console */ | 1920 | /* the next printk record to write to the console */ |
1885 | static u64 console_seq; | 1921 | static u64 console_seq; |
1886 | static u32 console_idx; | 1922 | static u32 console_idx; |
1923 | static enum log_flags console_prev; | ||
1887 | 1924 | ||
1888 | /** | 1925 | /** |
1889 | * console_unlock - unlock the console system | 1926 | * console_unlock - unlock the console system |
@@ -1944,6 +1981,7 @@ again: | |||
1944 | /* messages are gone, move to first one */ | 1981 | /* messages are gone, move to first one */ |
1945 | console_seq = log_first_seq; | 1982 | console_seq = log_first_seq; |
1946 | console_idx = log_first_idx; | 1983 | console_idx = log_first_idx; |
1984 | console_prev = 0; | ||
1947 | } | 1985 | } |
1948 | skip: | 1986 | skip: |
1949 | if (console_seq == log_next_seq) | 1987 | if (console_seq == log_next_seq) |
@@ -1957,14 +1995,21 @@ skip: | |||
1957 | */ | 1995 | */ |
1958 | console_idx = log_next(console_idx); | 1996 | console_idx = log_next(console_idx); |
1959 | console_seq++; | 1997 | console_seq++; |
1998 | /* | ||
1999 | * We will get here again when we register a new | ||
2000 | * CON_PRINTBUFFER console. Clear the flag so we | ||
2001 | * will properly dump everything later. | ||
2002 | */ | ||
2003 | msg->flags &= ~LOG_NOCONS; | ||
1960 | goto skip; | 2004 | goto skip; |
1961 | } | 2005 | } |
1962 | 2006 | ||
1963 | level = msg->level; | 2007 | level = msg->level; |
1964 | len = msg_print_text(msg, false, text, sizeof(text)); | 2008 | len = msg_print_text(msg, console_prev, false, |
1965 | 2009 | text, sizeof(text)); | |
1966 | console_idx = log_next(console_idx); | 2010 | console_idx = log_next(console_idx); |
1967 | console_seq++; | 2011 | console_seq++; |
2012 | console_prev = msg->flags; | ||
1968 | raw_spin_unlock(&logbuf_lock); | 2013 | raw_spin_unlock(&logbuf_lock); |
1969 | 2014 | ||
1970 | stop_critical_timings(); /* don't trace print latency */ | 2015 | stop_critical_timings(); /* don't trace print latency */ |
@@ -2227,6 +2272,7 @@ void register_console(struct console *newcon) | |||
2227 | raw_spin_lock_irqsave(&logbuf_lock, flags); | 2272 | raw_spin_lock_irqsave(&logbuf_lock, flags); |
2228 | console_seq = syslog_seq; | 2273 | console_seq = syslog_seq; |
2229 | console_idx = syslog_idx; | 2274 | console_idx = syslog_idx; |
2275 | console_prev = syslog_prev; | ||
2230 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); | 2276 | raw_spin_unlock_irqrestore(&logbuf_lock, flags); |
2231 | /* | 2277 | /* |
2232 | * We're about to replay the log buffer. Only do this to the | 2278 | * We're about to replay the log buffer. Only do this to the |
@@ -2520,8 +2566,7 @@ bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog, | |||
2520 | } | 2566 | } |
2521 | 2567 | ||
2522 | msg = log_from_idx(dumper->cur_idx); | 2568 | msg = log_from_idx(dumper->cur_idx); |
2523 | l = msg_print_text(msg, syslog, | 2569 | l = msg_print_text(msg, 0, syslog, line, size); |
2524 | line, size); | ||
2525 | 2570 | ||
2526 | dumper->cur_idx = log_next(dumper->cur_idx); | 2571 | dumper->cur_idx = log_next(dumper->cur_idx); |
2527 | dumper->cur_seq++; | 2572 | dumper->cur_seq++; |
@@ -2561,6 +2606,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, | |||
2561 | u32 idx; | 2606 | u32 idx; |
2562 | u64 next_seq; | 2607 | u64 next_seq; |
2563 | u32 next_idx; | 2608 | u32 next_idx; |
2609 | enum log_flags prev; | ||
2564 | size_t l = 0; | 2610 | size_t l = 0; |
2565 | bool ret = false; | 2611 | bool ret = false; |
2566 | 2612 | ||
@@ -2583,23 +2629,27 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, | |||
2583 | /* calculate length of entire buffer */ | 2629 | /* calculate length of entire buffer */ |
2584 | seq = dumper->cur_seq; | 2630 | seq = dumper->cur_seq; |
2585 | idx = dumper->cur_idx; | 2631 | idx = dumper->cur_idx; |
2632 | prev = 0; | ||
2586 | while (seq < dumper->next_seq) { | 2633 | while (seq < dumper->next_seq) { |
2587 | struct log *msg = log_from_idx(idx); | 2634 | struct log *msg = log_from_idx(idx); |
2588 | 2635 | ||
2589 | l += msg_print_text(msg, true, NULL, 0); | 2636 | l += msg_print_text(msg, prev, true, NULL, 0); |
2590 | idx = log_next(idx); | 2637 | idx = log_next(idx); |
2591 | seq++; | 2638 | seq++; |
2639 | prev = msg->flags; | ||
2592 | } | 2640 | } |
2593 | 2641 | ||
2594 | /* move first record forward until length fits into the buffer */ | 2642 | /* move first record forward until length fits into the buffer */ |
2595 | seq = dumper->cur_seq; | 2643 | seq = dumper->cur_seq; |
2596 | idx = dumper->cur_idx; | 2644 | idx = dumper->cur_idx; |
2645 | prev = 0; | ||
2597 | while (l > size && seq < dumper->next_seq) { | 2646 | while (l > size && seq < dumper->next_seq) { |
2598 | struct log *msg = log_from_idx(idx); | 2647 | struct log *msg = log_from_idx(idx); |
2599 | 2648 | ||
2600 | l -= msg_print_text(msg, true, NULL, 0); | 2649 | l -= msg_print_text(msg, prev, true, NULL, 0); |
2601 | idx = log_next(idx); | 2650 | idx = log_next(idx); |
2602 | seq++; | 2651 | seq++; |
2652 | prev = msg->flags; | ||
2603 | } | 2653 | } |
2604 | 2654 | ||
2605 | /* last message in next interation */ | 2655 | /* last message in next interation */ |
@@ -2607,14 +2657,14 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, | |||
2607 | next_idx = idx; | 2657 | next_idx = idx; |
2608 | 2658 | ||
2609 | l = 0; | 2659 | l = 0; |
2660 | prev = 0; | ||
2610 | while (seq < dumper->next_seq) { | 2661 | while (seq < dumper->next_seq) { |
2611 | struct log *msg = log_from_idx(idx); | 2662 | struct log *msg = log_from_idx(idx); |
2612 | 2663 | ||
2613 | l += msg_print_text(msg, syslog, | 2664 | l += msg_print_text(msg, prev, syslog, buf + l, size - l); |
2614 | buf + l, size - l); | ||
2615 | |||
2616 | idx = log_next(idx); | 2665 | idx = log_next(idx); |
2617 | seq++; | 2666 | seq++; |
2667 | prev = msg->flags; | ||
2618 | } | 2668 | } |
2619 | 2669 | ||
2620 | dumper->next_seq = next_seq; | 2670 | dumper->next_seq = next_seq; |