[patch RFC 24/29] printk: Put seq and dropped into cons_text_desc

From: Thomas Gleixner
Date: Sat Sep 10 2022 - 18:29:58 EST


Non-BKL consoles have atomic sequence tracking which is not
compatible with the legacy consoles.

Put sequence and dropped message count into struct cons_text_desc, let
cons_fill_outbuf() operate on the seq/dropped fields and let the call sites
handle the update to the corresponding fields in struct console.

This allows sharing cons_fill_outbuf() between the two worlds. For the
legacy consoles this is not more or less racy than the existing code.

Co-Developed-by: John Ogness <jogness@xxxxxxxxxxxxx>
Signed-off-by: John Ogness <jogness@xxxxxxxxxxxxx>
Signed-off-by: Thomas Gleixner <tglx@xxxxxxxxxxxxx>
---
include/linux/console.h | 2 ++
kernel/printk/printk.c | 25 ++++++++++++++-----------
2 files changed, 16 insertions(+), 11 deletions(-)

--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -232,6 +232,7 @@ struct cons_text_buf {
* @txtbuf: Pointer to buffer for storing the text
* @outbuf: Pointer to the position in @buffer for
* writing it out to the device
+ * @seq: The sequence requested
* @dropped: The dropped count
* @len: Message length
* @extmsg: Select extended format printing
@@ -239,6 +240,7 @@ struct cons_text_buf {
struct cons_outbuf_desc {
struct cons_text_buf *txtbuf;
char *outbuf;
+ u64 seq;
unsigned long dropped;
unsigned int len;
bool extmsg;
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2740,7 +2740,7 @@ static void cons_print_dropped(struct co
* If it is NULL then records have been dropped or skipped and con->seq
* has been forwarded so the caller can try to print the next record.
*/
-static bool cons_fill_outbuf(struct console *con, struct cons_outbuf_desc *desc)
+static bool cons_fill_outbuf(struct cons_outbuf_desc *desc)
{
static int panic_console_dropped;

@@ -2755,12 +2755,12 @@ static bool cons_fill_outbuf(struct cons

prb_rec_init_rd(&r, &info, txtbuf->text, CONSOLE_LOG_MAX);

- if (!prb_read_valid(prb, con->seq, &r))
+ if (!prb_read_valid(prb, desc->seq, &r))
return false;

- if (con->seq != r.info->seq) {
- con->dropped += r.info->seq - con->seq;
- con->seq = r.info->seq;
+ if (desc->seq != r.info->seq) {
+ desc->dropped += r.info->seq - desc->seq;
+ desc->seq = r.info->seq;
if (panic_in_progress() && panic_console_dropped++ > 10) {
suppress_panic_printk = 1;
pr_warn_once("Too many dropped messages. Suppress messages on non-panic CPUs to prevent livelock.\n");
@@ -2769,7 +2769,7 @@ static bool cons_fill_outbuf(struct cons

/* Skip record that has level above the console loglevel. */
if (suppress_message_printing(r.info->level)) {
- con->seq++;
+ desc->seq++;
return true;
}

@@ -2789,9 +2789,7 @@ static bool cons_fill_outbuf(struct cons

desc->len = len;
desc->outbuf = txtbuf->text;
- desc->dropped = con->dropped;
cons_print_dropped(desc);
- con->dropped = desc->dropped;
}

return true;
@@ -2820,16 +2818,21 @@ static bool console_emit_next_record(str
bool *handover, bool extmsg)
{
struct cons_outbuf_desc desc = {
- .txtbuf = txtbuf,
- .extmsg = extmsg,
+ .txtbuf = txtbuf,
+ .extmsg = extmsg,
+ .seq = con->seq,
+ .dropped = con->dropped,
};
unsigned long flags;

*handover = false;

- if (!cons_fill_outbuf(con, &desc))
+ if (!cons_fill_outbuf(&desc))
return false;

+ con->seq = desc.seq;
+ con->dropped = desc.dropped;
+
if (!desc.outbuf)
goto skip;