aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/printk.c51
1 files changed, 37 insertions, 14 deletions
diff --git a/kernel/printk.c b/kernel/printk.c
index ff05361962e1..cdfba44fedf0 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -862,26 +862,49 @@ static int syslog_print(char __user *buf, int size)
862{ 862{
863 char *text; 863 char *text;
864 struct log *msg; 864 struct log *msg;
865 int len; 865 int len = 0;
866 866
867 text = kmalloc(LOG_LINE_MAX, GFP_KERNEL); 867 text = kmalloc(LOG_LINE_MAX, GFP_KERNEL);
868 if (!text) 868 if (!text)
869 return -ENOMEM; 869 return -ENOMEM;
870 870
871 raw_spin_lock_irq(&logbuf_lock); 871 while (size > 0) {
872 if (syslog_seq < log_first_seq) { 872 size_t n;
873 /* messages are gone, move to first one */ 873
874 syslog_seq = log_first_seq; 874 raw_spin_lock_irq(&logbuf_lock);
875 syslog_idx = log_first_idx; 875 if (syslog_seq < log_first_seq) {
876 } 876 /* messages are gone, move to first one */
877 msg = log_from_idx(syslog_idx); 877 syslog_seq = log_first_seq;
878 len = msg_print_text(msg, true, text, LOG_LINE_MAX); 878 syslog_idx = log_first_idx;
879 syslog_idx = log_next(syslog_idx); 879 }
880 syslog_seq++; 880 if (syslog_seq == log_next_seq) {
881 raw_spin_unlock_irq(&logbuf_lock); 881 raw_spin_unlock_irq(&logbuf_lock);
882 break;
883 }
884 msg = log_from_idx(syslog_idx);
885 n = msg_print_text(msg, true, text, LOG_LINE_MAX);
886 if (n <= size) {
887 syslog_idx = log_next(syslog_idx);
888 syslog_seq++;
889 } else
890 n = 0;
891 raw_spin_unlock_irq(&logbuf_lock);
892
893 if (!n)
894 break;
882 895
883 if (len > 0 && copy_to_user(buf, text, len)) 896 len += n;
884 len = -EFAULT; 897 size -= n;
898 buf += n;
899 n = copy_to_user(buf - n, text, n);
900
901 if (n) {
902 len -= n;
903 if (!len)
904 len = -EFAULT;
905 break;
906 }
907 }
885 908
886 kfree(text); 909 kfree(text);
887 return len; 910 return len;