lkml.org 
[lkml]   [2022]   [Nov]   [23]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH printk v2 6/7] printk: Use an output buffer descriptor struct for emit
    Date
    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
    \
     
     \ /
      Last update: 2022-11-24 00:15    [W:3.852 / U:0.104 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site