From: Sasha Levin Date: Wed, 2 Oct 2019 01:08:45 +0000 (-0400) Subject: fixes for 4.9 X-Git-Tag: v4.4.195~51 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=5485077b418cc20cd1053bc3ef578af735594e5f;p=thirdparty%2Fkernel%2Fstable-queue.git fixes for 4.9 Signed-off-by: Sasha Levin --- diff --git a/queue-4.9/printk-do-not-lose-last-line-in-kmsg-buffer-dump.patch b/queue-4.9/printk-do-not-lose-last-line-in-kmsg-buffer-dump.patch new file mode 100644 index 00000000000..b39c03db3b9 --- /dev/null +++ b/queue-4.9/printk-do-not-lose-last-line-in-kmsg-buffer-dump.patch @@ -0,0 +1,74 @@ +From 36f2dbfe6ad33a96299580d6a5dd1176a398fd6f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 11 Jul 2019 16:29:37 +0200 +Subject: printk: Do not lose last line in kmsg buffer dump + +From: Vincent Whitchurch + +[ Upstream commit b46eff55ad5bd98e746c0a7022fe7ee071de5fee ] + +kmsg_dump_get_buffer() is supposed to select all the youngest log +messages which fit into the provided buffer. It determines the correct +start index by using msg_print_text() with a NULL buffer to calculate +the size of each entry. However, when performing the actual writes, +msg_print_text() only writes the entry to the buffer if the written len +is lesser than the size of the buffer. So if the lengths of the +selected youngest log messages happen to precisely fill up the provided +buffer, the last log message is not included. + +We don't want to modify msg_print_text() to fill up the buffer and start +returning a length which is equal to the size of the buffer, since +callers of its other users, such as kmsg_dump_get_line(), depend upon +the current behaviour. + +Instead, fix kmsg_dump_get_buffer() to compensate for this. + +For example, with the following two final prints: + +[ 6.427502] AAAAAAAAAAAAA +[ 6.427769] BBBBBBBB12345 + +A dump of a 64-byte buffer filled by kmsg_dump_get_buffer(), before this +patch: + + 00000000: 3c 30 3e 5b 20 20 20 20 36 2e 35 32 32 31 39 37 <0>[ 6.522197 + 00000010: 5d 20 41 41 41 41 41 41 41 41 41 41 41 41 41 0a ] AAAAAAAAAAAAA. + 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + +After this patch: + + 00000000: 3c 30 3e 5b 20 20 20 20 36 2e 34 35 36 36 37 38 <0>[ 6.456678 + 00000010: 5d 20 42 42 42 42 42 42 42 42 31 32 33 34 35 0a ] BBBBBBBB12345. + 00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + 00000030: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ + +Link: http://lkml.kernel.org/r/20190711142937.4083-1-vincent.whitchurch@axis.com +Fixes: e2ae715d66bf4bec ("kmsg - kmsg_dump() use iterator to receive log buffer content") +To: rostedt@goodmis.org +Cc: linux-kernel@vger.kernel.org +Cc: # v3.5+ +Signed-off-by: Vincent Whitchurch +Reviewed-by: Sergey Senozhatsky +Signed-off-by: Petr Mladek +Signed-off-by: Sasha Levin +--- + kernel/printk/printk.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index df348d4eeb265..6607d77afe55a 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -3131,7 +3131,7 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + /* move first record forward until length fits into the buffer */ + seq = dumper->cur_seq; + idx = dumper->cur_idx; +- while (l > size && seq < dumper->next_seq) { ++ while (l >= size && seq < dumper->next_seq) { + struct printk_log *msg = log_from_idx(idx); + + l -= msg_print_text(msg, true, NULL, 0); +-- +2.20.1 + diff --git a/queue-4.9/printk-remove-games-with-previous-record-flags.patch b/queue-4.9/printk-remove-games-with-previous-record-flags.patch new file mode 100644 index 00000000000..335ea83dda1 --- /dev/null +++ b/queue-4.9/printk-remove-games-with-previous-record-flags.patch @@ -0,0 +1,412 @@ +From eb62b7b33a2afb5b035ee286d25538e248a4aa58 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 25 Oct 2016 11:27:31 -0700 +Subject: printk: remove games with previous record flags + +From: Linus Torvalds + +[ Upstream commit 5aa068ea4082b39eafc356c27c9ecd155b0895f6 ] + +The record logging code looks at the previous record flags in various +ways, and they are all wrong. + +You can't use the previous record flags to determine anything about the +next record, because they may simply not be related. In particular, the +reason the previous record was a continuation record may well be exactly +_because_ the new record was printed by a different process, which is +why the previous record was flushed. + +So all those games are simply wrong, and make the code hard to +understand (because the code fundamentally cdoes not make sense). + +So remove it. + +Signed-off-by: Linus Torvalds +Signed-off-by: Sasha Levin +--- + kernel/printk/printk.c | 109 +++++++++-------------------------------- + 1 file changed, 24 insertions(+), 85 deletions(-) + +diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c +index 27adaaab96ba5..df348d4eeb265 100644 +--- a/kernel/printk/printk.c ++++ b/kernel/printk/printk.c +@@ -356,7 +356,6 @@ DECLARE_WAIT_QUEUE_HEAD(log_wait); + /* the next printk record to read by syslog(READ) or /proc/kmsg */ + static u64 syslog_seq; + static u32 syslog_idx; +-static enum log_flags syslog_prev; + static size_t syslog_partial; + + /* index and sequence number of the first record stored in the buffer */ +@@ -370,7 +369,6 @@ static u32 log_next_idx; + /* the next printk record to write to the console */ + static u64 console_seq; + static u32 console_idx; +-static enum log_flags console_prev; + + /* the next printk record to read after the last 'clear' command */ + static u64 clear_seq; +@@ -639,27 +637,15 @@ static void append_char(char **pp, char *e, char c) + } + + static ssize_t msg_print_ext_header(char *buf, size_t size, +- struct printk_log *msg, u64 seq, +- enum log_flags prev_flags) ++ struct printk_log *msg, u64 seq) + { + u64 ts_usec = msg->ts_nsec; +- char cont = '-'; + + do_div(ts_usec, 1000); + +- /* +- * If we couldn't merge continuation line fragments during the print, +- * export the stored flags to allow an optional external merge of the +- * records. Merging the records isn't always neccessarily correct, like +- * when we hit a race during printing. In most cases though, it produces +- * better readable output. 'c' in the record flags mark the first +- * fragment of a line, '+' the following. +- */ +- if (msg->flags & LOG_CONT) +- cont = (prev_flags & LOG_CONT) ? '+' : 'c'; +- + return scnprintf(buf, size, "%u,%llu,%llu,%c;", +- (msg->facility << 3) | msg->level, seq, ts_usec, cont); ++ (msg->facility << 3) | msg->level, seq, ts_usec, ++ msg->flags & LOG_CONT ? 'c' : '-'); + } + + static ssize_t msg_print_ext_body(char *buf, size_t size, +@@ -714,7 +700,6 @@ static ssize_t msg_print_ext_body(char *buf, size_t size, + struct devkmsg_user { + u64 seq; + u32 idx; +- enum log_flags prev; + struct ratelimit_state rs; + struct mutex lock; + char buf[CONSOLE_EXT_LOG_MAX]; +@@ -824,12 +809,11 @@ static ssize_t devkmsg_read(struct file *file, char __user *buf, + + msg = log_from_idx(user->idx); + len = msg_print_ext_header(user->buf, sizeof(user->buf), +- msg, user->seq, user->prev); ++ msg, user->seq); + len += msg_print_ext_body(user->buf + len, sizeof(user->buf) - len, + log_dict(msg), msg->dict_len, + log_text(msg), msg->text_len); + +- user->prev = msg->flags; + user->idx = log_next(user->idx); + user->seq++; + raw_spin_unlock_irq(&logbuf_lock); +@@ -1215,26 +1199,12 @@ static size_t print_prefix(const struct printk_log *msg, bool syslog, char *buf) + return len; + } + +-static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev, +- bool syslog, char *buf, size_t size) ++static size_t msg_print_text(const struct printk_log *msg, bool syslog, char *buf, size_t size) + { + const char *text = log_text(msg); + size_t text_size = msg->text_len; +- bool prefix = true; +- bool newline = true; + size_t len = 0; + +- if ((prev & LOG_CONT) && !(msg->flags & LOG_PREFIX)) +- prefix = false; +- +- if (msg->flags & LOG_CONT) { +- if ((prev & LOG_CONT) && !(prev & LOG_NEWLINE)) +- prefix = false; +- +- if (!(msg->flags & LOG_NEWLINE)) +- newline = false; +- } +- + do { + const char *next = memchr(text, '\n', text_size); + size_t text_len; +@@ -1252,22 +1222,17 @@ static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev, + text_len + 1 >= size - len) + break; + +- if (prefix) +- len += print_prefix(msg, syslog, buf + len); ++ len += print_prefix(msg, syslog, buf + len); + memcpy(buf + len, text, text_len); + len += text_len; +- if (next || newline) +- buf[len++] = '\n'; ++ buf[len++] = '\n'; + } else { + /* SYSLOG_ACTION_* buffer size only calculation */ +- if (prefix) +- len += print_prefix(msg, syslog, NULL); ++ len += print_prefix(msg, syslog, NULL); + len += text_len; +- if (next || newline) +- len++; ++ len++; + } + +- prefix = true; + text = next; + } while (text); + +@@ -1293,7 +1258,6 @@ static int syslog_print(char __user *buf, int size) + /* messages are gone, move to first one */ + syslog_seq = log_first_seq; + syslog_idx = log_first_idx; +- syslog_prev = 0; + syslog_partial = 0; + } + if (syslog_seq == log_next_seq) { +@@ -1303,13 +1267,11 @@ static int syslog_print(char __user *buf, int size) + + skip = syslog_partial; + msg = log_from_idx(syslog_idx); +- n = msg_print_text(msg, syslog_prev, true, text, +- LOG_LINE_MAX + PREFIX_MAX); ++ n = msg_print_text(msg, true, text, LOG_LINE_MAX + PREFIX_MAX); + if (n - syslog_partial <= size) { + /* message fits into buffer, move forward */ + syslog_idx = log_next(syslog_idx); + syslog_seq++; +- syslog_prev = msg->flags; + n -= syslog_partial; + syslog_partial = 0; + } else if (!len){ +@@ -1352,7 +1314,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + u64 next_seq; + u64 seq; + u32 idx; +- enum log_flags prev; + + /* + * Find first record that fits, including all following records, +@@ -1360,12 +1321,10 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + */ + seq = clear_seq; + idx = clear_idx; +- prev = 0; + while (seq < log_next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- len += msg_print_text(msg, prev, true, NULL, 0); +- prev = msg->flags; ++ len += msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; + } +@@ -1373,12 +1332,10 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + /* move first record forward until length fits into the buffer */ + seq = clear_seq; + idx = clear_idx; +- prev = 0; + while (len > size && seq < log_next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- len -= msg_print_text(msg, prev, true, NULL, 0); +- prev = msg->flags; ++ len -= msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; + } +@@ -1391,7 +1348,7 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + struct printk_log *msg = log_from_idx(idx); + int textlen; + +- textlen = msg_print_text(msg, prev, true, text, ++ textlen = msg_print_text(msg, true, text, + LOG_LINE_MAX + PREFIX_MAX); + if (textlen < 0) { + len = textlen; +@@ -1399,7 +1356,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + } + idx = log_next(idx); + seq++; +- prev = msg->flags; + + raw_spin_unlock_irq(&logbuf_lock); + if (copy_to_user(buf + len, text, textlen)) +@@ -1412,7 +1368,6 @@ static int syslog_print_all(char __user *buf, int size, bool clear) + /* messages are gone, move to next one */ + seq = log_first_seq; + idx = log_first_idx; +- prev = 0; + } + } + } +@@ -1513,7 +1468,6 @@ int do_syslog(int type, char __user *buf, int len, int source) + /* messages are gone, move to first one */ + syslog_seq = log_first_seq; + syslog_idx = log_first_idx; +- syslog_prev = 0; + syslog_partial = 0; + } + if (source == SYSLOG_FROM_PROC) { +@@ -1526,16 +1480,14 @@ int do_syslog(int type, char __user *buf, int len, int source) + } else { + u64 seq = syslog_seq; + u32 idx = syslog_idx; +- enum log_flags prev = syslog_prev; + + error = 0; + while (seq < log_next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- error += msg_print_text(msg, prev, true, NULL, 0); ++ error += msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; +- prev = msg->flags; + } + error -= syslog_partial; + } +@@ -1717,7 +1669,7 @@ static size_t cont_print_text(char *text, size_t size) + size_t textlen = 0; + size_t len; + +- if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) { ++ if (cont.cons == 0) { + textlen += print_time(cont.ts_nsec, text); + size -= textlen; + } +@@ -1985,11 +1937,9 @@ static u64 syslog_seq; + static u32 syslog_idx; + static u64 console_seq; + static u32 console_idx; +-static enum log_flags syslog_prev; + static u64 log_first_seq; + static u32 log_first_idx; + static u64 log_next_seq; +-static enum log_flags console_prev; + static struct cont { + size_t len; + size_t cons; +@@ -2001,15 +1951,15 @@ static char *log_dict(const struct printk_log *msg) { return NULL; } + static struct printk_log *log_from_idx(u32 idx) { return NULL; } + static u32 log_next(u32 idx) { return 0; } + static ssize_t msg_print_ext_header(char *buf, size_t size, +- struct printk_log *msg, u64 seq, +- enum log_flags prev_flags) { return 0; } ++ struct printk_log *msg, ++ u64 seq) { return 0; } + static ssize_t msg_print_ext_body(char *buf, size_t size, + char *dict, size_t dict_len, + char *text, size_t text_len) { return 0; } + static void call_console_drivers(int level, + const char *ext_text, size_t ext_len, + const char *text, size_t len) {} +-static size_t msg_print_text(const struct printk_log *msg, enum log_flags prev, ++static size_t msg_print_text(const struct printk_log *msg, + bool syslog, char *buf, size_t size) { return 0; } + static size_t cont_print_text(char *text, size_t size) { return 0; } + static bool suppress_message_printing(int level) { return false; } +@@ -2397,7 +2347,6 @@ void console_unlock(void) + /* messages are gone, move to first one */ + console_seq = log_first_seq; + console_idx = log_first_idx; +- console_prev = 0; + } else { + len = 0; + } +@@ -2422,16 +2371,14 @@ void console_unlock(void) + * will properly dump everything later. + */ + msg->flags &= ~LOG_NOCONS; +- console_prev = msg->flags; + goto skip; + } + +- len += msg_print_text(msg, console_prev, false, +- text + len, sizeof(text) - len); ++ len += msg_print_text(msg, false, text + len, sizeof(text) - len); + if (nr_ext_console_drivers) { + ext_len = msg_print_ext_header(ext_text, + sizeof(ext_text), +- msg, console_seq, console_prev); ++ msg, console_seq); + ext_len += msg_print_ext_body(ext_text + ext_len, + sizeof(ext_text) - ext_len, + log_dict(msg), msg->dict_len, +@@ -2439,7 +2386,6 @@ void console_unlock(void) + } + console_idx = log_next(console_idx); + console_seq++; +- console_prev = msg->flags; + raw_spin_unlock(&logbuf_lock); + + stop_critical_timings(); /* don't trace print latency */ +@@ -2734,7 +2680,6 @@ void register_console(struct console *newcon) + raw_spin_lock_irqsave(&logbuf_lock, flags); + console_seq = syslog_seq; + console_idx = syslog_idx; +- console_prev = syslog_prev; + raw_spin_unlock_irqrestore(&logbuf_lock, flags); + /* + * We're about to replay the log buffer. Only do this to the +@@ -3084,7 +3029,7 @@ bool kmsg_dump_get_line_nolock(struct kmsg_dumper *dumper, bool syslog, + goto out; + + msg = log_from_idx(dumper->cur_idx); +- l = msg_print_text(msg, 0, syslog, line, size); ++ l = msg_print_text(msg, syslog, line, size); + + dumper->cur_idx = log_next(dumper->cur_idx); + dumper->cur_seq++; +@@ -3153,7 +3098,6 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + u32 idx; + u64 next_seq; + u32 next_idx; +- enum log_flags prev; + size_t l = 0; + bool ret = false; + +@@ -3176,27 +3120,23 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + /* calculate length of entire buffer */ + seq = dumper->cur_seq; + idx = dumper->cur_idx; +- prev = 0; + while (seq < dumper->next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- l += msg_print_text(msg, prev, true, NULL, 0); ++ l += msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; +- prev = msg->flags; + } + + /* move first record forward until length fits into the buffer */ + seq = dumper->cur_seq; + idx = dumper->cur_idx; +- prev = 0; + while (l > size && seq < dumper->next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- l -= msg_print_text(msg, prev, true, NULL, 0); ++ l -= msg_print_text(msg, true, NULL, 0); + idx = log_next(idx); + seq++; +- prev = msg->flags; + } + + /* last message in next interation */ +@@ -3207,10 +3147,9 @@ bool kmsg_dump_get_buffer(struct kmsg_dumper *dumper, bool syslog, + while (seq < dumper->next_seq) { + struct printk_log *msg = log_from_idx(idx); + +- l += msg_print_text(msg, prev, syslog, buf + l, size - l); ++ l += msg_print_text(msg, syslog, buf + l, size - l); + idx = log_next(idx); + seq++; +- prev = msg->flags; + } + + dumper->next_seq = next_seq; +-- +2.20.1 + diff --git a/queue-4.9/series b/queue-4.9/series index 824721ec067..56f733942b5 100644 --- a/queue-4.9/series +++ b/queue-4.9/series @@ -98,3 +98,5 @@ pm-devfreq-passive-fix-compiler-warning.patch alsa-firewire-tascam-handle-error-code-when-getting-current-source-of-clock.patch alsa-firewire-tascam-check-intermediate-state-of-clock-status-and-retry.patch ib-hfi1-define-variables-as-unsigned-long-to-fix-kasan-warning.patch +printk-remove-games-with-previous-record-flags.patch +printk-do-not-lose-last-line-in-kmsg-buffer-dump.patch