Messages in this thread Patch in this message | | | From | John Ogness <> | Subject | [PATCH printk v2 6/7] printk: Use an output buffer descriptor struct for emit | Date | Thu, 24 Nov 2022 00:19:59 +0106 |
| |
From: Thomas Gleixner <tglx@linutronix.de>
To prepare for a new console infrastructure that is independent of the console BKL, wrap the output mode into a descriptor struct so the new infrastructure can share the emit code that dumps the ringbuffer record into the output text buffers.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: John Ogness <john.ogness@linutronix.de> --- include/linux/console.h | 15 ++++++ kernel/printk/printk.c | 107 ++++++++++++++++++++++++++++------------ 2 files changed, 90 insertions(+), 32 deletions(-)
diff --git a/include/linux/console.h b/include/linux/console.h index 641c1ca7fb67..32614011a950 100644 --- a/include/linux/console.h +++ b/include/linux/console.h @@ -188,6 +188,21 @@ struct console_buffers { char text[CONSOLE_LOG_MAX]; }; +/** + * struct console_message - console output buffer descriptor + * @cbufs: Pointer to console buffers storing the record text + * @outbuf: Pointer to the text buffer to be used for writing out + * to the device + * @outbuf_len: Length of text at @outbuf + * @is_extmsg: True if this is an extended format message + */ +struct console_message { + struct console_buffers *cbufs; + char *outbuf; + unsigned int outbuf_len; + bool is_extmsg; +}; + /** * struct console - The console descriptor structure * @name: The name of the console driver diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 750559171e30..dd1d8599ce5a 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2741,11 +2741,76 @@ static void __console_unlock(void) up_console_sem(); } +/** + * console_get_next_message - Fill the output buffer with the next record + * @con: The console to print on + * @cmsg: Pointer to the output buffer descriptor + * + * Return: False if there is no pending record in the ringbuffer. + * True if there is a pending record in the ringbuffer. + * + * When the return value is true, then the caller must check + * @cmsg->outbuf. If not NULL it points to the first character to write + * to the device and @cmsg->outbuf_len contains the length of the message. + * If it is NULL then the record will be skipped. + */ +static bool console_get_next_message(struct console *con, struct console_message *cmsg) +{ + struct console_buffers *cbufs = cmsg->cbufs; + static int panic_console_dropped; + struct printk_info info; + struct printk_record r; + size_t write_text_size; + char *write_text; + size_t len; + + cmsg->outbuf = NULL; + cmsg->outbuf_len = 0; + + prb_rec_init_rd(&r, &info, &cbufs->text[0], sizeof(cbufs->text)); + + if (!prb_read_valid(prb, con->seq, &r)) + return false; + + if (con->seq != r.info->seq) { + con->dropped += r.info->seq - con->seq; + con->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"); + } + } + + /* + * Skip record that has level above the console loglevel. + * Return true so the caller knows a record exists and + * leave cmsg->outbuf NULL so the caller knows the record + * is being skipped. + */ + if (suppress_message_printing(r.info->level)) + return true; + + if (cmsg->is_extmsg) { + write_text = &cbufs->ext_text[0]; + write_text_size = sizeof(cbufs->ext_text); + len = info_print_ext_header(write_text, write_text_size, r.info); + len += msg_print_ext_body(write_text + len, write_text_size - len, + &r.text_buf[0], r.info->text_len, &r.info->dev_info); + } else { + write_text = &cbufs->text[0]; + len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); + } + + cmsg->outbuf = write_text; + cmsg->outbuf_len = len; + return true; +} + /* * Print one record for the given console. The record printed is whatever * record is the next available record for the given console. * - * @cbufs is the console buffers used to string-print the formatted messages. + * @cbufs is the console buffers to use for string-printing the message. * * @cookie is the cookie from entering the SRCU read-side critical section. * @@ -2761,52 +2826,30 @@ static void __console_unlock(void) static bool console_emit_next_record(struct console *con, struct console_buffers *cbufs, int cookie, bool *handover) { - static int panic_console_dropped; - struct printk_info info; - struct printk_record r; - size_t write_text_size; + struct console_message cmsg = { + .cbufs = cbufs, + .is_extmsg = console_srcu_read_flags(con) & CON_EXTENDED, + }; unsigned long flags; char *dropped_text; - char *write_text; - size_t len; - - prb_rec_init_rd(&r, &info, &cbufs->text[0], sizeof(cbufs->text)); *handover = false; - if (!prb_read_valid(prb, con->seq, &r)) + if (!console_get_next_message(con, &cmsg)) return false; - if (con->seq != r.info->seq) { - con->dropped += r.info->seq - con->seq; - con->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"); - } - } - - /* Skip record that has level above the console loglevel. */ - if (suppress_message_printing(r.info->level)) { + if (!cmsg.outbuf) { + /* Skipping this record. */ con->seq++; goto skip; } - if (console_srcu_read_flags(con) & CON_EXTENDED) { + if (cmsg.is_extmsg) { /* Extended consoles do not print "dropped messages". */ dropped_text = NULL; - - write_text = &cbufs->ext_text[0]; - write_text_size = sizeof(cbufs->ext_text); - len = info_print_ext_header(write_text, write_text_size, r.info); - len += msg_print_ext_body(write_text + len, write_text_size - len, - &r.text_buf[0], r.info->text_len, &r.info->dev_info); } else { /* @ext_text is unused. Use it for "dropped messages". */ dropped_text = &cbufs->ext_text[0]; - - write_text = &cbufs->text[0]; - len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); } /* @@ -2823,7 +2866,7 @@ static bool console_emit_next_record(struct console *con, struct console_buffers console_lock_spinning_enable(); stop_critical_timings(); /* don't trace print latency */ - call_console_driver(con, write_text, len, dropped_text); + call_console_driver(con, cmsg.outbuf, cmsg.outbuf_len, dropped_text); start_critical_timings(); con->seq++; -- 2.30.2
| |