diff options
author | John Ogness <john.ogness@linutronix.de> | 2024-02-07 14:46:59 +0106 |
---|---|---|
committer | Sasha Levin <sashal@kernel.org> | 2024-03-26 18:18:10 -0400 |
commit | 3cabf67787c517387b193ad2bf667ebb81170524 (patch) | |
tree | f0897186e403d2030e54e11b1cba9307a3944eb3 | |
parent | e2c9100ae6adbbe03c16e74d78d7ebc74a3b731f (diff) | |
download | linux-stable-3cabf67787c517387b193ad2bf667ebb81170524.tar.gz linux-stable-3cabf67787c517387b193ad2bf667ebb81170524.tar.bz2 linux-stable-3cabf67787c517387b193ad2bf667ebb81170524.zip |
printk: ringbuffer: Skip non-finalized records in panic
[ Upstream commit b1c4c67a5e90db8fbdb5b5504fe16e17b564cca8 ]
Normally a reader will stop once reaching a non-finalized
record. However, when a panic happens, writers from other CPUs
(or an interrupted context on the panic CPU) may have been
writing a record and were unable to finalize it. The panic CPU
will reserve/commit/finalize its panic records, but these will
be located after the non-finalized records. This results in
panic() not flushing the panic messages.
Extend _prb_read_valid() to skip over non-finalized records if
on the panic CPU.
Fixes: 896fbe20b4e2 ("printk: use the lockless ringbuffer")
Signed-off-by: John Ogness <john.ogness@linutronix.de>
Reviewed-by: Petr Mladek <pmladek@suse.com>
Link: https://lore.kernel.org/r/20240207134103.1357162-11-john.ogness@linutronix.de
Signed-off-by: Petr Mladek <pmladek@suse.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
-rw-r--r-- | kernel/printk/printk_ringbuffer.c | 28 |
1 files changed, 26 insertions, 2 deletions
diff --git a/kernel/printk/printk_ringbuffer.c b/kernel/printk/printk_ringbuffer.c index 97ec25d22797..3d98232902cf 100644 --- a/kernel/printk/printk_ringbuffer.c +++ b/kernel/printk/printk_ringbuffer.c @@ -2087,6 +2087,10 @@ try_again: * * On failure @seq is updated to a record that is not yet available to the * reader, but it will be the next record available to the reader. + * + * Note: When the current CPU is in panic, this function will skip over any + * non-existent/non-finalized records in order to allow the panic CPU + * to print any and all records that have been finalized. */ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, struct printk_record *r, unsigned int *line_count) @@ -2109,8 +2113,28 @@ static bool _prb_read_valid(struct printk_ringbuffer *rb, u64 *seq, (*seq)++; } else { - /* Non-existent/non-finalized record. Must stop. */ - return false; + /* + * Non-existent/non-finalized record. Must stop. + * + * For panic situations it cannot be expected that + * non-finalized records will become finalized. But + * there may be other finalized records beyond that + * need to be printed for a panic situation. If this + * is the panic CPU, skip this + * non-existent/non-finalized record unless it is + * at or beyond the head, in which case it is not + * possible to continue. + * + * Note that new messages printed on panic CPU are + * finalized when we are here. The only exception + * might be the last message without trailing newline. + * But it would have the sequence number returned + * by "prb_next_reserve_seq() - 1". + */ + if (this_cpu_in_panic() && ((*seq + 1) < prb_next_reserve_seq(rb))) + (*seq)++; + else + return false; } } |