diff options
Diffstat (limited to '03-kmsg-cont-order.patch')
-rw-r--r-- | 03-kmsg-cont-order.patch | 213 |
1 files changed, 0 insertions, 213 deletions
diff --git a/03-kmsg-cont-order.patch b/03-kmsg-cont-order.patch deleted file mode 100644 index b53c6fb..0000000 --- a/03-kmsg-cont-order.patch +++ /dev/null @@ -1,213 +0,0 @@ -From: Kay Sievers <kay@vrfy.org> -Subject: kmsg - do not flush partial lines when the console is busy - -Fragments of continuation lines are flushed to the console immediately. In -case the console is locked, the fragment must be queued up in the cont -buffer. - -If the the console is busy and the continuation line is complete, but no part -of it was written to the console up to this point, we can just store the -entire line as a regular record and free the buffer earlier. - -If the console is busy and earlier messages are already queued up, we -should not flush the fragments of continuation lines, but store them after -the queued up messages, to ensure the proper ordering. - -This keeps the console output better readable in case printk()s race against -each other, or we receive over-long continuation lines we need to flush. - -Signed-off-by: Kay Sievers <kay@vrfy.org> ---- - - kernel/printk.c | 93 ++++++++++++++++++++++++++++++++++++++++---------------- - 1 file changed, 68 insertions(+), 25 deletions(-) - ---- a/kernel/printk.c -+++ b/kernel/printk.c -@@ -231,6 +231,11 @@ static u32 log_first_idx; - static u64 log_next_seq; - 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; - static u32 clear_idx; -@@ -1386,6 +1391,7 @@ static struct cont { - u64 ts_nsec; /* time of first print */ - u8 level; /* log level of first message */ - u8 facility; /* log level of first message */ -+ enum log_flags flags; /* prefix, newline flags */ - bool flushed:1; /* buffer sealed and committed */ - } cont; - -@@ -1396,10 +1402,25 @@ static void cont_flush(enum log_flags fl - if (cont.len == 0) - return; - -- log_store(cont.facility, cont.level, LOG_NOCONS | flags, -- cont.ts_nsec, NULL, 0, cont.buf, cont.len); -- -- cont.flushed = true; -+ if (cont.cons) { -+ /* -+ * If a fragment of this line was directly flushed to the -+ * console; wait for the console to pick up the rest of the -+ * line. LOG_NOCONS suppresses a duplicated output. -+ */ -+ log_store(cont.facility, cont.level, flags | LOG_NOCONS, -+ cont.ts_nsec, NULL, 0, cont.buf, cont.len); -+ cont.flags = flags; -+ cont.flushed = true; -+ } else { -+ /* -+ * If no fragment of this line ever reached the console, -+ * just submit it to the store and free the buffer. -+ */ -+ log_store(cont.facility, cont.level, flags, 0, -+ NULL, 0, cont.buf, cont.len); -+ cont.len = 0; -+ } - } - - static bool cont_add(int facility, int level, const char *text, size_t len) -@@ -1418,12 +1439,17 @@ static bool cont_add(int facility, int l - cont.level = level; - cont.owner = current; - cont.ts_nsec = local_clock(); -+ cont.flags = 0; - cont.cons = 0; - cont.flushed = false; - } - - memcpy(cont.buf + cont.len, text, len); - cont.len += len; -+ -+ if (cont.len > (sizeof(cont.buf) * 80) / 100) -+ cont_flush(LOG_CONT); -+ - return true; - } - -@@ -1432,7 +1458,7 @@ static size_t cont_print_text(char *text - size_t textlen = 0; - size_t len; - -- if (cont.cons == 0) { -+ if (cont.cons == 0 && (console_prev & LOG_NEWLINE)) { - textlen += print_time(cont.ts_nsec, text); - size -= textlen; - } -@@ -1447,7 +1473,8 @@ static size_t cont_print_text(char *text - } - - if (cont.flushed) { -- text[textlen++] = '\n'; -+ if (cont.flags & LOG_NEWLINE) -+ text[textlen++] = '\n'; - /* got everything, release buffer */ - cont.len = 0; - } -@@ -1545,7 +1572,7 @@ asmlinkage int vprintk_emit(int facility - * or another task also prints continuation lines. - */ - if (cont.len && (lflags & LOG_PREFIX || cont.owner != current)) -- cont_flush(0); -+ cont_flush(LOG_NEWLINE); - - /* buffer line if possible, otherwise store it right away */ - if (!cont_add(facility, level, text, text_len)) -@@ -1563,7 +1590,7 @@ asmlinkage int vprintk_emit(int facility - if (cont.len && cont.owner == current) { - if (!(lflags & LOG_PREFIX)) - stored = cont_add(facility, level, text, text_len); -- cont_flush(0); -+ cont_flush(LOG_NEWLINE); - } - - if (!stored) -@@ -1661,10 +1688,13 @@ EXPORT_SYMBOL(printk); - #define LOG_LINE_MAX 0 - 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; -@@ -1948,10 +1978,34 @@ void wake_up_klogd(void) - this_cpu_or(printk_pending, PRINTK_PENDING_WAKEUP); - } - --/* the next printk record to write to the console */ --static u64 console_seq; --static u32 console_idx; --static enum log_flags console_prev; -+static void console_cont_flush(char *text, size_t size) -+{ -+ unsigned long flags; -+ size_t len; -+ -+ raw_spin_lock_irqsave(&logbuf_lock, flags); -+ -+ if (!cont.len) -+ goto out; -+ -+ /* -+ * We still queue earlier records, likely because the console was -+ * busy. The earlier ones need to be printed before this one, we -+ * did not flush any fragment so far, so just let it queue up. -+ */ -+ if (console_seq < log_next_seq && !cont.cons) -+ goto out; -+ -+ len = cont_print_text(text, size); -+ raw_spin_unlock(&logbuf_lock); -+ stop_critical_timings(); -+ call_console_drivers(cont.level, text, len); -+ start_critical_timings(); -+ local_irq_restore(flags); -+ return; -+out: -+ raw_spin_unlock_irqrestore(&logbuf_lock, flags); -+} - - /** - * console_unlock - unlock the console system -@@ -1983,19 +2037,7 @@ void console_unlock(void) - console_may_schedule = 0; - - /* flush buffered message fragment immediately to console */ -- raw_spin_lock_irqsave(&logbuf_lock, flags); -- if (cont.len && (cont.cons < cont.len || cont.flushed)) { -- size_t len; -- -- len = cont_print_text(text, sizeof(text)); -- raw_spin_unlock(&logbuf_lock); -- stop_critical_timings(); -- call_console_drivers(cont.level, text, len); -- start_critical_timings(); -- local_irq_restore(flags); -- } else -- raw_spin_unlock_irqrestore(&logbuf_lock, flags); -- -+ console_cont_flush(text, sizeof(text)); - again: - for (;;) { - struct log *msg; -@@ -2032,6 +2074,7 @@ skip: - * will properly dump everything later. - */ - msg->flags &= ~LOG_NOCONS; -+ console_prev = msg->flags; - goto skip; - } - |