summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Andrzej Siewior <bigeasy@linutronix.de>2020-11-30 18:19:31 +0100
committerSebastian Andrzej Siewior <bigeasy@linutronix.de>2020-11-30 18:19:31 +0100
commit0162011ad222d71ed173bc3c32f847aa245555fa (patch)
treef05e7ed96fe6d7d5f31d973779f34be9305dfc89
parent056c6e65e9f26f301c0bf066a5322cfeb0dae61a (diff)
downloadlinux-rt-0162011ad222d71ed173bc3c32f847aa245555fa.tar.gz
[ANNOUNCE] v5.10-rc6-rt13v5.10-rc6-rt13-patches
Dear RT folks! I'm pleased to announce the v5.10-rc6-rt13 patch set. Changes since v5.10-rc6-rt12: - John's printk series was updated to his current status. - The notifier lock has been made a raw_spinlock_t to avoid a acquiring a sleeping lock in atomic context. Patch by Valentin Schneider. - The lock-lock in zswap lock was not properly initialized since v5.9-RT. This was noticed during the investigation of a z3fold related failure report Oleksandr Natalenko. According to Mike Galbraith this is still broken. Known issues - It has been pointed out that due to changes to the printk code the internal buffer representation changed. This is only an issue if tools like `crash' are used to extract the printk buffer from a kernel memory image. The delta patch against v5.10-rc6-rt12 is appended below and can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/incr/patch-5.10-rc6-rt12-rt13.patch.xz You can get this release via the git tree at: git://git.kernel.org/pub/scm/linux/kernel/git/rt/linux-rt-devel.git v5.10-rc6-rt13 The RT patch against v5.10-rc6 can be found here: https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patch-5.10-rc6-rt13.patch.xz The split quilt queue is available at: https://cdn.kernel.org/pub/linux/kernel/projects/rt/5.10/older/patches-5.10-rc6-rt13.tar.xz Sebastian Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-rw-r--r--patches/0001-printk-refactor-kmsg_dump_get_buffer.patch6
-rw-r--r--patches/0002-printk-inline-log_output-log_store-in-vprintk_store.patch (renamed from patches/0008-printk-inline-log_output-log_store-in-vprintk_store.patch)70
-rw-r--r--patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch193
-rw-r--r--patches/0003-printk-change-clear_seq-to-atomic64_t.patch20
-rw-r--r--patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch349
-rw-r--r--patches/0005-printk-remove-safe-buffers.patch10
-rw-r--r--patches/0006-console-add-write_atomic-interface.patch12
-rw-r--r--patches/0007-serial-8250-implement-write_atomic.patch4
-rw-r--r--patches/0008-printk-relocate-printk_delay-and-vprintk_default.patch (renamed from patches/0009-printk-relocate-printk_delay-and-vprintk_default.patch)16
-rw-r--r--patches/0009-printk-combine-boot_delay_msec-into-printk_delay.patch (renamed from patches/0010-printk-combine-boot_delay_msec-into-printk_delay.patch)8
-rw-r--r--patches/0010-printk-change-console_seq-to-atomic64_t.patch122
-rw-r--r--patches/0011-printk-introduce-kernel-sync-mode.patch220
-rw-r--r--patches/0012-printk-move-console-printing-to-kthreads.patch480
-rw-r--r--patches/0013-printk-remove-deferred-printing.patch74
-rw-r--r--patches/0014-printk-add-console-handover.patch12
-rw-r--r--patches/0015-printk-add-pr_flush.patch103
-rw-r--r--patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch43
-rw-r--r--patches/localversion.patch2
-rw-r--r--patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch20
-rw-r--r--patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch123
-rw-r--r--patches/printk-Tiny-cleanup.patch145
-rw-r--r--patches/series14
-rw-r--r--patches/x86-kvm-require-const-tsc-for-rt.patch2
23 files changed, 1182 insertions, 866 deletions
diff --git a/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch b/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch
index 53fabc5d9437..219f71ec5104 100644
--- a/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch
+++ b/patches/0001-printk-refactor-kmsg_dump_get_buffer.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 19:09:15 +0200
-Subject: [PATCH 01/15] printk: refactor kmsg_dump_get_buffer()
+Date: Mon, 30 Nov 2020 01:41:56 +0106
+Subject: [PATCH 01/16] printk: refactor kmsg_dump_get_buffer()
kmsg_dump_get_buffer() requires nearly the same logic as
syslog_print_all(), but uses different variable names and
@@ -85,7 +85,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
- /* last message in next interation */
-+ /* Keep track of the last message for the next interation. */
++ /* Keep track of the last message for the next iteration. */
next_seq = seq;
- /* actually read text into the buffer now */
diff --git a/patches/0008-printk-inline-log_output-log_store-in-vprintk_store.patch b/patches/0002-printk-inline-log_output-log_store-in-vprintk_store.patch
index f4cebbc4ca8f..0af56e5c7288 100644
--- a/patches/0008-printk-inline-log_output-log_store-in-vprintk_store.patch
+++ b/patches/0002-printk-inline-log_output-log_store-in-vprintk_store.patch
@@ -1,22 +1,21 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 16:40:26 +0206
-Subject: [PATCH 08/15] printk: inline log_output(),log_store() in
+Date: Mon, 30 Nov 2020 01:41:57 +0106
+Subject: [PATCH 02/16] printk: inline log_output(),log_store() in
vprintk_store()
-In preparation for supporting atomic printing, inline log_output()
-and log_store() into vprintk_store(). This allows these
-sub-functions to more easily communicate if they have performed
-a finalized commit as well as the sequence number of that commit.
+In preparation for removing logbuf_lock, inline log_output()
+and log_store() into vprintk_store(). This will simplify dealing
+with the various code branches and fallbacks that are possible.
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- kernel/printk/printk.c | 141 +++++++++++++++++++++----------------------------
- 1 file changed, 63 insertions(+), 78 deletions(-)
+ kernel/printk/printk.c | 134 ++++++++++++++++++++-----------------------------
+ 1 file changed, 56 insertions(+), 78 deletions(-)
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -465,52 +465,6 @@ static void truncate_msg(u16 *text_len,
+@@ -491,52 +491,6 @@ static void truncate_msg(u16 *text_len,
*trunc_msg_len = 0;
}
@@ -69,7 +68,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
int dmesg_restrict = IS_ENABLED(CONFIG_SECURITY_DMESG_RESTRICT);
static int syslog_action_restricted(int type)
-@@ -2001,45 +1955,24 @@ static inline u32 printk_caller_id(void)
+@@ -1907,44 +1861,22 @@ static inline u32 printk_caller_id(void)
0x80000000 + raw_smp_processor_id();
}
@@ -102,66 +101,59 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- dev_info, text, text_len);
-}
-
+ /* Must be called under logbuf_lock. */
int vprintk_store(int facility, int level,
const struct dev_printk_info *dev_info,
const char *fmt, va_list args)
{
-- size_t text_len;
+ const u32 caller_id = printk_caller_id();
+ static char textbuf[LOG_LINE_MAX];
+- char *text = textbuf;
+- size_t text_len;
+ struct prb_reserved_entry e;
enum log_flags lflags = 0;
- unsigned long irqflags;
+ struct printk_record r;
+ u16 trunc_msg_len = 0;
- int sprint_id;
++ char *text = textbuf;
+ u16 text_len;
+ u64 ts_nsec;
-+ int ret = 0;
- char *text;
-- int ret;
-+ u64 seq;
+
+ ts_nsec = local_clock();
- /* No buffer is available if printk has recursed too much. */
- text = get_sprint_buf(&sprint_id, &irqflags);
-@@ -2083,8 +2016,60 @@ int vprintk_store(int facility, int leve
+ /*
+ * The printf needs to come first; we need the syslog
+@@ -1983,7 +1915,53 @@ int vprintk_store(int facility, int leve
if (dev_info)
lflags |= LOG_NEWLINE;
-- ret = log_output(facility, level, lflags, dev_info, text, text_len);
+- return log_output(facility, level, lflags, dev_info, text, text_len);
+ if (lflags & LOG_CONT) {
+ prb_rec_init_wr(&r, text_len);
+ if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) {
-+ seq = r.info->seq;
+ memcpy(&r.text_buf[r.info->text_len], text, text_len);
+ r.info->text_len += text_len;
++
+ if (lflags & LOG_NEWLINE) {
+ r.info->flags |= LOG_NEWLINE;
+ prb_final_commit(&e);
+ } else {
+ prb_commit(&e);
+ }
-+ ret = text_len;
-+ goto out;
++
++ return text_len;
+ }
+ }
+
-+ /* Store it in the record log */
-+
+ prb_rec_init_wr(&r, text_len);
-+
+ if (!prb_reserve(&e, prb, &r)) {
+ /* truncate the message if it is too long for empty buffer */
+ truncate_msg(&text_len, &trunc_msg_len);
++
+ prb_rec_init_wr(&r, text_len + trunc_msg_len);
-+ /* survive when the log buffer is too small for trunc_msg */
+ if (!prb_reserve(&e, prb, &r))
-+ goto out;
++ return 0;
+ }
+
-+ seq = r.info->seq;
-+
+ /* fill message */
+ memcpy(&r.text_buf[0], text, text_len);
+ if (trunc_msg_len)
@@ -174,16 +166,14 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ r.info->caller_id = caller_id;
+ if (dev_info)
+ memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info));
-
-+ /* insert message */
-+ if ((lflags & LOG_CONT) || !(lflags & LOG_NEWLINE)) {
++
++ /* A message without a trailing newline can be continued. */
++ if (!(lflags & LOG_NEWLINE))
+ prb_commit(&e);
-+ } else {
++ else
+ prb_final_commit(&e);
-+ }
+
-+ ret = text_len + trunc_msg_len;
-+out:
- put_sprint_buf(sprint_id, irqflags);
- return ret;
++ return (text_len + trunc_msg_len);
}
+
+ asmlinkage int vprintk_emit(int facility, int level,
diff --git a/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch b/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch
deleted file mode 100644
index ee4c41875be3..000000000000
--- a/patches/0002-printk-use-buffer-pools-for-sprint-buffers.patch
+++ /dev/null
@@ -1,193 +0,0 @@
-From: John Ogness <john.ogness@linutronix.de>
-Date: Tue, 13 Oct 2020 22:57:55 +0200
-Subject: [PATCH 02/15] printk: use buffer pools for sprint buffers
-
-vprintk_store() is using a single static buffer as a temporary
-sprint buffer for the message text. This will not work once
-@logbuf_lock is removed. Replace the single static buffer with
-per-cpu and global pools.
-
-Each per-cpu pool is large enough to support a worse case of 2
-contexts (non-NMI and NMI).
-
-To support printk() recursion and printk() calls before per-cpu
-variables are ready, an extra/fallback global pool of 2 contexts is
-available.
-
-Signed-off-by: John Ogness <john.ogness@linutronix.de>
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- kernel/printk/printk.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++--
- 1 file changed, 137 insertions(+), 4 deletions(-)
-
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -1704,6 +1704,129 @@ SYSCALL_DEFINE3(syslog, int, type, char
- }
-
- /*
-+ * The per-cpu sprint buffers are used with interrupts disabled, so each CPU
-+ * only requires 2 buffers: for non-NMI and NMI contexts. Recursive printk()
-+ * calls are handled by the global sprint buffers.
-+ */
-+#define SPRINT_CTX_DEPTH 2
-+
-+/* Static sprint buffers for early boot (only 1 CPU) and recursion. */
-+static DECLARE_BITMAP(sprint_global_buffer_map, SPRINT_CTX_DEPTH);
-+static char sprint_global_buffer[SPRINT_CTX_DEPTH][PREFIX_MAX + LOG_LINE_MAX];
-+
-+struct sprint_buffers {
-+ char buf[SPRINT_CTX_DEPTH][PREFIX_MAX + LOG_LINE_MAX];
-+ atomic_t index;
-+};
-+
-+static DEFINE_PER_CPU(struct sprint_buffers, percpu_sprint_buffers);
-+
-+/*
-+ * Acquire an unused buffer, returning its index. If no buffer is
-+ * available, @count is returned.
-+ */
-+static int _get_sprint_buf(unsigned long *map, int count)
-+{
-+ int index;
-+
-+ do {
-+ index = find_first_zero_bit(map, count);
-+ if (index == count)
-+ break;
-+ /*
-+ * Guarantee map changes are ordered for the other CPUs.
-+ * Pairs with clear_bit() in _put_sprint_buf().
-+ */
-+ } while (test_and_set_bit(index, map));
-+
-+ return index;
-+}
-+
-+/* Mark the buffer @index as unused. */
-+static void _put_sprint_buf(unsigned long *map, unsigned int count, unsigned int index)
-+{
-+ /*
-+ * Guarantee map changes are ordered for the other CPUs.
-+ * Pairs with test_and_set_bit() in _get_sprint_buf().
-+ */
-+ clear_bit(index, map);
-+}
-+
-+/*
-+ * Get a buffer sized PREFIX_MAX+LOG_LINE_MAX for sprinting. On success, @id
-+ * is set and interrupts are disabled. @id is used to put back the buffer.
-+ *
-+ * @id is non-negative for per-cpu buffers, negative for global buffers.
-+ */
-+static char *get_sprint_buf(int *id, unsigned long *flags)
-+{
-+ struct sprint_buffers *bufs;
-+ unsigned int index;
-+ unsigned int cpu;
-+
-+ local_irq_save(*flags);
-+ cpu = get_cpu();
-+
-+ if (printk_percpu_data_ready()) {
-+
-+ /*
-+ * First try with per-cpu pool. Note that the last
-+ * buffer is reserved for NMI context.
-+ */
-+ bufs = per_cpu_ptr(&percpu_sprint_buffers, cpu);
-+ index = atomic_read(&bufs->index);
-+ if (index < (SPRINT_CTX_DEPTH - 1) ||
-+ (in_nmi() && index < SPRINT_CTX_DEPTH)) {
-+ atomic_set(&bufs->index, index + 1);
-+ *id = cpu;
-+ return &bufs->buf[index][0];
-+ }
-+ }
-+
-+ /*
-+ * Fallback to global pool.
-+ *
-+ * The global pool will only ever be used if per-cpu data is not ready
-+ * yet or printk recurses. Recursion will not occur unless printk is
-+ * having internal issues.
-+ */
-+ index = _get_sprint_buf(sprint_global_buffer_map, SPRINT_CTX_DEPTH);
-+ if (index != SPRINT_CTX_DEPTH) {
-+ /* Convert to global buffer representation. */
-+ *id = -index - 1;
-+ return &sprint_global_buffer[index][0];
-+ }
-+
-+ /* Failed to get a buffer. */
-+ put_cpu();
-+ local_irq_restore(*flags);
-+ return NULL;
-+}
-+
-+/* Put back an sprint buffer and restore interrupts. */
-+static void put_sprint_buf(int id, unsigned long flags)
-+{
-+ struct sprint_buffers *bufs;
-+ unsigned int index;
-+ unsigned int cpu;
-+
-+ if (id >= 0) {
-+ cpu = id;
-+ bufs = per_cpu_ptr(&percpu_sprint_buffers, cpu);
-+ index = atomic_read(&bufs->index);
-+ atomic_set(&bufs->index, index - 1);
-+ } else {
-+ /* Convert from global buffer representation. */
-+ index = -id - 1;
-+ _put_sprint_buf(sprint_global_buffer_map,
-+ SPRINT_CTX_DEPTH, index);
-+ }
-+
-+ put_cpu();
-+ local_irq_restore(flags);
-+}
-+
-+/*
- * Special console_lock variants that help to reduce the risk of soft-lockups.
- * They allow to pass console_lock to another printk() call using a busy wait.
- */
-@@ -1941,16 +2064,23 @@ int vprintk_store(int facility, int leve
- const struct dev_printk_info *dev_info,
- const char *fmt, va_list args)
- {
-- static char textbuf[LOG_LINE_MAX];
-- char *text = textbuf;
- size_t text_len;
- enum log_flags lflags = 0;
-+ unsigned long irqflags;
-+ int sprint_id;
-+ char *text;
-+ int ret;
-+
-+ /* No buffer is available if printk has recursed too much. */
-+ text = get_sprint_buf(&sprint_id, &irqflags);
-+ if (!text)
-+ return 0;
-
- /*
- * The printf needs to come first; we need the syslog
- * prefix which might be passed-in as a parameter.
- */
-- text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
-+ text_len = vscnprintf(text, LOG_LINE_MAX, fmt, args);
-
- /* mark and strip a trailing newline */
- if (text_len && text[text_len-1] == '\n') {
-@@ -1983,7 +2113,10 @@ int vprintk_store(int facility, int leve
- if (dev_info)
- lflags |= LOG_NEWLINE;
-
-- return log_output(facility, level, lflags, dev_info, text, text_len);
-+ ret = log_output(facility, level, lflags, dev_info, text, text_len);
-+
-+ put_sprint_buf(sprint_id, irqflags);
-+ return ret;
- }
-
- asmlinkage int vprintk_emit(int facility, int level,
diff --git a/patches/0003-printk-change-clear_seq-to-atomic64_t.patch b/patches/0003-printk-change-clear_seq-to-atomic64_t.patch
index d29d83360af9..0eaf077e7e1d 100644
--- a/patches/0003-printk-change-clear_seq-to-atomic64_t.patch
+++ b/patches/0003-printk-change-clear_seq-to-atomic64_t.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Tue, 13 Oct 2020 23:19:35 +0200
-Subject: [PATCH 03/15] printk: change @clear_seq to atomic64_t
+Date: Mon, 30 Nov 2020 01:41:58 +0106
+Subject: [PATCH 03/16] printk: change @clear_seq to atomic64_t
Currently @clear_seq access is protected by @logbuf_lock. Once
@logbuf_lock is removed some other form of synchronization will be
@@ -24,7 +24,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#ifdef CONFIG_PRINTK_CALLER
#define PREFIX_MAX 48
-@@ -843,7 +843,7 @@ static loff_t devkmsg_llseek(struct file
+@@ -797,7 +797,7 @@ static loff_t devkmsg_llseek(struct file
* like issued by 'dmesg -c'. Reading /dev/kmsg itself
* changes no global state, and does not clear anything.
*/
@@ -33,7 +33,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
break;
case SEEK_END:
/* after the last record */
-@@ -960,6 +960,9 @@ void log_buf_vmcoreinfo_setup(void)
+@@ -914,6 +914,9 @@ void log_buf_vmcoreinfo_setup(void)
* parse it and detect any changes to structure down the line.
*/
@@ -43,7 +43,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
VMCOREINFO_STRUCT_SIZE(printk_ringbuffer);
VMCOREINFO_OFFSET(printk_ringbuffer, desc_ring);
VMCOREINFO_OFFSET(printk_ringbuffer, text_data_ring);
-@@ -1522,6 +1525,7 @@ static int syslog_print_all(char __user
+@@ -1476,6 +1479,7 @@ static int syslog_print_all(char __user
struct printk_info info;
unsigned int line_count;
struct printk_record r;
@@ -51,7 +51,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
char *text;
int len = 0;
u64 seq;
-@@ -1533,15 +1537,17 @@ static int syslog_print_all(char __user
+@@ -1487,15 +1491,17 @@ static int syslog_print_all(char __user
time = printk_time;
logbuf_lock_irq();
@@ -71,7 +71,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (len <= size)
break;
len -= get_record_print_text_size(&info, line_count, true, time);
-@@ -1572,7 +1578,7 @@ static int syslog_print_all(char __user
+@@ -1526,7 +1532,7 @@ static int syslog_print_all(char __user
}
if (clear)
@@ -80,7 +80,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
logbuf_unlock_irq();
kfree(text);
-@@ -1582,7 +1588,7 @@ static int syslog_print_all(char __user
+@@ -1536,7 +1542,7 @@ static int syslog_print_all(char __user
static void syslog_clear(void)
{
logbuf_lock_irq();
@@ -89,7 +89,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
logbuf_unlock_irq();
}
-@@ -3355,7 +3361,7 @@ void kmsg_dump(enum kmsg_dump_reason rea
+@@ -3200,7 +3206,7 @@ void kmsg_dump(enum kmsg_dump_reason rea
dumper->active = true;
logbuf_lock_irqsave(flags);
@@ -98,7 +98,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
dumper->next_seq = prb_next_seq(prb);
logbuf_unlock_irqrestore(flags);
-@@ -3563,7 +3569,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
+@@ -3408,7 +3414,7 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
*/
void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
{
diff --git a/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch b/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch
index 2ee099289033..b9cd36838148 100644
--- a/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch
+++ b/patches/0004-printk-remove-logbuf_lock-add-syslog_lock.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 19:06:12 +0200
-Subject: [PATCH 04/15] printk: remove logbuf_lock, add syslog_lock
+Date: Mon, 30 Nov 2020 01:41:59 +0106
+Subject: [PATCH 04/16] printk: remove logbuf_lock, add syslog_lock
Since the ringbuffer is lockless, there is no need for it to be
protected by @logbuf_lock. Remove @logbuf_lock.
@@ -15,14 +15,33 @@ protect these.
@console_seq, @exclusive_console_stop_seq, @console_dropped are
protected by @console_lock.
+Without @logbuf_lock it is no longer possible to use the single
+static buffer for temporarily sprint'ing the message. Instead,
+use vsnprintf() to determine the length and perform the real
+vscnprintf() using the area reserved from the ringbuffer. This
+leads to suboptimal packing of the message data, but will
+result in less wasted storage than multiple per-cpu buffers to
+support lockless temporary sprint'ing.
+
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- kernel/printk/internal.h | 4 -
- kernel/printk/printk.c | 151 +++++++++++---------------------------------
- kernel/printk/printk_safe.c | 18 -----
- 3 files changed, 42 insertions(+), 131 deletions(-)
+ include/linux/printk.h | 1
+ kernel/printk/internal.h | 4
+ kernel/printk/printk.c | 285 +++++++++++++++++++++++---------------------
+ kernel/printk/printk_safe.c | 18 --
+ 4 files changed, 157 insertions(+), 151 deletions(-)
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -45,6 +45,7 @@ static inline const char *printk_skip_he
+ }
+
+ #define CONSOLE_EXT_LOG_MAX 8192
++#define CONSOLE_LOG_MAX 1024
+
+ /* printk's without a loglevel use this.. */
+ #define MESSAGE_LOGLEVEL_DEFAULT CONFIG_MESSAGE_LOGLEVEL_DEFAULT
--- a/kernel/printk/internal.h
+++ b/kernel/printk/internal.h
@@ -12,8 +12,6 @@
@@ -45,7 +64,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*/
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -355,48 +355,22 @@ enum log_flags {
+@@ -355,48 +355,18 @@ enum log_flags {
LOG_CONT = 8, /* text is a fragment of a continuation line */
};
@@ -84,11 +103,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- printk_safe_exit_irqrestore(flags); \
- } while (0)
+/* The syslog_lock protects syslog_* variables. */
-+DEFINE_RAW_SPINLOCK(syslog_lock);
-+#define syslog_lock_irq() raw_spin_lock_irq(&syslog_lock)
-+#define syslog_unlock_irq() raw_spin_unlock_irq(&syslog_lock)
-+#define syslog_lock_irqsave(flags) raw_spin_lock_irqsave(&syslog_lock, flags)
-+#define syslog_unlock_irqrestore(flags) raw_spin_unlock_irqrestore(&syslog_lock, flags)
++static DEFINE_SPINLOCK(syslog_lock);
#ifdef CONFIG_PRINTK
DECLARE_WAIT_QUEUE_HEAD(log_wait);
@@ -102,7 +117,16 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* the next printk record to write to the console */
static u64 console_seq;
static u64 exclusive_console_stop_seq;
-@@ -766,27 +740,22 @@ static ssize_t devkmsg_read(struct file
+@@ -410,7 +380,7 @@ static atomic64_t clear_seq = ATOMIC64_I
+ #else
+ #define PREFIX_MAX 32
+ #endif
+-#define LOG_LINE_MAX (1024 - PREFIX_MAX)
++#define LOG_LINE_MAX (CONSOLE_LOG_MAX - PREFIX_MAX)
+
+ #define LOG_LEVEL(v) ((v) & 0x07)
+ #define LOG_FACILITY(v) ((v) >> 3 & 0xff)
+@@ -720,27 +690,22 @@ static ssize_t devkmsg_read(struct file
if (ret)
return ret;
@@ -130,7 +154,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
goto out;
}
-@@ -796,7 +765,6 @@ static ssize_t devkmsg_read(struct file
+@@ -750,7 +715,6 @@ static ssize_t devkmsg_read(struct file
&r->info->dev_info);
user->seq = r->info->seq + 1;
@@ -138,7 +162,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (len > count) {
ret = -EINVAL;
-@@ -831,7 +799,6 @@ static loff_t devkmsg_llseek(struct file
+@@ -785,7 +749,6 @@ static loff_t devkmsg_llseek(struct file
if (offset)
return -ESPIPE;
@@ -146,7 +170,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
switch (whence) {
case SEEK_SET:
/* the first record */
-@@ -852,7 +819,6 @@ static loff_t devkmsg_llseek(struct file
+@@ -806,7 +769,6 @@ static loff_t devkmsg_llseek(struct file
default:
ret = -EINVAL;
}
@@ -154,7 +178,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return ret;
}
-@@ -866,7 +832,6 @@ static __poll_t devkmsg_poll(struct file
+@@ -820,7 +782,6 @@ static __poll_t devkmsg_poll(struct file
poll_wait(file, &log_wait, wait);
@@ -162,7 +186,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (prb_read_valid(prb, user->seq, NULL)) {
/* return error when data has vanished underneath us */
if (user->seq < prb_first_valid_seq(prb))
-@@ -874,7 +839,6 @@ static __poll_t devkmsg_poll(struct file
+@@ -828,7 +789,6 @@ static __poll_t devkmsg_poll(struct file
else
ret = EPOLLIN|EPOLLRDNORM;
}
@@ -170,7 +194,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return ret;
}
-@@ -907,9 +871,7 @@ static int devkmsg_open(struct inode *in
+@@ -861,9 +821,7 @@ static int devkmsg_open(struct inode *in
prb_rec_init_rd(&user->record, &user->info,
&user->text_buf[0], sizeof(user->text_buf));
@@ -180,7 +204,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
file->private_data = user;
return 0;
-@@ -1117,7 +1079,6 @@ void __init setup_log_buf(int early)
+@@ -1071,7 +1029,6 @@ void __init setup_log_buf(int early)
struct printk_record r;
size_t new_descs_size;
size_t new_infos_size;
@@ -188,7 +212,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
char *new_log_buf;
unsigned int free;
u64 seq;
-@@ -1175,8 +1136,6 @@ void __init setup_log_buf(int early)
+@@ -1129,8 +1086,6 @@ void __init setup_log_buf(int early)
new_descs, ilog2(new_descs_count),
new_infos);
@@ -197,7 +221,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
log_buf_len = new_log_buf_len;
log_buf = new_log_buf;
new_log_buf_len = 0;
-@@ -1192,8 +1151,6 @@ void __init setup_log_buf(int early)
+@@ -1146,8 +1101,6 @@ void __init setup_log_buf(int early)
*/
prb = &printk_rb_dynamic;
@@ -206,28 +230,28 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (seq != prb_next_seq(&printk_rb_static)) {
pr_err("dropped %llu messages\n",
prb_next_seq(&printk_rb_static) - seq);
-@@ -1469,9 +1426,9 @@ static int syslog_print(char __user *buf
+@@ -1423,9 +1376,9 @@ static int syslog_print(char __user *buf
size_t n;
size_t skip;
- logbuf_lock_irq();
-+ syslog_lock_irq();
++ spin_lock_irq(&syslog_lock);
if (!prb_read_valid(prb, syslog_seq, &r)) {
- logbuf_unlock_irq();
-+ syslog_unlock_irq();
++ spin_unlock_irq(&syslog_lock);
break;
}
if (r.info->seq != syslog_seq) {
-@@ -1500,7 +1457,7 @@ static int syslog_print(char __user *buf
+@@ -1454,7 +1407,7 @@ static int syslog_print(char __user *buf
syslog_partial += n;
} else
n = 0;
- logbuf_unlock_irq();
-+ syslog_unlock_irq();
++ spin_unlock_irq(&syslog_lock);
if (!n)
break;
-@@ -1525,6 +1482,7 @@ static int syslog_print_all(char __user
+@@ -1479,6 +1432,7 @@ static int syslog_print_all(char __user
struct printk_info info;
unsigned int line_count;
struct printk_record r;
@@ -235,7 +259,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
u64 clr_seq;
char *text;
int len = 0;
-@@ -1536,19 +1494,30 @@ static int syslog_print_all(char __user
+@@ -1490,19 +1444,30 @@ static int syslog_print_all(char __user
return -ENOMEM;
time = printk_time;
@@ -269,7 +293,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
break;
len -= get_record_print_text_size(&info, line_count, true, time);
}
-@@ -1566,12 +1535,10 @@ static int syslog_print_all(char __user
+@@ -1520,12 +1485,10 @@ static int syslog_print_all(char __user
break;
}
@@ -282,7 +306,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (len < 0)
break;
-@@ -1579,7 +1546,6 @@ static int syslog_print_all(char __user
+@@ -1533,7 +1496,6 @@ static int syslog_print_all(char __user
if (clear)
atomic64_set(&clear_seq, seq);
@@ -290,7 +314,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
kfree(text);
return len;
-@@ -1587,9 +1553,7 @@ static int syslog_print_all(char __user
+@@ -1541,9 +1503,7 @@ static int syslog_print_all(char __user
static void syslog_clear(void)
{
@@ -300,7 +324,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
int do_syslog(int type, char __user *buf, int len, int source)
-@@ -1597,6 +1561,7 @@ int do_syslog(int type, char __user *buf
+@@ -1551,6 +1511,7 @@ int do_syslog(int type, char __user *buf
bool clear = false;
static int saved_console_loglevel = LOGLEVEL_DEFAULT;
int error;
@@ -308,46 +332,249 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
error = check_syslog_permissions(type, source);
if (error)
-@@ -1614,8 +1579,11 @@ int do_syslog(int type, char __user *buf
+@@ -1568,8 +1529,11 @@ int do_syslog(int type, char __user *buf
return 0;
if (!access_ok(buf, len))
return -EFAULT;
-+ syslog_lock_irq();
++ spin_lock_irq(&syslog_lock);
+ seq = syslog_seq;
-+ syslog_unlock_irq();
++ spin_unlock_irq(&syslog_lock);
error = wait_event_interruptible(log_wait,
- prb_read_valid(prb, syslog_seq, NULL));
+ prb_read_valid(prb, seq, NULL));
if (error)
return error;
error = syslog_print(buf, len);
-@@ -1663,7 +1631,7 @@ int do_syslog(int type, char __user *buf
+@@ -1617,7 +1581,7 @@ int do_syslog(int type, char __user *buf
break;
/* Number of chars in the log buffer */
case SYSLOG_ACTION_SIZE_UNREAD:
- logbuf_lock_irq();
-+ syslog_lock_irq();
++ spin_lock_irq(&syslog_lock);
if (syslog_seq < prb_first_valid_seq(prb)) {
/* messages are gone, move to first one */
syslog_seq = prb_first_valid_seq(prb);
-@@ -1690,7 +1658,7 @@ int do_syslog(int type, char __user *buf
+@@ -1644,7 +1608,7 @@ int do_syslog(int type, char __user *buf
}
error -= syslog_partial;
}
- logbuf_unlock_irq();
-+ syslog_unlock_irq();
++ spin_unlock_irq(&syslog_lock);
break;
/* Size of the log buffer */
case SYSLOG_ACTION_SIZE_BUFFER:
-@@ -2065,7 +2033,6 @@ static size_t log_output(int facility, i
- dev_info, text, text_len);
+@@ -1847,6 +1811,65 @@ static void call_console_drivers(const c
+ }
+ }
+
++#ifdef CONFIG_PRINTK_NMI
++#define NUM_RECURSION_CTX 2
++#else
++#define NUM_RECURSION_CTX 1
++#endif
++
++struct printk_recursion {
++ char count[NUM_RECURSION_CTX];
++};
++
++static DEFINE_PER_CPU(struct printk_recursion, percpu_printk_recursion);
++static char printk_recursion_count[NUM_RECURSION_CTX];
++
++static char *get_printk_count(void)
++{
++ struct printk_recursion *rec;
++ char *count;
++
++ if (!printk_percpu_data_ready()) {
++ count = &printk_recursion_count[0];
++ } else {
++ rec = this_cpu_ptr(&percpu_printk_recursion);
++
++ count = &rec->count[0];
++ }
++
++#ifdef CONFIG_PRINTK_NMI
++ if (in_nmi())
++ count++;
++#endif
++
++ return count;
++}
++
++static bool printk_enter(unsigned long *flags)
++{
++ char *count;
++
++ local_irq_save(*flags);
++ count = get_printk_count();
++ /* Only 1 level of recursion allowed. */
++ if (*count > 1) {
++ local_irq_restore(*flags);
++ return false;
++ }
++ (*count)++;
++
++ return true;
++}
++
++static void printk_exit(unsigned long flags)
++{
++ char *count;
++
++ count = get_printk_count();
++ (*count)--;
++ local_irq_restore(flags);
++}
++
+ int printk_delay_msec __read_mostly;
+
+ static inline void printk_delay(void)
+@@ -1867,40 +1890,75 @@ static inline u32 printk_caller_id(void)
+ 0x80000000 + raw_smp_processor_id();
}
-/* Must be called under logbuf_lock. */
++static u16 printk_sprint(char *text, u16 size, int facility, enum log_flags *lflags,
++ const char *fmt, va_list args)
++{
++ char *orig_text = text;
++ u16 text_len;
++
++ text_len = vscnprintf(text, size, fmt, args);
++
++ /* Mark and strip a trailing newline. */
++ if (text_len && text[text_len - 1] == '\n') {
++ text_len--;
++ *lflags |= LOG_NEWLINE;
++ }
++
++ /* Strip kernel syslog prefix. */
++ if (facility == 0) {
++ while (text_len >= 2 && printk_get_level(text)) {
++ text_len -= 2;
++ text += 2;
++ }
++
++ if (text != orig_text)
++ memmove(orig_text, text, text_len);
++ }
++
++ return text_len;
++}
++
++__printf(4, 0)
int vprintk_store(int facility, int level,
const struct dev_printk_info *dev_info,
const char *fmt, va_list args)
-@@ -2131,7 +2098,6 @@ asmlinkage int vprintk_emit(int facility
+ {
+ const u32 caller_id = printk_caller_id();
+- static char textbuf[LOG_LINE_MAX];
+ struct prb_reserved_entry e;
+ enum log_flags lflags = 0;
+ struct printk_record r;
++ unsigned long irqflags;
+ u16 trunc_msg_len = 0;
+- char *text = textbuf;
++ char lvlbuf[8];
++ va_list args2;
+ u16 text_len;
++ int ret = 0;
+ u64 ts_nsec;
+
+ ts_nsec = local_clock();
+
++ if (!printk_enter(&irqflags))
++ return 0;
++
++ va_copy(args2, args);
++
+ /*
+ * The printf needs to come first; we need the syslog
+ * prefix which might be passed-in as a parameter.
+ */
+- text_len = vscnprintf(text, sizeof(textbuf), fmt, args);
++ text_len = vsnprintf(&lvlbuf[0], sizeof(lvlbuf), fmt, args) + 1;
++ if (text_len > CONSOLE_LOG_MAX)
++ text_len = CONSOLE_LOG_MAX;
+
+- /* mark and strip a trailing newline */
+- if (text_len && text[text_len-1] == '\n') {
+- text_len--;
+- lflags |= LOG_NEWLINE;
+- }
+-
+- /* strip kernel syslog prefix and extract log level or control flags */
++ /* Extract log level or control flags. */
+ if (facility == 0) {
+ int kern_level;
++ int i;
+
+- while ((kern_level = printk_get_level(text)) != 0) {
++ for (i = 0; i < sizeof(lvlbuf); i += 2) {
++ kern_level = printk_get_level(&lvlbuf[i]);
++ if (!kern_level)
++ break;
+ switch (kern_level) {
+ case '0' ... '7':
+ if (level == LOGLEVEL_DEFAULT)
+@@ -1909,9 +1967,6 @@ int vprintk_store(int facility, int leve
+ case 'c': /* KERN_CONT */
+ lflags |= LOG_CONT;
+ }
+-
+- text_len -= 2;
+- text += 2;
+ }
+ }
+
+@@ -1924,7 +1979,8 @@ int vprintk_store(int facility, int leve
+ if (lflags & LOG_CONT) {
+ prb_rec_init_wr(&r, text_len);
+ if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) {
+- memcpy(&r.text_buf[r.info->text_len], text, text_len);
++ text_len = printk_sprint(&r.text_buf[r.info->text_len], text_len,
++ facility, &lflags, fmt, args2);
+ r.info->text_len += text_len;
+
+ if (lflags & LOG_NEWLINE) {
+@@ -1934,7 +1990,8 @@ int vprintk_store(int facility, int leve
+ prb_commit(&e);
+ }
+
+- return text_len;
++ ret = text_len;
++ goto out;
+ }
+ }
+
+@@ -1945,11 +2002,11 @@ int vprintk_store(int facility, int leve
+
+ prb_rec_init_wr(&r, text_len + trunc_msg_len);
+ if (!prb_reserve(&e, prb, &r))
+- return 0;
++ goto out;
+ }
+
+ /* fill message */
+- memcpy(&r.text_buf[0], text, text_len);
++ text_len = printk_sprint(&r.text_buf[0], text_len, facility, &lflags, fmt, args2);
+ if (trunc_msg_len)
+ memcpy(&r.text_buf[text_len], trunc_msg, trunc_msg_len);
+ r.info->text_len = text_len + trunc_msg_len;
+@@ -1967,7 +2024,11 @@ int vprintk_store(int facility, int leve
+ else
+ prb_final_commit(&e);
+
+- return (text_len + trunc_msg_len);
++ ret = text_len + trunc_msg_len;
++out:
++ va_end(args2);
++ printk_exit(irqflags);
++ return ret;
+ }
+
+ asmlinkage int vprintk_emit(int facility, int level,
+@@ -1976,7 +2037,6 @@ asmlinkage int vprintk_emit(int facility
{
int printed_len;
bool in_sched = false;
@@ -355,7 +582,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* Suppress unimportant messages after panic happens */
if (unlikely(suppress_printk))
-@@ -2146,9 +2112,7 @@ asmlinkage int vprintk_emit(int facility
+@@ -1991,9 +2051,7 @@ asmlinkage int vprintk_emit(int facility
printk_delay();
/* This stops the holder of console_sem just where we want him */
@@ -365,7 +592,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* If called from the scheduler, we can not call up(). */
if (!in_sched) {
-@@ -2580,7 +2544,6 @@ void console_unlock(void)
+@@ -2425,7 +2483,6 @@ void console_unlock(void)
size_t len;
printk_safe_enter_irqsave(flags);
@@ -373,7 +600,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
skip:
if (!prb_read_valid(prb, console_seq, &r))
break;
-@@ -2624,7 +2587,6 @@ void console_unlock(void)
+@@ -2469,7 +2526,6 @@ void console_unlock(void)
console_msg_format & MSG_FORMAT_SYSLOG,
printk_time);
console_seq++;
@@ -381,7 +608,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* While actively printing out messages, if another printk()
-@@ -2651,8 +2613,6 @@ void console_unlock(void)
+@@ -2496,8 +2552,6 @@ void console_unlock(void)
console_locked = 0;
@@ -390,7 +617,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
up_console_sem();
/*
-@@ -2661,9 +2621,7 @@ void console_unlock(void)
+@@ -2506,9 +2560,7 @@ void console_unlock(void)
* there's a new owner and the console_unlock() from them will do the
* flush, no worries.
*/
@@ -400,7 +627,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
printk_safe_exit_irqrestore(flags);
if (retry && console_trylock())
-@@ -2727,13 +2685,8 @@ void console_flush_on_panic(enum con_flu
+@@ -2572,13 +2624,8 @@ void console_flush_on_panic(enum con_flu
console_trylock();
console_may_schedule = 0;
@@ -415,7 +642,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
console_unlock();
}
-@@ -2957,11 +2910,7 @@ void register_console(struct console *ne
+@@ -2802,11 +2849,7 @@ void register_console(struct console *ne
nr_ext_console_drivers++;
if (newcon->flags & CON_PRINTBUFFER) {
@@ -424,20 +651,20 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- * for us.
- */
- logbuf_lock_irqsave(flags);
-+ syslog_lock_irqsave(flags);
++ spin_lock_irqsave(&syslog_lock, flags);
/*
* We're about to replay the log buffer. Only do this to the
* just-registered console to avoid excessive message spam to
-@@ -2974,7 +2923,7 @@ void register_console(struct console *ne
+@@ -2819,7 +2862,7 @@ void register_console(struct console *ne
exclusive_console = newcon;
exclusive_console_stop_seq = console_seq;
console_seq = syslog_seq;
- logbuf_unlock_irqrestore(flags);
-+ syslog_unlock_irqrestore(flags);
++ spin_unlock_irqrestore(&syslog_lock, flags);
}
console_unlock();
console_sysfs_notify();
-@@ -3340,7 +3289,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_reason_str);
+@@ -3185,7 +3228,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_reason_str);
void kmsg_dump(enum kmsg_dump_reason reason)
{
struct kmsg_dumper *dumper;
@@ -445,7 +672,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
rcu_read_lock();
list_for_each_entry_rcu(dumper, &dump_list, list) {
-@@ -3360,10 +3308,7 @@ void kmsg_dump(enum kmsg_dump_reason rea
+@@ -3205,10 +3247,7 @@ void kmsg_dump(enum kmsg_dump_reason rea
/* initialize iterator with data about the stored records */
dumper->active = true;
@@ -457,7 +684,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* invoke dumper which will iterate over records */
dumper->dump(dumper, reason);
-@@ -3450,14 +3395,7 @@ bool kmsg_dump_get_line_nolock(struct km
+@@ -3295,14 +3334,7 @@ bool kmsg_dump_get_line_nolock(struct km
bool kmsg_dump_get_line(struct kmsg_dumper *dumper, bool syslog,
char *line, size_t size, size_t *len)
{
@@ -473,7 +700,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
EXPORT_SYMBOL_GPL(kmsg_dump_get_line);
-@@ -3486,7 +3424,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du
+@@ -3331,7 +3363,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du
struct printk_info info;
unsigned int line_count;
struct printk_record r;
@@ -481,7 +708,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
u64 seq;
u64 next_seq;
size_t len = 0;
-@@ -3496,17 +3433,14 @@ bool kmsg_dump_get_buffer(struct kmsg_du
+@@ -3341,17 +3372,14 @@ bool kmsg_dump_get_buffer(struct kmsg_du
if (!dumper->active || !buf || !size)
goto out;
@@ -500,7 +727,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Find first record that fits, including all following records,
-@@ -3549,7 +3483,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du
+@@ -3394,7 +3422,6 @@ bool kmsg_dump_get_buffer(struct kmsg_du
dumper->next_seq = next_seq;
ret = true;
@@ -508,7 +735,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
out:
if (len_out)
*len_out = len;
-@@ -3564,8 +3497,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
+@@ -3409,8 +3436,6 @@ EXPORT_SYMBOL_GPL(kmsg_dump_get_buffer);
* Reset the dumper's iterator so that kmsg_dump_get_line() and
* kmsg_dump_get_buffer() can be called again and used multiple
* times within the same dumper.dump() callback.
@@ -517,7 +744,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
*/
void kmsg_dump_rewind_nolock(struct kmsg_dumper *dumper)
{
-@@ -3583,11 +3514,7 @@ void kmsg_dump_rewind_nolock(struct kmsg
+@@ -3428,11 +3453,7 @@ void kmsg_dump_rewind_nolock(struct kmsg
*/
void kmsg_dump_rewind(struct kmsg_dumper *dumper)
{
diff --git a/patches/0005-printk-remove-safe-buffers.patch b/patches/0005-printk-remove-safe-buffers.patch
index ba8805748b07..874938b4efeb 100644
--- a/patches/0005-printk-remove-safe-buffers.patch
+++ b/patches/0005-printk-remove-safe-buffers.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 20:00:11 +0200
-Subject: [PATCH 05/15] printk: remove safe buffers
+Date: Mon, 30 Nov 2020 01:42:00 +0106
+Subject: [PATCH 05/16] printk: remove safe buffers
With @logbuf_lock removed, the high level printk functions for
storing messages are lockless. Messages can be stored from any
@@ -50,7 +50,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
-@@ -207,8 +207,6 @@ void __init setup_log_buf(int early);
+@@ -208,8 +208,6 @@ void __init setup_log_buf(int early);
void dump_stack_print_info(const char *log_lvl);
void show_regs_print_info(const char *log_lvl);
extern asmlinkage void dump_stack(void) __cold;
@@ -59,7 +59,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#else
static inline __printf(1, 0)
int vprintk(const char *s, va_list args)
-@@ -272,14 +270,6 @@ static inline void show_regs_print_info(
+@@ -273,14 +271,6 @@ static inline void show_regs_print_info(
static inline void dump_stack(void)
{
}
@@ -122,7 +122,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#endif /* CONFIG_PRINTK */
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -1037,9 +1037,6 @@ static inline void log_buf_add_cpu(void)
+@@ -987,9 +987,6 @@ static inline void log_buf_add_cpu(void)
static void __init set_percpu_data_ready(void)
{
diff --git a/patches/0006-console-add-write_atomic-interface.patch b/patches/0006-console-add-write_atomic-interface.patch
index 0c25e4ae99c2..b1d6bdd94f72 100644
--- a/patches/0006-console-add-write_atomic-interface.patch
+++ b/patches/0006-console-add-write_atomic-interface.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 20:26:35 +0200
-Subject: [PATCH 06/15] console: add write_atomic interface
+Date: Mon, 30 Nov 2020 01:42:01 +0106
+Subject: [PATCH 06/16] console: add write_atomic interface
Add a write_atomic() callback to the console. This is an optional
function for console drivers. The function must be atomic (including
@@ -34,7 +34,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct console {
char name[16];
void (*write)(struct console *, const char *, unsigned);
-+ void (*write_atomic)(struct console *, const char *, unsigned);
++ void (*write_atomic)(struct console *co, const char *s, unsigned int count);
int (*read)(struct console *, char *, unsigned);
struct tty_driver *(*device)(struct console *, int *);
void (*unblank)(void);
@@ -48,7 +48,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#endif /* _LINUX_CONSOLE_H */
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -3516,3 +3516,103 @@ void kmsg_dump_rewind(struct kmsg_dumper
+@@ -3455,3 +3455,103 @@ void kmsg_dump_rewind(struct kmsg_dumper
EXPORT_SYMBOL_GPL(kmsg_dump_rewind);
#endif
@@ -105,7 +105,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * It is safe to call this function from any context and state.
+ */
-+void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store)
++static void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store)
+{
+ for (;;) {
+ if (__prb_trylock(cpu_lock, cpu_store))
@@ -123,7 +123,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ *
+ * It is safe to call this function from any context and state.
+ */
-+void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store)
++static void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store)
+{
+ unsigned long *flags;
+ unsigned int cpu;
diff --git a/patches/0007-serial-8250-implement-write_atomic.patch b/patches/0007-serial-8250-implement-write_atomic.patch
index 1b88e78b4d7c..b1aef776d287 100644
--- a/patches/0007-serial-8250-implement-write_atomic.patch
+++ b/patches/0007-serial-8250-implement-write_atomic.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 20:31:46 +0200
-Subject: [PATCH 07/15] serial: 8250: implement write_atomic
+Date: Mon, 30 Nov 2020 01:42:02 +0106
+Subject: [PATCH 07/16] serial: 8250: implement write_atomic
Implement a non-sleeping NMI-safe write_atomic() console function in
order to support emergency console printing.
diff --git a/patches/0009-printk-relocate-printk_delay-and-vprintk_default.patch b/patches/0008-printk-relocate-printk_delay-and-vprintk_default.patch
index ffd29dfd11af..89139600b8fd 100644
--- a/patches/0009-printk-relocate-printk_delay-and-vprintk_default.patch
+++ b/patches/0008-printk-relocate-printk_delay-and-vprintk_default.patch
@@ -1,11 +1,11 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 21:02:40 +0206
-Subject: [PATCH 09/15] printk: relocate printk_delay() and vprintk_default()
+Date: Mon, 30 Nov 2020 01:42:03 +0106
+Subject: [PATCH 08/16] printk: relocate printk_delay() and vprintk_default()
Move printk_delay() and vprintk_default() "as is" further up so that
they can be used by new functions in an upcoming commit.
-Signed-off-by: John Ogness <john.ogness@linutornix.de>
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
kernel/printk/printk.c | 40 ++++++++++++++++++++--------------------
@@ -13,8 +13,8 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -1751,6 +1751,20 @@ static void put_sprint_buf(int id, unsig
- local_irq_restore(flags);
+@@ -1624,6 +1624,20 @@ SYSCALL_DEFINE3(syslog, int, type, char
+ return do_syslog(type, buf, len, SYSLOG_FROM_READER);
}
+int printk_delay_msec __read_mostly;
@@ -34,8 +34,8 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Special console_lock variants that help to reduce the risk of soft-lockups.
* They allow to pass console_lock to another printk() call using a busy wait.
-@@ -1935,20 +1949,6 @@ static void call_console_drivers(const c
- }
+@@ -1867,20 +1881,6 @@ static void printk_exit(unsigned long fl
+ local_irq_restore(flags);
}
-int printk_delay_msec __read_mostly;
@@ -55,7 +55,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static inline u32 printk_caller_id(void)
{
return in_task() ? task_pid_nr(current) :
-@@ -2119,18 +2119,18 @@ asmlinkage int vprintk_emit(int facility
+@@ -2073,18 +2073,18 @@ asmlinkage int vprintk_emit(int facility
}
EXPORT_SYMBOL(vprintk_emit);
diff --git a/patches/0010-printk-combine-boot_delay_msec-into-printk_delay.patch b/patches/0009-printk-combine-boot_delay_msec-into-printk_delay.patch
index 54892f3d062f..ed47f9da8faf 100644
--- a/patches/0010-printk-combine-boot_delay_msec-into-printk_delay.patch
+++ b/patches/0009-printk-combine-boot_delay_msec-into-printk_delay.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 22:11:31 +0206
-Subject: [PATCH 10/15] printk: combine boot_delay_msec() into printk_delay()
+Date: Mon, 30 Nov 2020 01:42:04 +0106
+Subject: [PATCH 09/16] printk: combine boot_delay_msec() into printk_delay()
boot_delay_msec() is always called immediately before printk_delay()
so just combine the two.
@@ -13,7 +13,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -1753,8 +1753,10 @@ static void put_sprint_buf(int id, unsig
+@@ -1626,8 +1626,10 @@ SYSCALL_DEFINE3(syslog, int, type, char
int printk_delay_msec __read_mostly;
@@ -25,7 +25,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (unlikely(printk_delay_msec)) {
int m = printk_delay_msec;
-@@ -2090,8 +2092,7 @@ asmlinkage int vprintk_emit(int facility
+@@ -2044,8 +2046,7 @@ asmlinkage int vprintk_emit(int facility
in_sched = true;
}
diff --git a/patches/0010-printk-change-console_seq-to-atomic64_t.patch b/patches/0010-printk-change-console_seq-to-atomic64_t.patch
new file mode 100644
index 000000000000..5299e29eecca
--- /dev/null
+++ b/patches/0010-printk-change-console_seq-to-atomic64_t.patch
@@ -0,0 +1,122 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 30 Nov 2020 01:42:05 +0106
+Subject: [PATCH 10/16] printk: change @console_seq to atomic64_t
+
+In preparation for atomic printing, change @console_seq to atomic
+so that it can be accessed without requiring @console_sem.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ kernel/printk/printk.c | 34 +++++++++++++++++++---------------
+ 1 file changed, 19 insertions(+), 15 deletions(-)
+
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -366,12 +366,13 @@ static u64 syslog_seq;
+ static size_t syslog_partial;
+ static bool syslog_time;
+
+-/* All 3 protected by @console_sem. */
+-/* the next printk record to write to the console */
+-static u64 console_seq;
++/* Both protected by @console_sem. */
+ static u64 exclusive_console_stop_seq;
+ static unsigned long console_dropped;
+
++/* the next printk record to write to the console */
++static atomic64_t console_seq = ATOMIC64_INIT(0);
++
+ /* the next printk record to read after the last 'clear' command */
+ static atomic64_t clear_seq = ATOMIC64_INIT(0);
+
+@@ -2130,7 +2131,7 @@ EXPORT_SYMBOL(printk);
+ #define prb_first_valid_seq(rb) 0
+
+ static u64 syslog_seq;
+-static u64 console_seq;
++static atomic64_t console_seq = ATOMIC64_INIT(0);
+ static u64 exclusive_console_stop_seq;
+ static unsigned long console_dropped;
+
+@@ -2439,6 +2440,7 @@ void console_unlock(void)
+ bool do_cond_resched, retry;
+ struct printk_info info;
+ struct printk_record r;
++ u64 seq;
+
+ if (console_suspended) {
+ up_console_sem();
+@@ -2482,12 +2484,14 @@ void console_unlock(void)
+
+ printk_safe_enter_irqsave(flags);
+ skip:
+- if (!prb_read_valid(prb, console_seq, &r))
++ seq = atomic64_read(&console_seq);
++ if (!prb_read_valid(prb, seq, &r))
+ break;
+
+- if (console_seq != r.info->seq) {
+- console_dropped += r.info->seq - console_seq;
+- console_seq = r.info->seq;
++ if (seq != r.info->seq) {
++ console_dropped += r.info->seq - seq;
++ atomic64_set(&console_seq, r.info->seq);
++ seq = r.info->seq;
+ }
+
+ if (suppress_message_printing(r.info->level)) {
+@@ -2496,13 +2500,13 @@ void console_unlock(void)
+ * directly to the console when we received it, and
+ * record that has level above the console loglevel.
+ */
+- console_seq++;
++ atomic64_set(&console_seq, seq + 1);
+ goto skip;
+ }
+
+ /* Output to all consoles once old messages replayed. */
+ if (unlikely(exclusive_console &&
+- console_seq >= exclusive_console_stop_seq)) {
++ seq >= exclusive_console_stop_seq)) {
+ exclusive_console = NULL;
+ }
+
+@@ -2523,7 +2527,7 @@ void console_unlock(void)
+ len = record_print_text(&r,
+ console_msg_format & MSG_FORMAT_SYSLOG,
+ printk_time);
+- console_seq++;
++ atomic64_set(&console_seq, seq + 1);
+
+ /*
+ * While actively printing out messages, if another printk()
+@@ -2558,7 +2562,7 @@ void console_unlock(void)
+ * there's a new owner and the console_unlock() from them will do the
+ * flush, no worries.
+ */
+- retry = prb_read_valid(prb, console_seq, NULL);
++ retry = prb_read_valid(prb, atomic64_read(&console_seq), NULL);
+ printk_safe_exit_irqrestore(flags);
+
+ if (retry && console_trylock())
+@@ -2623,7 +2627,7 @@ void console_flush_on_panic(enum con_flu
+ console_may_schedule = 0;
+
+ if (mode == CONSOLE_REPLAY_ALL)
+- console_seq = prb_first_valid_seq(prb);
++ atomic64_set(&console_seq, prb_first_valid_seq(prb));
+ console_unlock();
+ }
+
+@@ -2858,8 +2862,8 @@ void register_console(struct console *ne
+ * ignores console_lock.
+ */
+ exclusive_console = newcon;
+- exclusive_console_stop_seq = console_seq;
+- console_seq = syslog_seq;
++ exclusive_console_stop_seq = atomic64_read(&console_seq);
++ atomic64_set(&console_seq, syslog_seq);
+ spin_unlock_irqrestore(&syslog_lock, flags);
+ }
+ console_unlock();
diff --git a/patches/0011-printk-introduce-kernel-sync-mode.patch b/patches/0011-printk-introduce-kernel-sync-mode.patch
index 8d7107ee3df0..efcc95736dd9 100644
--- a/patches/0011-printk-introduce-kernel-sync-mode.patch
+++ b/patches/0011-printk-introduce-kernel-sync-mode.patch
@@ -1,20 +1,39 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Wed, 14 Oct 2020 20:40:05 +0200
-Subject: [PATCH 11/15] printk: introduce kernel sync mode
+Date: Mon, 30 Nov 2020 01:42:06 +0106
+Subject: [PATCH 11/16] printk: introduce kernel sync mode
When the kernel performs an OOPS, enter into "sync mode":
- only atomic consoles (write_atomic() callback) will print
- printing occurs within vprintk_store() instead of console_unlock()
-Change @console_seq to atomic64_t for atomic access.
-
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- kernel/printk/printk.c | 165 ++++++++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 150 insertions(+), 15 deletions(-)
+ include/linux/console.h | 4 +
+ kernel/printk/printk.c | 142 +++++++++++++++++++++++++++++++++++++++++++++++-
+ 2 files changed, 144 insertions(+), 2 deletions(-)
+--- a/include/linux/console.h
++++ b/include/linux/console.h
+@@ -16,6 +16,7 @@
+
+ #include <linux/atomic.h>
+ #include <linux/types.h>
++#include <linux/printk.h>
+
+ struct vc_data;
+ struct console_font_op;
+@@ -151,6 +152,9 @@ struct console {
+ short flags;
+ short index;
+ int cflag;
++#ifdef CONFIG_PRINTK
++ char sync_buf[CONSOLE_LOG_MAX];
++#endif
+ void *data;
+ struct console *next;
+ };
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -44,6 +44,7 @@
@@ -25,34 +44,17 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#include <linux/sched/clock.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
-@@ -78,6 +79,9 @@ EXPORT_SYMBOL(ignore_console_lock_warnin
- int oops_in_progress;
- EXPORT_SYMBOL(oops_in_progress);
+@@ -359,6 +360,9 @@ enum log_flags {
+ static DEFINE_SPINLOCK(syslog_lock);
+ #ifdef CONFIG_PRINTK
+/* Set to enable sync mode. Once set, it is never cleared. */
+static bool sync_mode;
+
- /*
- * console_sem protects the console_drivers list, and also
- * provides serialisation for access to the entire console
-@@ -370,12 +374,13 @@ static u64 syslog_seq;
- static size_t syslog_partial;
- static bool syslog_time;
-
--/* All 3 protected by @console_sem. */
--/* the next printk record to write to the console */
--static u64 console_seq;
-+/* Both protected by @console_sem. */
- static u64 exclusive_console_stop_seq;
- static unsigned long console_dropped;
-
-+/* the next printk record to write to the console */
-+static atomic64_t console_seq = ATOMIC64_INIT(0);
-+
- /* the next printk record to read after the last 'clear' command */
- static atomic64_t clear_seq = ATOMIC64_INIT(0);
-
-@@ -1767,6 +1772,110 @@ static inline void printk_delay(int leve
+ DECLARE_WAIT_QUEUE_HEAD(log_wait);
+ /* All 3 protected by @syslog_lock. */
+ /* the next printk record to read by syslog(READ) or /proc/kmsg */
+@@ -1641,6 +1645,110 @@ static inline void printk_delay(int leve
}
}
@@ -106,20 +108,20 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ return false;
+}
+
-+static bool print_sync(struct console *con, char *buf, size_t buf_size, u64 *seq)
++static bool print_sync(struct console *con, u64 *seq)
+{
+ struct printk_info info;
+ struct printk_record r;
+ size_t text_len;
+
-+ prb_rec_init_rd(&r, &info, buf, buf_size);
++ prb_rec_init_rd(&r, &info, &con->sync_buf[0], sizeof(con->sync_buf));
+
+ if (!prb_read_valid(prb, *seq, &r))
+ return false;
+
+ text_len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time);
+
-+ if (!call_sync_console_driver(con, buf, text_len))
++ if (!call_sync_console_driver(con, &con->sync_buf[0], text_len))
+ return false;
+
+ *seq = r.info->seq;
@@ -135,7 +137,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ return true;
+}
+
-+static void print_sync_until(u64 seq, struct console *con, char *buf, size_t buf_size)
++static void print_sync_until(struct console *con, u64 seq)
+{
+ unsigned int flags;
+ u64 printk_seq;
@@ -143,7 +145,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ if (!con) {
+ for_each_console(con) {
+ if (console_can_sync(con))
-+ print_sync_until(seq, con, buf, buf_size);
++ print_sync_until(con, seq);
+ }
+ return;
+ }
@@ -153,7 +155,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ printk_seq = atomic64_read(&console_seq);
+ if (printk_seq >= seq)
+ break;
-+ if (!print_sync(con, buf, buf_size, &printk_seq))
++ if (!print_sync(con, &printk_seq))
+ break;
+ atomic64_set(&console_seq, printk_seq + 1);
+ }
@@ -163,7 +165,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/*
* Special console_lock variants that help to reduce the risk of soft-lockups.
* They allow to pass console_lock to another printk() call using a busy wait.
-@@ -1941,6 +2050,8 @@ static void call_console_drivers(const c
+@@ -1815,6 +1923,8 @@ static void call_console_drivers(const c
if (!cpu_online(smp_processor_id()) &&
!(con->flags & CON_ANYTIME))
continue;
@@ -172,15 +174,31 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (con->flags & CON_EXTENDED)
con->write(con, ext_text, ext_len);
else {
-@@ -1964,6 +2075,7 @@ int vprintk_store(int facility, int leve
+@@ -1926,6 +2036,7 @@ int vprintk_store(int facility, int leve
const u32 caller_id = printk_caller_id();
struct prb_reserved_entry e;
enum log_flags lflags = 0;
+ bool final_commit = false;
- unsigned long irqflags;
struct printk_record r;
+ unsigned long irqflags;
u16 trunc_msg_len = 0;
-@@ -2027,6 +2139,7 @@ int vprintk_store(int facility, int leve
+@@ -1934,6 +2045,7 @@ int vprintk_store(int facility, int leve
+ u16 text_len;
+ int ret = 0;
+ u64 ts_nsec;
++ u64 seq;
+
+ ts_nsec = local_clock();
+
+@@ -1979,6 +2091,7 @@ int vprintk_store(int facility, int leve
+ if (lflags & LOG_CONT) {
+ prb_rec_init_wr(&r, text_len);
+ if (prb_reserve_in_last(&e, prb, &r, caller_id, LOG_LINE_MAX)) {
++ seq = r.info->seq;
+ text_len = printk_sprint(&r.text_buf[r.info->text_len], text_len,
+ facility, &lflags, fmt, args2);
+ r.info->text_len += text_len;
+@@ -1986,6 +2099,7 @@ int vprintk_store(int facility, int leve
if (lflags & LOG_NEWLINE) {
r.info->flags |= LOG_NEWLINE;
prb_final_commit(&e);
@@ -188,32 +206,47 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
} else {
prb_commit(&e);
}
-@@ -2068,10 +2181,15 @@ int vprintk_store(int facility, int leve
+@@ -2005,6 +2119,8 @@ int vprintk_store(int facility, int leve
+ goto out;
+ }
+
++ seq = r.info->seq;
++
+ /* fill message */
+ text_len = printk_sprint(&r.text_buf[0], text_len, facility, &lflags, fmt, args2);
+ if (trunc_msg_len)
+@@ -2019,13 +2135,19 @@ int vprintk_store(int facility, int leve
+ memcpy(&r.info->dev_info, dev_info, sizeof(r.info->dev_info));
+
+ /* A message without a trailing newline can be continued. */
+- if (!(lflags & LOG_NEWLINE))
++ if (!(lflags & LOG_NEWLINE)) {
prb_commit(&e);
- } else {
+- else
++ } else {
prb_final_commit(&e);
+ final_commit = true;
- }
++ }
ret = text_len + trunc_msg_len;
out:
+ /* only the kernel may perform synchronous printing */
+ if (facility == 0 && final_commit && any_console_can_sync())
-+ print_sync_until(seq + 1, NULL, text, PREFIX_MAX + LOG_LINE_MAX);
++ print_sync_until(NULL, seq + 1);
+
- put_sprint_buf(sprint_id, irqflags);
+ va_end(args2);
+ printk_exit(irqflags);
return ret;
- }
-@@ -2176,7 +2294,7 @@ EXPORT_SYMBOL(printk);
+@@ -2130,6 +2252,8 @@ EXPORT_SYMBOL(printk);
+ #define prb_read_valid(rb, seq, r) false
#define prb_first_valid_seq(rb) 0
++#define kernel_sync_mode() false
++
static u64 syslog_seq;
--static u64 console_seq;
-+static atomic64_t console_seq = ATOMI64_INIT(0);
+ static atomic64_t console_seq = ATOMIC64_INIT(0);
static u64 exclusive_console_stop_seq;
- static unsigned long console_dropped;
-
-@@ -2460,6 +2578,8 @@ static int have_callable_console(void)
+@@ -2415,6 +2539,8 @@ static int have_callable_console(void)
*/
static inline int can_use_console(void)
{
@@ -222,88 +255,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return cpu_online(raw_smp_processor_id()) || have_callable_console();
}
-@@ -2485,6 +2605,7 @@ void console_unlock(void)
- bool do_cond_resched, retry;
- struct printk_info info;
- struct printk_record r;
-+ u64 seq;
-
- if (console_suspended) {
- up_console_sem();
-@@ -2528,12 +2649,14 @@ void console_unlock(void)
-
- printk_safe_enter_irqsave(flags);
- skip:
-- if (!prb_read_valid(prb, console_seq, &r))
-+ seq = atomic64_read(&console_seq);
-+ if (!prb_read_valid(prb, seq, &r))
- break;
-
-- if (console_seq != r.info->seq) {
-- console_dropped += r.info->seq - console_seq;
-- console_seq = r.info->seq;
-+ if (seq != r.info->seq) {
-+ console_dropped += r.info->seq - seq;
-+ atomic64_set(&console_seq, r.info->seq);
-+ seq = r.info->seq;
- }
-
- if (suppress_message_printing(r.info->level)) {
-@@ -2542,13 +2665,13 @@ void console_unlock(void)
- * directly to the console when we received it, and
- * record that has level above the console loglevel.
- */
-- console_seq++;
-+ atomic64_set(&console_seq, seq + 1);
- goto skip;
- }
-
- /* Output to all consoles once old messages replayed. */
- if (unlikely(exclusive_console &&
-- console_seq >= exclusive_console_stop_seq)) {
-+ seq >= exclusive_console_stop_seq)) {
- exclusive_console = NULL;
- }
-
-@@ -2569,7 +2692,7 @@ void console_unlock(void)
- len = record_print_text(&r,
- console_msg_format & MSG_FORMAT_SYSLOG,
- printk_time);
-- console_seq++;
-+ atomic64_set(&console_seq, seq + 1);
-
- /*
- * While actively printing out messages, if another printk()
-@@ -2604,7 +2727,7 @@ void console_unlock(void)
- * there's a new owner and the console_unlock() from them will do the
- * flush, no worries.
- */
-- retry = prb_read_valid(prb, console_seq, NULL);
-+ retry = prb_read_valid(prb, atomic64_read(&console_seq), NULL);
- printk_safe_exit_irqrestore(flags);
-
- if (retry && console_trylock())
-@@ -2669,7 +2792,7 @@ void console_flush_on_panic(enum con_flu
- console_may_schedule = 0;
-
- if (mode == CONSOLE_REPLAY_ALL)
-- console_seq = prb_first_valid_seq(prb);
-+ atomic64_set(&console_seq, prb_first_valid_seq(prb));
- console_unlock();
- }
-
-@@ -2904,8 +3027,8 @@ void register_console(struct console *ne
- * ignores console_lock.
- */
- exclusive_console = newcon;
-- exclusive_console_stop_seq = console_seq;
-- console_seq = syslog_seq;
-+ exclusive_console_stop_seq = atomic64_read(&console_seq);
-+ atomic64_set(&console_seq, syslog_seq);
- syslog_unlock_irqrestore(flags);
- }
- console_unlock();
-@@ -3273,6 +3396,18 @@ void kmsg_dump(enum kmsg_dump_reason rea
+@@ -3231,6 +3357,18 @@ void kmsg_dump(enum kmsg_dump_reason rea
{
struct kmsg_dumper *dumper;
diff --git a/patches/0012-printk-move-console-printing-to-kthreads.patch b/patches/0012-printk-move-console-printing-to-kthreads.patch
index 39df8851ff79..4f3310e13ed0 100644
--- a/patches/0012-printk-move-console-printing-to-kthreads.patch
+++ b/patches/0012-printk-move-console-printing-to-kthreads.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 22:30:38 +0206
-Subject: [PATCH 12/15] printk: move console printing to kthreads
+Date: Mon, 30 Nov 2020 01:42:07 +0106
+Subject: [PATCH 12/16] printk: move console printing to kthreads
Create a kthread for each console to perform console printing. Now
all console printing is fully asynchronous except for the boot
@@ -14,15 +14,15 @@ Signed-off-by: John Ogness <john.ogness@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
include/linux/console.h | 2
- kernel/printk/printk.c | 586 +++++++++++++++---------------------------------
- 2 files changed, 190 insertions(+), 398 deletions(-)
+ kernel/printk/printk.c | 635 ++++++++++++++----------------------------------
+ 2 files changed, 192 insertions(+), 445 deletions(-)
--- a/include/linux/console.h
+++ b/include/linux/console.h
-@@ -151,6 +151,8 @@ struct console {
- short flags;
- short index;
- int cflag;
+@@ -155,6 +155,8 @@ struct console {
+ #ifdef CONFIG_PRINTK
+ char sync_buf[CONSOLE_LOG_MAX];
+ #endif
+ atomic64_t printk_seq;
+ struct task_struct *thread;
void *data;
@@ -38,7 +38,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#include <linux/clocksource.h>
#include <linux/sched/clock.h>
#include <linux/sched/debug.h>
-@@ -271,11 +272,6 @@ static void __up_console_sem(unsigned lo
+@@ -268,11 +269,6 @@ static void __up_console_sem(unsigned lo
static int console_locked, console_suspended;
/*
@@ -50,7 +50,19 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
* Array of consoles built from command line options (console=)
*/
-@@ -374,13 +370,6 @@ static u64 syslog_seq;
+@@ -356,10 +352,10 @@ enum log_flags {
+ LOG_CONT = 8, /* text is a fragment of a continuation line */
+ };
+
++#ifdef CONFIG_PRINTK
+ /* The syslog_lock protects syslog_* variables. */
+ static DEFINE_SPINLOCK(syslog_lock);
+
+-#ifdef CONFIG_PRINTK
+ /* Set to enable sync mode. Once set, it is never cleared. */
+ static bool sync_mode;
+
+@@ -370,13 +366,6 @@ static u64 syslog_seq;
static size_t syslog_partial;
static bool syslog_time;
@@ -64,7 +76,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* the next printk record to read after the last 'clear' command */
static atomic64_t clear_seq = ATOMIC64_INIT(0);
-@@ -1783,6 +1772,8 @@ static bool console_can_sync(struct cons
+@@ -1656,6 +1645,8 @@ static bool console_can_sync(struct cons
return false;
if (con->write_atomic && kernel_sync_mode())
return true;
@@ -73,7 +85,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return false;
}
-@@ -1792,6 +1783,8 @@ static bool call_sync_console_driver(str
+@@ -1665,6 +1656,8 @@ static bool call_sync_console_driver(str
return false;
if (con->write_atomic && kernel_sync_mode())
con->write_atomic(con, text, text_len);
@@ -82,7 +94,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
else
return false;
-@@ -1866,202 +1859,16 @@ static void print_sync_until(u64 seq, st
+@@ -1739,202 +1732,16 @@ static void print_sync_until(struct cons
console_atomic_lock(&flags);
for (;;) {
@@ -90,7 +102,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ printk_seq = atomic64_read(&con->printk_seq);
if (printk_seq >= seq)
break;
- if (!print_sync(con, buf, buf_size, &printk_seq))
+ if (!print_sync(con, &printk_seq))
break;
- atomic64_set(&console_seq, printk_seq + 1);
+ atomic64_set(&con->printk_seq, printk_seq + 1);
@@ -284,10 +296,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- }
-}
-
- static inline u32 printk_caller_id(void)
- {
- return in_task() ? task_pid_nr(current) :
-@@ -2199,40 +2006,16 @@ asmlinkage int vprintk_emit(int facility
+ #ifdef CONFIG_PRINTK_NMI
+ #define NUM_RECURSION_CTX 2
+ #else
+@@ -2158,40 +1965,16 @@ asmlinkage int vprintk_emit(int facility
const char *fmt, va_list args)
{
int printed_len;
@@ -302,9 +314,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
level = LOGLEVEL_DEFAULT;
- in_sched = true;
- }
--
-- printk_delay(level);
+- printk_delay(level);
+-
- /* This stops the holder of console_sem just where we want him */
printed_len = vprintk_store(facility, level, dev_info, fmt, args);
@@ -329,35 +341,233 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
wake_up_klogd();
return printed_len;
}
-@@ -2294,9 +2077,6 @@ EXPORT_SYMBOL(printk);
+@@ -2243,6 +2026,153 @@ asmlinkage __visible int printk(const ch
+ }
+ EXPORT_SYMBOL(printk);
+
++static int printk_kthread_func(void *data)
++{
++ struct console *con = data;
++ unsigned long dropped = 0;
++ char *dropped_text = NULL;
++ struct printk_info info;
++ struct printk_record r;
++ char *ext_text = NULL;
++ size_t dropped_len;
++ int ret = -ENOMEM;
++ char *text = NULL;
++ char *write_text;
++ u64 printk_seq;
++ size_t len;
++ int error;
++ u64 seq;
++
++ if (con->flags & CON_EXTENDED) {
++ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
++ if (!ext_text)
++ goto out;
++ }
++ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
++ dropped_text = kmalloc(64, GFP_KERNEL);
++ if (!text || !dropped_text)
++ goto out;
++
++ if (con->flags & CON_EXTENDED)
++ write_text = ext_text;
++ else
++ write_text = text;
++
++ seq = atomic64_read(&con->printk_seq);
++
++ prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX);
++
++ for (;;) {
++ error = wait_event_interruptible(log_wait,
++ prb_read_valid(prb, seq, &r) || kthread_should_stop());
++
++ if (kthread_should_stop())
++ break;
++
++ if (error)
++ continue;
++
++ if (seq != r.info->seq) {
++ dropped += r.info->seq - seq;
++ seq = r.info->seq;
++ }
++
++ seq++;
++
++ if (!(con->flags & CON_ENABLED))
++ continue;
++
++ if (suppress_message_printing(r.info->level))
++ continue;
++
++ if (con->flags & CON_EXTENDED) {
++ len = info_print_ext_header(ext_text,
++ CONSOLE_EXT_LOG_MAX,
++ r.info);
++ len += msg_print_ext_body(ext_text + len,
++ CONSOLE_EXT_LOG_MAX - len,
++ &r.text_buf[0], r.info->text_len,
++ &r.info->dev_info);
++ } else {
++ len = record_print_text(&r,
++ console_msg_format & MSG_FORMAT_SYSLOG,
++ printk_time);
++ }
++
++ printk_seq = atomic64_read(&con->printk_seq);
++
++ console_lock();
++ console_may_schedule = 0;
++
++ if (kernel_sync_mode() && con->write_atomic) {
++ console_unlock();
++ break;
++ }
++
++ if (!(con->flags & CON_EXTENDED) && dropped) {
++ dropped_len = snprintf(dropped_text, 64,
++ "** %lu printk messages dropped **\n",
++ dropped);
++ dropped = 0;
++
++ con->write(con, dropped_text, dropped_len);
++ printk_delay(r.info->level);
++ }
++
++ con->write(con, write_text, len);
++ if (len)
++ printk_delay(r.info->level);
++
++ atomic64_cmpxchg_relaxed(&con->printk_seq, printk_seq, seq);
++
++ console_unlock();
++ }
++out:
++ kfree(dropped_text);
++ kfree(text);
++ kfree(ext_text);
++ pr_info("%sconsole [%s%d]: printing thread stopped\n",
++ (con->flags & CON_BOOT) ? "boot" : "",
++ con->name, con->index);
++ return ret;
++}
++
++/* Must be called within console_lock(). */
++static void start_printk_kthread(struct console *con)
++{
++ con->thread = kthread_run(printk_kthread_func, con,
++ "pr/%s%d", con->name, con->index);
++ if (IS_ERR(con->thread)) {
++ pr_err("%sconsole [%s%d]: unable to start printing thread\n",
++ (con->flags & CON_BOOT) ? "boot" : "",
++ con->name, con->index);
++ return;
++ }
++ pr_info("%sconsole [%s%d]: printing thread started\n",
++ (con->flags & CON_BOOT) ? "boot" : "",
++ con->name, con->index);
++}
++
++/* protected by console_lock */
++static bool kthreads_started;
++
++/* Must be called within console_lock(). */
++static void console_try_thread(struct console *con)
++{
++ if (kthreads_started) {
++ start_printk_kthread(con);
++ return;
++ }
++
++ /*
++ * The printing threads have not been started yet. If this console
++ * can print synchronously, print all unprinted messages.
++ */
++
++ if (console_can_sync(con))
++ print_sync_until(con, prb_next_seq(prb));
++}
++
+ #else /* CONFIG_PRINTK */
+
+ #define LOG_LINE_MAX 0
+@@ -2251,32 +2181,11 @@ EXPORT_SYMBOL(printk);
+
+ #define prb_read_valid(rb, seq, r) false
#define prb_first_valid_seq(rb) 0
++#define prb_next_seq(rb) 0
- static u64 syslog_seq;
--static atomic64_t console_seq = ATOMI64_INIT(0);
+ #define kernel_sync_mode() false
+
+-static u64 syslog_seq;
+-static atomic64_t console_seq = ATOMIC64_INIT(0);
-static u64 exclusive_console_stop_seq;
-static unsigned long console_dropped;
-
- static size_t record_print_text(const struct printk_record *r,
- bool syslog, bool time)
-@@ -2311,8 +2091,6 @@ static ssize_t info_print_ext_header(cha
- static ssize_t msg_print_ext_body(char *buf, size_t size,
- char *text, size_t text_len,
- struct dev_printk_info *dev_info) { return 0; }
+-
+-static size_t record_print_text(const struct printk_record *r,
+- bool syslog, bool time)
+-{
+- return 0;
+-}
+-static ssize_t info_print_ext_header(char *buf, size_t size,
+- struct printk_info *info)
+-{
+- return 0;
+-}
+-static ssize_t msg_print_ext_body(char *buf, size_t size,
+- char *text, size_t text_len,
+- struct dev_printk_info *dev_info) { return 0; }
-static void console_lock_spinning_enable(void) { }
-static int console_lock_spinning_disable_and_check(void) { return 0; }
- static void call_console_drivers(const char *ext_text, size_t ext_len,
- const char *text, size_t len) {}
- static bool suppress_message_printing(int level) { return false; }
-@@ -2578,8 +2356,6 @@ static int have_callable_console(void)
- */
- static inline int can_use_console(void)
- {
-- if (kernel_sync_mode())
-- return false;
- return cpu_online(raw_smp_processor_id()) || have_callable_console();
+-static void call_console_drivers(const char *ext_text, size_t ext_len,
+- const char *text, size_t len) {}
+-static bool suppress_message_printing(int level) { return false; }
++#define console_try_thread(con)
+
+ #endif /* CONFIG_PRINTK */
+
+@@ -2514,36 +2423,6 @@ int is_console_locked(void)
}
+ EXPORT_SYMBOL(is_console_locked);
-@@ -2599,139 +2375,14 @@ static inline int can_use_console(void)
+-/*
+- * Check if we have any console that is capable of printing while cpu is
+- * booting or shutting down. Requires console_sem.
+- */
+-static int have_callable_console(void)
+-{
+- struct console *con;
+-
+- for_each_console(con)
+- if ((con->flags & CON_ENABLED) &&
+- (con->flags & CON_ANYTIME))
+- return 1;
+-
+- return 0;
+-}
+-
+-/*
+- * Can we actually use the console at this time on this cpu?
+- *
+- * Console drivers may assume that per-cpu resources have been allocated. So
+- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
+- * call them until this CPU is officially up.
+- */
+-static inline int can_use_console(void)
+-{
+- if (kernel_sync_mode())
+- return false;
+- return cpu_online(raw_smp_processor_id()) || have_callable_console();
+-}
+-
+ /**
+ * console_unlock - unlock the console system
+ *
+@@ -2560,139 +2439,14 @@ static inline int can_use_console(void)
*/
void console_unlock(void)
{
@@ -497,7 +707,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
EXPORT_SYMBOL(console_unlock);
-@@ -2781,18 +2432,20 @@ void console_unblank(void)
+@@ -2742,18 +2496,20 @@ void console_unblank(void)
*/
void console_flush_on_panic(enum con_flush_mode mode)
{
@@ -528,16 +738,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
console_unlock();
}
-@@ -2906,6 +2559,8 @@ static int try_enable_new_console(struct
- return -ENOENT;
- }
-
-+static void console_try_thread(struct console *con);
-+
- /*
- * The console driver calls this routine during kernel initialization
- * to register the console printing procedure with printk() and to
-@@ -2927,7 +2582,6 @@ static int try_enable_new_console(struct
+@@ -2888,7 +2644,6 @@ static int try_enable_new_console(struct
*/
void register_console(struct console *newcon)
{
@@ -545,7 +746,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
struct console *bcon = NULL;
int err;
-@@ -2951,6 +2605,8 @@ void register_console(struct console *ne
+@@ -2912,6 +2667,8 @@ void register_console(struct console *ne
}
}
@@ -554,12 +755,12 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (console_drivers && console_drivers->flags & CON_BOOT)
bcon = console_drivers;
-@@ -3015,22 +2671,12 @@ void register_console(struct console *ne
+@@ -2976,22 +2733,12 @@ void register_console(struct console *ne
if (newcon->flags & CON_EXTENDED)
nr_ext_console_drivers++;
- if (newcon->flags & CON_PRINTBUFFER) {
-- syslog_lock_irqsave(flags);
+- spin_lock_irqsave(&syslog_lock, flags);
- /*
- * We're about to replay the log buffer. Only do this to the
- * just-registered console to avoid excessive message spam to
@@ -572,7 +773,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
- exclusive_console = newcon;
- exclusive_console_stop_seq = atomic64_read(&console_seq);
- atomic64_set(&console_seq, syslog_seq);
-- syslog_unlock_irqrestore(flags);
+- spin_unlock_irqrestore(&syslog_lock, flags);
- }
+ if (newcon->flags & CON_PRINTBUFFER)
+ atomic64_set(&newcon->printk_seq, 0);
@@ -583,7 +784,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
console_unlock();
console_sysfs_notify();
-@@ -3104,6 +2750,9 @@ int unregister_console(struct console *c
+@@ -3065,6 +2812,9 @@ int unregister_console(struct console *c
console_unlock();
console_sysfs_notify();
@@ -593,176 +794,23 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (console->exit)
res = console->exit(console);
-@@ -3147,6 +2796,154 @@ void __init console_init(void)
- }
- }
-
-+static int printk_kthread_func(void *data)
-+{
-+ struct console *con = data;
-+ unsigned long dropped = 0;
-+ struct printk_info info;
-+ struct printk_record r;
-+ char *ext_text = NULL;
-+ size_t dropped_len;
-+ char *dropped_text;
-+ int ret = -ENOMEM;
-+ char *write_text;
-+ u64 printk_seq;
-+ size_t len;
-+ char *text;
-+ int error;
-+ u64 seq;
-+
-+ if (con->flags & CON_EXTENDED) {
-+ ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL);
-+ if (!ext_text)
-+ return ret;
-+ }
-+ text = kmalloc(LOG_LINE_MAX + PREFIX_MAX, GFP_KERNEL);
-+ dropped_text = kmalloc(64, GFP_KERNEL);
-+ if (!text || !dropped_text)
-+ goto out;
-+
-+ if (con->flags & CON_EXTENDED)
-+ write_text = ext_text;
-+ else
-+ write_text = text;
-+
-+ seq = atomic64_read(&con->printk_seq);
-+
-+ prb_rec_init_rd(&r, &info, text, LOG_LINE_MAX + PREFIX_MAX);
-+
-+ for (;;) {
-+ error = wait_event_interruptible(log_wait,
-+ prb_read_valid(prb, seq, &r) || kthread_should_stop());
-+
-+ if (kthread_should_stop())
-+ break;
-+
-+ if (error)
-+ continue;
-+
-+ if (seq != r.info->seq) {
-+ dropped += r.info->seq - seq;
-+ seq = r.info->seq;
-+ }
-+
-+ seq++;
-+
-+ if (!(con->flags & CON_ENABLED))
-+ continue;
-+
-+ if (suppress_message_printing(r.info->level))
-+ continue;
-+
-+ if (con->flags & CON_EXTENDED) {
-+ len = info_print_ext_header(ext_text,
-+ CONSOLE_EXT_LOG_MAX,
-+ r.info);
-+ len += msg_print_ext_body(ext_text + len,
-+ CONSOLE_EXT_LOG_MAX - len,
-+ &r.text_buf[0], r.info->text_len,
-+ &r.info->dev_info);
-+ } else {
-+ len = record_print_text(&r,
-+ console_msg_format & MSG_FORMAT_SYSLOG,
-+ printk_time);
-+ }
-+
-+ printk_seq = atomic64_read(&con->printk_seq);
-+
-+ console_lock();
-+ console_may_schedule = 0;
-+
-+ if (kernel_sync_mode() && con->write_atomic) {
-+ console_unlock();
-+ break;
-+ }
-+
-+ if (!(con->flags & CON_EXTENDED) && dropped) {
-+ dropped_len = snprintf(dropped_text, 64,
-+ "** %lu printk messages dropped **\n",
-+ dropped);
-+ dropped = 0;
-+
-+ con->write(con, dropped_text, dropped_len);
-+ printk_delay(r.info->level);
-+ }
-+
-+ con->write(con, write_text, len);
-+ if (len)
-+ printk_delay(r.info->level);
-+
-+ atomic64_cmpxchg_relaxed(&con->printk_seq, printk_seq, seq);
-+
-+ console_unlock();
-+ }
-+out:
-+ kfree(dropped_text);
-+ kfree(text);
-+ kfree(ext_text);
-+ pr_info("%sconsole [%s%d]: printing thread stopped\n",
-+ (con->flags & CON_BOOT) ? "boot" : "" ,
-+ con->name, con->index);
-+ return ret;
-+}
-+
-+static void start_printk_kthread(struct console *con)
-+{
-+ con->thread = kthread_run(printk_kthread_func, con,
-+ "pr/%s%d", con->name, con->index);
-+ if (IS_ERR(con->thread)) {
-+ pr_err("%sconsole [%s%d]: unable to start printing thread\n",
-+ (con->flags & CON_BOOT) ? "boot" : "" ,
-+ con->name, con->index);
-+ return;
-+ }
-+ pr_info("%sconsole [%s%d]: printing thread started\n",
-+ (con->flags & CON_BOOT) ? "boot" : "" ,
-+ con->name, con->index);
-+}
-+
-+static bool kthreads_started;
-+
-+static void console_try_thread(struct console *con)
-+{
-+ unsigned long irqflags;
-+ int sprint_id;
-+ char *buf;
-+
-+ if (kthreads_started) {
-+ start_printk_kthread(con);
-+ return;
-+ }
-+
-+ buf = get_sprint_buf(&sprint_id, &irqflags);
-+ if (!buf)
-+ return;
-+
-+ print_sync_until(prb_next_seq(prb), con, buf, PREFIX_MAX + LOG_LINE_MAX);
-+
-+ put_sprint_buf(sprint_id, irqflags);
-+}
-+
- /*
- * Some boot consoles access data that is in the init section and which will
- * be discarded after the initcalls have been run. To make sure that no code
-@@ -3186,6 +2983,13 @@ static int __init printk_late_init(void)
+@@ -3147,6 +2897,15 @@ static int __init printk_late_init(void)
unregister_console(con);
}
}
+
++#ifdef CONFIG_PRINTK
+ console_lock();
+ for_each_console(con)
+ start_printk_kthread(con);
+ kthreads_started = true;
+ console_unlock();
++#endif
+
ret = cpuhp_setup_state_nocalls(CPUHP_PRINTK_DEAD, "printk:dead", NULL,
console_cpu_notify);
WARN_ON(ret < 0);
-@@ -3201,7 +3005,6 @@ late_initcall(printk_late_init);
+@@ -3162,7 +2921,6 @@ late_initcall(printk_late_init);
* Delayed printk version, for scheduler-internal messages:
*/
#define PRINTK_PENDING_WAKEUP 0x01
@@ -770,7 +818,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
static DEFINE_PER_CPU(int, printk_pending);
-@@ -3209,12 +3012,6 @@ static void wake_up_klogd_work_func(stru
+@@ -3170,12 +2928,6 @@ static void wake_up_klogd_work_func(stru
{
int pending = __this_cpu_xchg(printk_pending, 0);
@@ -783,7 +831,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (pending & PRINTK_PENDING_WAKEUP)
wake_up_interruptible(&log_wait);
}
-@@ -3239,13 +3036,6 @@ void wake_up_klogd(void)
+@@ -3200,13 +2952,6 @@ void wake_up_klogd(void)
void defer_console_output(void)
{
diff --git a/patches/0013-printk-remove-deferred-printing.patch b/patches/0013-printk-remove-deferred-printing.patch
index d0e55876f372..ca30c73593dd 100644
--- a/patches/0013-printk-remove-deferred-printing.patch
+++ b/patches/0013-printk-remove-deferred-printing.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 22:53:30 +0206
-Subject: [PATCH 13/15] printk: remove deferred printing
+Date: Mon, 30 Nov 2020 01:42:08 +0106
+Subject: [PATCH 13/16] printk: remove deferred printing
Since printing occurs either atomically or from the printing
kthread, there is no need for any deferring or tracking possible
@@ -15,10 +15,10 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
include/linux/printk.h | 12 ------
kernel/printk/Makefile | 1
kernel/printk/internal.h | 70 -----------------------------------
- kernel/printk/printk.c | 40 ++++++--------------
+ kernel/printk/printk.c | 57 +++++++++++------------------
kernel/printk/printk_safe.c | 86 --------------------------------------------
kernel/trace/trace.c | 2 -
- 9 files changed, 12 insertions(+), 206 deletions(-)
+ 9 files changed, 22 insertions(+), 213 deletions(-)
delete mode 100644 kernel/printk/internal.h
delete mode 100644 kernel/printk/printk_safe.c
@@ -66,7 +66,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
} while (0)
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
-@@ -149,18 +149,6 @@ static inline __printf(1, 2) __cold
+@@ -150,18 +150,6 @@ static inline __printf(1, 2) __cold
void early_printk(const char *s, ...) { }
#endif
@@ -168,7 +168,15 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-#endif /* CONFIG_PRINTK */
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -60,7 +60,6 @@
+@@ -45,6 +45,7 @@
+ #include <linux/ctype.h>
+ #include <linux/uio.h>
+ #include <linux/kthread.h>
++#include <linux/kdb.h>
+ #include <linux/clocksource.h>
+ #include <linux/sched/clock.h>
+ #include <linux/sched/debug.h>
+@@ -60,7 +61,6 @@
#include "printk_ringbuffer.h"
#include "console_cmdline.h"
#include "braille.h"
@@ -176,7 +184,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
int console_printk[4] = {
CONSOLE_LOGLEVEL_DEFAULT, /* console_loglevel */
-@@ -230,19 +229,7 @@ static int nr_ext_console_drivers;
+@@ -227,19 +227,7 @@ static int nr_ext_console_drivers;
static int __down_trylock_console_sem(unsigned long ip)
{
@@ -197,7 +205,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 1;
mutex_acquire(&console_lock_dep_map, 0, 1, ip);
return 0;
-@@ -251,13 +238,9 @@ static int __down_trylock_console_sem(un
+@@ -248,13 +236,9 @@ static int __down_trylock_console_sem(un
static void __up_console_sem(unsigned long ip)
{
@@ -211,11 +219,42 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
}
#define up_console_sem() __up_console_sem(_RET_IP_)
-@@ -2027,6 +2010,16 @@ int vprintk_default(const char *fmt, va_
+@@ -411,7 +395,7 @@ static struct printk_ringbuffer *prb = &
+ */
+ static bool __printk_percpu_data_ready __read_mostly;
+
+-bool printk_percpu_data_ready(void)
++static bool printk_percpu_data_ready(void)
+ {
+ return __printk_percpu_data_ready;
+ }
+@@ -1836,9 +1820,9 @@ static u16 printk_sprint(char *text, u16
}
- EXPORT_SYMBOL_GPL(vprintk_default);
-+__printf(1, 0) int vprintk_func(const char *fmt, va_list args)
+ __printf(4, 0)
+-int vprintk_store(int facility, int level,
+- const struct dev_printk_info *dev_info,
+- const char *fmt, va_list args)
++static int vprintk_store(int facility, int level,
++ const struct dev_printk_info *dev_info,
++ const char *fmt, va_list args)
+ {
+ const u32 caller_id = printk_caller_id();
+ struct prb_reserved_entry e;
+@@ -1980,11 +1964,22 @@ asmlinkage int vprintk_emit(int facility
+ }
+ EXPORT_SYMBOL(vprintk_emit);
+
+-int vprintk_default(const char *fmt, va_list args)
++__printf(1, 0)
++static int vprintk_default(const char *fmt, va_list args)
+ {
+ return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
+ }
+-EXPORT_SYMBOL_GPL(vprintk_default);
++
++__printf(1, 0)
++static int vprintk_func(const char *fmt, va_list args)
+{
+#ifdef CONFIG_KGDB_KDB
+ /* Allow to pass printk() to kdb but avoid a recursion. */
@@ -224,20 +263,21 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+#endif
+ return vprintk_default(fmt, args);
+}
-+
+
asmlinkage int vprintk(const char *fmt, va_list args)
{
- return vprintk_func(fmt, args);
-@@ -3034,18 +3027,9 @@ void wake_up_klogd(void)
+@@ -2950,18 +2945,10 @@ void wake_up_klogd(void)
preempt_enable();
}
-void defer_console_output(void)
--{
++__printf(1, 0)
++static int vprintk_deferred(const char *fmt, va_list args)
+ {
-}
-
- int vprintk_deferred(const char *fmt, va_list args)
- {
+-int vprintk_deferred(const char *fmt, va_list args)
+-{
- int r;
-
- r = vprintk_emit(0, LOGLEVEL_SCHED, NULL, fmt, args);
diff --git a/patches/0014-printk-add-console-handover.patch b/patches/0014-printk-add-console-handover.patch
index be2dfc39c3e2..20fc3125a4ce 100644
--- a/patches/0014-printk-add-console-handover.patch
+++ b/patches/0014-printk-add-console-handover.patch
@@ -1,6 +1,6 @@
From: John Ogness <john.ogness@linutronix.de>
-Date: Mon, 19 Oct 2020 23:03:44 +0206
-Subject: [PATCH 14/15] printk: add console handover
+Date: Mon, 30 Nov 2020 01:42:09 +0106
+Subject: [PATCH 14/16] printk: add console handover
If earlyprintk is used, a boot console will print directly to the
console immediately. The boot console will unregister itself as soon
@@ -25,7 +25,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
--- a/include/linux/console.h
+++ b/include/linux/console.h
-@@ -137,6 +137,7 @@ static inline int con_debug_leave(void)
+@@ -138,6 +138,7 @@ static inline int con_debug_leave(void)
#define CON_ANYTIME (16) /* Safe to call when cpu is offline */
#define CON_BRL (32) /* Used for a braille device */
#define CON_EXTENDED (64) /* Use the extended output format a la /dev/kmsg */
@@ -35,7 +35,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
char name[16];
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
-@@ -1755,6 +1755,8 @@ static bool console_can_sync(struct cons
+@@ -1629,6 +1629,8 @@ static bool console_can_sync(struct cons
return false;
if (con->write_atomic && kernel_sync_mode())
return true;
@@ -44,7 +44,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (con->write && (con->flags & CON_BOOT) && !con->thread)
return true;
return false;
-@@ -1766,6 +1768,8 @@ static bool call_sync_console_driver(str
+@@ -1640,6 +1642,8 @@ static bool call_sync_console_driver(str
return false;
if (con->write_atomic && kernel_sync_mode())
con->write_atomic(con, text, text_len);
@@ -53,7 +53,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
else if (con->write && (con->flags & CON_BOOT) && !con->thread)
con->write(con, text, text_len);
else
-@@ -2641,8 +2645,10 @@ void register_console(struct console *ne
+@@ -2705,8 +2709,10 @@ void register_console(struct console *ne
* the real console are the same physical device, it's annoying to
* see the beginning boot messages twice
*/
diff --git a/patches/0015-printk-add-pr_flush.patch b/patches/0015-printk-add-pr_flush.patch
new file mode 100644
index 000000000000..26a704450f72
--- /dev/null
+++ b/patches/0015-printk-add-pr_flush.patch
@@ -0,0 +1,103 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 30 Nov 2020 01:42:10 +0106
+Subject: [PATCH 15/16] printk: add pr_flush()
+
+Provide a function to allow waiting for console printers to catch
+up to the latest logged message.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/printk.h | 2 +
+ kernel/printk/printk.c | 72 +++++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 74 insertions(+)
+
+--- a/include/linux/printk.h
++++ b/include/linux/printk.h
+@@ -476,6 +476,8 @@ extern int kptr_restrict;
+ no_printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__)
+ #endif
+
++bool pr_flush(bool may_sleep, int timeout_ms, bool reset_on_progress);
++
+ /*
+ * ratelimited messages with local ratelimit_state,
+ * no local ratelimit_state used in the !PRINTK case
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3436,3 +3436,75 @@ void console_atomic_unlock(unsigned int
+ prb_unlock(&printk_cpulock, flags);
+ }
+ EXPORT_SYMBOL(console_atomic_unlock);
++
++static void pr_msleep(bool may_sleep, int ms)
++{
++ if (may_sleep) {
++ msleep(ms);
++ } else {
++ while (ms--)
++ udelay(1000);
++ }
++}
++
++/**
++ * pr_flush() - Wait for printing threads to catch up.
++ *
++ * @may_sleep: Context allows msleep() calls.
++ * @timeout_ms: The maximum time (in ms) to wait.
++ * @reset_on_progress: Reset the timeout if forward progress is seen.
++ *
++ * A value of 0 for @timeout_ms means no waiting will occur. A value of -1
++ * represents infinite waiting.
++ *
++ * If @reset_on_progress is true, the timeout will be reset whenever any
++ * printer has been seen to make some forward progress.
++ *
++ * Context: Any context if @timeout_ms is 0 or @may_sleep is false. Otherwise
++ * process context.
++ * Return: true if all enabled printers are caught up.
++ */
++bool pr_flush(bool may_sleep, int timeout_ms, bool reset_on_progress)
++{
++ int remaining = timeout_ms;
++ struct console *con;
++ u64 last_diff = 0;
++ u64 printk_seq;
++ u64 diff;
++ u64 seq;
++
++ seq = prb_next_seq(prb);
++
++ for (;;) {
++ diff = 0;
++
++ for_each_console(con) {
++ if (!(con->flags & CON_ENABLED))
++ continue;
++ printk_seq = atomic64_read(&con->printk_seq);
++ if (printk_seq < seq)
++ diff += seq - printk_seq;
++ }
++
++ if (diff != last_diff && reset_on_progress)
++ remaining = timeout_ms;
++
++ if (!diff || remaining == 0)
++ break;
++
++ if (remaining < 0) {
++ pr_msleep(may_sleep, 100);
++ } else if (remaining < 100) {
++ pr_msleep(may_sleep, remaining);
++ remaining = 0;
++ } else {
++ pr_msleep(may_sleep, 100);
++ remaining -= 100;
++ }
++
++ last_diff = diff;
++ }
++
++ return (diff == 0);
++}
++EXPORT_SYMBOL(pr_flush);
diff --git a/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch b/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch
new file mode 100644
index 000000000000..1479af403f58
--- /dev/null
+++ b/patches/0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch
@@ -0,0 +1,43 @@
+From: John Ogness <john.ogness@linutronix.de>
+Date: Mon, 30 Nov 2020 01:42:11 +0106
+Subject: [PATCH 16/16] printk: kmsg_dump,do_mounts wait for printers
+
+Use pr_flush() to give console printers a chance to finish if no
+atomic console is available. This should probably be implemented
+inside panic(), giving panic() an additional @may_sleep argument.
+But that would require evaluating every panic() caller. For now
+just call pr_flush() for kmsg_dump and when failing to mount the
+root filesystem, since these are both common error paths.
+
+Signed-off-by: John Ogness <john.ogness@linutronix.de>
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ init/do_mounts.c | 1 +
+ kernel/printk/printk.c | 6 ++++++
+ 2 files changed, 7 insertions(+)
+
+--- a/init/do_mounts.c
++++ b/init/do_mounts.c
+@@ -457,6 +457,7 @@ void __init mount_block_root(char *name,
+ printk("DEBUG_BLOCK_EXT_DEVT is enabled, you need to specify "
+ "explicit textual name for \"root=\" boot option.\n");
+ #endif
++ pr_flush(true, 1000, true);
+ panic("VFS: Unable to mount root fs on %s", b);
+ }
+ if (!(flags & SB_RDONLY)) {
+--- a/kernel/printk/printk.c
++++ b/kernel/printk/printk.c
+@@ -3105,6 +3105,12 @@ void kmsg_dump(enum kmsg_dump_reason rea
+ sync_mode = true;
+ pr_info("enabled sync mode\n");
+ }
++
++ /*
++ * Give the printing threads time to flush, allowing up to 1
++ * second of no printing forward progress before giving up.
++ */
++ pr_flush(false, 100, true);
+ }
+
+ rcu_read_lock();
diff --git a/patches/localversion.patch b/patches/localversion.patch
index 12bd473a33f5..25e5fadbaae8 100644
--- a/patches/localversion.patch
+++ b/patches/localversion.patch
@@ -10,4 +10,4 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- /dev/null
+++ b/localversion-rt
@@ -0,0 +1 @@
-+-rt12
++-rt13
diff --git a/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch b/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch
index 7d7180d74b41..0b624ecb1c9d 100644
--- a/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch
+++ b/patches/mm-zswap-Use-local-lock-to-protect-per-CPU-data.patch
@@ -23,8 +23,8 @@ Cc: linux-mm@kvack.org
Signed-off-by: Luis Claudio R. Goncalves <lgoncalv@redhat.com>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
---
- mm/zswap.c | 41 ++++++++++++++++++++++++++---------------
- 1 file changed, 26 insertions(+), 15 deletions(-)
+ mm/zswap.c | 43 ++++++++++++++++++++++++++++---------------
+ 1 file changed, 28 insertions(+), 15 deletions(-)
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -36,7 +36,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
#include <linux/types.h>
#include <linux/atomic.h>
#include <linux/frontswap.h>
-@@ -387,27 +388,35 @@ static struct zswap_entry *zswap_entry_f
+@@ -387,27 +388,37 @@ static struct zswap_entry *zswap_entry_f
/*********************************
* per-cpu code
**********************************/
@@ -47,7 +47,9 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+ u8 *dstmem;
+};
+
-+static DEFINE_PER_CPU(struct zswap_comp, zswap_comp);
++static DEFINE_PER_CPU(struct zswap_comp, zswap_comp) = {
++ .lock = INIT_LOCAL_LOCK(lock),
++};
static int zswap_dstmem_prepare(unsigned int cpu)
{
@@ -78,7 +80,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
return 0;
}
-@@ -919,10 +928,11 @@ static int zswap_writeback_entry(struct
+@@ -919,10 +930,11 @@ static int zswap_writeback_entry(struct
dlen = PAGE_SIZE;
src = (u8 *)zhdr + sizeof(struct zswap_header);
dst = kmap_atomic(page);
@@ -92,7 +94,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
kunmap_atomic(dst);
BUG_ON(ret);
BUG_ON(dlen != PAGE_SIZE);
-@@ -1074,12 +1084,12 @@ static int zswap_frontswap_store(unsigne
+@@ -1074,12 +1086,12 @@ static int zswap_frontswap_store(unsigne
}
/* compress */
@@ -108,7 +110,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
if (ret) {
ret = -EINVAL;
goto put_dstmem;
-@@ -1103,7 +1113,7 @@ static int zswap_frontswap_store(unsigne
+@@ -1103,7 +1115,7 @@ static int zswap_frontswap_store(unsigne
memcpy(buf, &zhdr, hlen);
memcpy(buf + hlen, dst, dlen);
zpool_unmap_handle(entry->pool->zpool, handle);
@@ -117,7 +119,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
/* populate entry */
entry->offset = offset;
-@@ -1131,7 +1141,7 @@ static int zswap_frontswap_store(unsigne
+@@ -1131,7 +1143,7 @@ static int zswap_frontswap_store(unsigne
return 0;
put_dstmem:
@@ -126,7 +128,7 @@ Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
zswap_pool_put(entry->pool);
freepage:
zswap_entry_cache_free(entry);
-@@ -1176,9 +1186,10 @@ static int zswap_frontswap_load(unsigned
+@@ -1176,9 +1188,10 @@ static int zswap_frontswap_load(unsigned
if (zpool_evictable(entry->pool->zpool))
src += sizeof(struct zswap_header);
dst = kmap_atomic(page);
diff --git a/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch b/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch
new file mode 100644
index 000000000000..3ef97ac3f0d1
--- /dev/null
+++ b/patches/notifier-Make-atomic_notifiers-use-raw_spinlock.patch
@@ -0,0 +1,123 @@
+From: Valentin Schneider <valentin.schneider@arm.com>
+Date: Sun, 22 Nov 2020 20:19:04 +0000
+Subject: [PATCH] notifier: Make atomic_notifiers use raw_spinlock
+
+Booting a recent PREEMPT_RT kernel (v5.10-rc3-rt7-rebase) on my arm64 Juno
+leads to the idle task blocking on an RT sleeping spinlock down some
+notifier path:
+
+ [ 1.809101] BUG: scheduling while atomic: swapper/5/0/0x00000002
+ [ 1.809116] Modules linked in:
+ [ 1.809123] Preemption disabled at:
+ [ 1.809125] secondary_start_kernel (arch/arm64/kernel/smp.c:227)
+ [ 1.809146] CPU: 5 PID: 0 Comm: swapper/5 Tainted: G W 5.10.0-rc3-rt7 #168
+ [ 1.809153] Hardware name: ARM Juno development board (r0) (DT)
+ [ 1.809158] Call trace:
+ [ 1.809160] dump_backtrace (arch/arm64/kernel/stacktrace.c:100 (discriminator 1))
+ [ 1.809170] show_stack (arch/arm64/kernel/stacktrace.c:198)
+ [ 1.809178] dump_stack (lib/dump_stack.c:122)
+ [ 1.809188] __schedule_bug (kernel/sched/core.c:4886)
+ [ 1.809197] __schedule (./arch/arm64/include/asm/preempt.h:18 kernel/sched/core.c:4913 kernel/sched/core.c:5040)
+ [ 1.809204] preempt_schedule_lock (kernel/sched/core.c:5365 (discriminator 1))
+ [ 1.809210] rt_spin_lock_slowlock_locked (kernel/locking/rtmutex.c:1072)
+ [ 1.809217] rt_spin_lock_slowlock (kernel/locking/rtmutex.c:1110)
+ [ 1.809224] rt_spin_lock (./include/linux/rcupdate.h:647 kernel/locking/rtmutex.c:1139)
+ [ 1.809231] atomic_notifier_call_chain_robust (kernel/notifier.c:71 kernel/notifier.c:118 kernel/notifier.c:186)
+ [ 1.809240] cpu_pm_enter (kernel/cpu_pm.c:39 kernel/cpu_pm.c:93)
+ [ 1.809249] psci_enter_idle_state (drivers/cpuidle/cpuidle-psci.c:52 drivers/cpuidle/cpuidle-psci.c:129)
+ [ 1.809258] cpuidle_enter_state (drivers/cpuidle/cpuidle.c:238)
+ [ 1.809267] cpuidle_enter (drivers/cpuidle/cpuidle.c:353)
+ [ 1.809275] do_idle (kernel/sched/idle.c:132 kernel/sched/idle.c:213 kernel/sched/idle.c:273)
+ [ 1.809282] cpu_startup_entry (kernel/sched/idle.c:368 (discriminator 1))
+ [ 1.809288] secondary_start_kernel (arch/arm64/kernel/smp.c:273)
+
+Two points worth noting:
+
+1) That this is conceptually the same issue as pointed out in:
+ 313c8c16ee62 ("PM / CPU: replace raw_notifier with atomic_notifier")
+2) Only the _robust() variant of atomic_notifier callchains suffer from
+ this
+
+AFAICT only the cpu_pm_notifier_chain really needs to be changed, but
+singling it out would mean introducing a new (truly) non-blocking API. At
+the same time, callers that are fine with any blocking within the call
+chain should use blocking notifiers, so patching up all atomic_notifier's
+doesn't seem *too* crazy to me.
+
+Fixes: 70d932985757 ("notifier: Fix broken error handling pattern")
+Signed-off-by: Valentin Schneider <valentin.schneider@arm.com>
+Reviewed-by: Daniel Bristot de Oliveira <bristot@redhat.com>
+Link: https://lkml.kernel.org/r/20201122201904.30940-1-valentin.schneider@arm.com
+Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
+---
+ include/linux/notifier.h | 6 +++---
+ kernel/notifier.c | 12 ++++++------
+ 2 files changed, 9 insertions(+), 9 deletions(-)
+
+--- a/include/linux/notifier.h
++++ b/include/linux/notifier.h
+@@ -58,7 +58,7 @@ struct notifier_block {
+ };
+
+ struct atomic_notifier_head {
+- spinlock_t lock;
++ raw_spinlock_t lock;
+ struct notifier_block __rcu *head;
+ };
+
+@@ -78,7 +78,7 @@ struct srcu_notifier_head {
+ };
+
+ #define ATOMIC_INIT_NOTIFIER_HEAD(name) do { \
+- spin_lock_init(&(name)->lock); \
++ raw_spin_lock_init(&(name)->lock); \
+ (name)->head = NULL; \
+ } while (0)
+ #define BLOCKING_INIT_NOTIFIER_HEAD(name) do { \
+@@ -95,7 +95,7 @@ extern void srcu_init_notifier_head(stru
+ cleanup_srcu_struct(&(name)->srcu);
+
+ #define ATOMIC_NOTIFIER_INIT(name) { \
+- .lock = __SPIN_LOCK_UNLOCKED(name.lock), \
++ .lock = __RAW_SPIN_LOCK_UNLOCKED(name.lock), \
+ .head = NULL }
+ #define BLOCKING_NOTIFIER_INIT(name) { \
+ .rwsem = __RWSEM_INITIALIZER((name).rwsem), \
+--- a/kernel/notifier.c
++++ b/kernel/notifier.c
+@@ -142,9 +142,9 @@ int atomic_notifier_chain_register(struc
+ unsigned long flags;
+ int ret;
+
+- spin_lock_irqsave(&nh->lock, flags);
++ raw_spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_register(&nh->head, n);
+- spin_unlock_irqrestore(&nh->lock, flags);
++ raw_spin_unlock_irqrestore(&nh->lock, flags);
+ return ret;
+ }
+ EXPORT_SYMBOL_GPL(atomic_notifier_chain_register);
+@@ -164,9 +164,9 @@ int atomic_notifier_chain_unregister(str
+ unsigned long flags;
+ int ret;
+
+- spin_lock_irqsave(&nh->lock, flags);
++ raw_spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_chain_unregister(&nh->head, n);
+- spin_unlock_irqrestore(&nh->lock, flags);
++ raw_spin_unlock_irqrestore(&nh->lock, flags);
+ synchronize_rcu();
+ return ret;
+ }
+@@ -182,9 +182,9 @@ int atomic_notifier_call_chain_robust(st
+ * Musn't use RCU; because then the notifier list can
+ * change between the up and down traversal.
+ */
+- spin_lock_irqsave(&nh->lock, flags);
++ raw_spin_lock_irqsave(&nh->lock, flags);
+ ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v);
+- spin_unlock_irqrestore(&nh->lock, flags);
++ raw_spin_unlock_irqrestore(&nh->lock, flags);
+
+ return ret;
+ }
diff --git a/patches/printk-Tiny-cleanup.patch b/patches/printk-Tiny-cleanup.patch
deleted file mode 100644
index 7408f2a7f869..000000000000
--- a/patches/printk-Tiny-cleanup.patch
+++ /dev/null
@@ -1,145 +0,0 @@
-From: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
-Date: Tue, 20 Oct 2020 18:48:16 +0200
-Subject: [PATCH] printk: Tiny cleanup
-
-- mark functions and variables static which are used only in this file.
-- add printf annotation where appropriate
-- remove static functions without caller
-- add kdb header file for kgdb builds.
-
-Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
----
- kernel/printk/printk.c | 62 +++++++++++++++----------------------------------
- 1 file changed, 19 insertions(+), 43 deletions(-)
-
---- a/kernel/printk/printk.c
-+++ b/kernel/printk/printk.c
-@@ -49,6 +49,7 @@
- #include <linux/sched/clock.h>
- #include <linux/sched/debug.h>
- #include <linux/sched/task_stack.h>
-+#include <linux/kdb.h>
-
- #include <linux/uaccess.h>
- #include <asm/sections.h>
-@@ -339,11 +340,11 @@ enum log_flags {
- };
-
- /* The syslog_lock protects syslog_* variables. */
--DEFINE_RAW_SPINLOCK(syslog_lock);
--#define syslog_lock_irq() raw_spin_lock_irq(&syslog_lock)
--#define syslog_unlock_irq() raw_spin_unlock_irq(&syslog_lock)
--#define syslog_lock_irqsave(flags) raw_spin_lock_irqsave(&syslog_lock, flags)
--#define syslog_unlock_irqrestore(flags) raw_spin_unlock_irqrestore(&syslog_lock, flags)
-+static DEFINE_SPINLOCK(syslog_lock);
-+#define syslog_lock_irq() spin_lock_irq(&syslog_lock)
-+#define syslog_unlock_irq() spin_unlock_irq(&syslog_lock)
-+#define syslog_lock_irqsave(flags) spin_lock_irqsave(&syslog_lock, flags)
-+#define syslog_unlock_irqrestore(flags) spin_unlock_irqrestore(&syslog_lock, flags)
-
- #ifdef CONFIG_PRINTK
- DECLARE_WAIT_QUEUE_HEAD(log_wait);
-@@ -398,7 +399,7 @@ static struct printk_ringbuffer *prb = &
- */
- static bool __printk_percpu_data_ready __read_mostly;
-
--bool printk_percpu_data_ready(void)
-+static bool printk_percpu_data_ready(void)
- {
- return __printk_percpu_data_ready;
- }
-@@ -1862,9 +1863,10 @@ static inline u32 printk_caller_id(void)
- 0x80000000 + raw_smp_processor_id();
- }
-
--int vprintk_store(int facility, int level,
-- const struct dev_printk_info *dev_info,
-- const char *fmt, va_list args)
-+__printf(4, 0)
-+static int vprintk_store(int facility, int level,
-+ const struct dev_printk_info *dev_info,
-+ const char *fmt, va_list args)
- {
- const u32 caller_id = printk_caller_id();
- struct prb_reserved_entry e;
-@@ -2008,13 +2010,14 @@ asmlinkage int vprintk_emit(int facility
- }
- EXPORT_SYMBOL(vprintk_emit);
-
--int vprintk_default(const char *fmt, va_list args)
-+ __printf(1, 0)
-+static int vprintk_default(const char *fmt, va_list args)
- {
- return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
- }
--EXPORT_SYMBOL_GPL(vprintk_default);
-
--__printf(1, 0) int vprintk_func(const char *fmt, va_list args)
-+__printf(1, 0)
-+static int vprintk_func(const char *fmt, va_list args)
- {
- #ifdef CONFIG_KGDB_KDB
- /* Allow to pass printk() to kdb but avoid a recursion. */
-@@ -2328,34 +2331,6 @@ int is_console_locked(void)
- }
- EXPORT_SYMBOL(is_console_locked);
-
--/*
-- * Check if we have any console that is capable of printing while cpu is
-- * booting or shutting down. Requires console_sem.
-- */
--static int have_callable_console(void)
--{
-- struct console *con;
--
-- for_each_console(con)
-- if ((con->flags & CON_ENABLED) &&
-- (con->flags & CON_ANYTIME))
-- return 1;
--
-- return 0;
--}
--
--/*
-- * Can we actually use the console at this time on this cpu?
-- *
-- * Console drivers may assume that per-cpu resources have been allocated. So
-- * unless they're explicitly marked as being able to cope (CON_ANYTIME) don't
-- * call them until this CPU is officially up.
-- */
--static inline int can_use_console(void)
--{
-- return cpu_online(raw_smp_processor_id()) || have_callable_console();
--}
--
- /**
- * console_unlock - unlock the console system
- *
-@@ -3033,7 +3008,8 @@ void wake_up_klogd(void)
- preempt_enable();
- }
-
--int vprintk_deferred(const char *fmt, va_list args)
-+__printf(1, 0)
-+static int vprintk_deferred(const char *fmt, va_list args)
- {
- return vprintk_emit(0, LOGLEVEL_DEFAULT, NULL, fmt, args);
- }
-@@ -3470,7 +3446,7 @@ static bool __prb_trylock(struct prb_cpu
- *
- * It is safe to call this function from any context and state.
- */
--void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store)
-+static void prb_lock(struct prb_cpulock *cpu_lock, unsigned int *cpu_store)
- {
- for (;;) {
- if (__prb_trylock(cpu_lock, cpu_store))
-@@ -3488,7 +3464,7 @@ void prb_lock(struct prb_cpulock *cpu_lo
- *
- * It is safe to call this function from any context and state.
- */
--void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store)
-+static void prb_unlock(struct prb_cpulock *cpu_lock, unsigned int cpu_store)
- {
- unsigned long *flags;
- unsigned int cpu;
diff --git a/patches/series b/patches/series
index e65af8c36ba9..b2b8ba0b94bb 100644
--- a/patches/series
+++ b/patches/series
@@ -106,26 +106,30 @@ timers-Don-t-block-on-expiry_lock-for-TIMER_IRQSAFE.patch
0001-kthread-Move-prio-affinite-change-into-the-newly-cre.patch
0002-genirq-Move-prio-assignment-into-the-newly-created-t.patch
+# 20201122201904.30940-1-valentin.schneider@arm.com
+notifier-Make-atomic_notifiers-use-raw_spinlock.patch
+
############################################################
# Ready for posting
############################################################
# John's printk series.
0001-printk-refactor-kmsg_dump_get_buffer.patch
-0002-printk-use-buffer-pools-for-sprint-buffers.patch
+0002-printk-inline-log_output-log_store-in-vprintk_store.patch
0003-printk-change-clear_seq-to-atomic64_t.patch
0004-printk-remove-logbuf_lock-add-syslog_lock.patch
0005-printk-remove-safe-buffers.patch
0006-console-add-write_atomic-interface.patch
0007-serial-8250-implement-write_atomic.patch
-0008-printk-inline-log_output-log_store-in-vprintk_store.patch
-0009-printk-relocate-printk_delay-and-vprintk_default.patch
-0010-printk-combine-boot_delay_msec-into-printk_delay.patch
+0008-printk-relocate-printk_delay-and-vprintk_default.patch
+0009-printk-combine-boot_delay_msec-into-printk_delay.patch
+0010-printk-change-console_seq-to-atomic64_t.patch
0011-printk-introduce-kernel-sync-mode.patch
0012-printk-move-console-printing-to-kthreads.patch
0013-printk-remove-deferred-printing.patch
0014-printk-add-console-handover.patch
-printk-Tiny-cleanup.patch
+0015-printk-add-pr_flush.patch
+0016-printk-kmsg_dump-do_mounts-wait-for-printers.patch
############################################################
# Needs to address review feedback
diff --git a/patches/x86-kvm-require-const-tsc-for-rt.patch b/patches/x86-kvm-require-const-tsc-for-rt.patch
index 0f7b158d2a09..c7cd925d4339 100644
--- a/patches/x86-kvm-require-const-tsc-for-rt.patch
+++ b/patches/x86-kvm-require-const-tsc-for-rt.patch
@@ -14,7 +14,7 @@ Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
-@@ -7870,6 +7870,14 @@ int kvm_arch_init(void *opaque)
+@@ -7872,6 +7872,14 @@ int kvm_arch_init(void *opaque)
goto out;
}