From patchwork Wed Dec 21 20:27:03 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: John Ogness X-Patchwork-Id: 35511 Return-Path: Delivered-To: ouuuleilei@gmail.com Received: by 2002:adf:e747:0:0:0:0:0 with SMTP id c7csp3730500wrn; Wed, 21 Dec 2022 12:34:58 -0800 (PST) X-Google-Smtp-Source: AMrXdXtFnRMuuilh0/cM9+qwrbQM4G/FBpeblj2ol0bbdKkR+APQnuM8psR01VLbSgLtVpkLBI24 X-Received: by 2002:a17:90b:2747:b0:21a:1b9b:139e with SMTP id qi7-20020a17090b274700b0021a1b9b139emr3625469pjb.8.1671654898521; Wed, 21 Dec 2022 12:34:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1671654898; cv=none; d=google.com; s=arc-20160816; b=HNDjRKkCsvaJtKAOr9dhAKkt34yWP28T5Dy5mfP+ZEAHeTyAJ6U1KDuPP0y9flUFIq sfx5j9Kt+OQb0/1pbz1MM0N5h6GnWK4rEvQAvLNx2u4cPJX++KL6ddGgCna2dcRK3FaR iX/5HmSjn7I/JeVWpwtIqJijJ4qba6EP1WyiBiqboRJp6IfhfwXl5t3VADzUBRvwPVAx xkCctQrH/8w/z4ets0yfr7TbPBqcc9JVZ8LFknr39Yd8gGlpjlNvTN9kCPRDyt2xJxLm W5FAQbabvoCLJhdAzh/Ttvk0o1pIsvgallsyK76RSxG+Wd1ksko6w5ADHEXmM2yBEFsd HAMA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:dkim-signature :dkim-signature:from; bh=JpYeAsldPGyAqY4hxNmOiSJNyyD2urN7p0Yg2vrAx2c=; b=ekGL7D3gPf2VsB+aR+vqwDtImZijoUqWPJ029l8nmyq8UoDKW6Ux3voUtqpcnqnSMI lFWNXfectlLmmN2yso58Vr0sNA919ZrMvGOXEKZwmkG2ZshPxaor9SVDRVq8YJcBSbaM 8MofYy8o8aW7VKmA8V6N7PU+sEAoOkXf6HyNfHet7ZwR1u0lJADCoMDWxHrzrxaja2sr Vd7zFIYIzwvt6rvUM2XjWMuMCKn162xiEpmWgSkghvo/IJNoqnTM0Ho4V7k7mQWU77Lo 7wOSM4LyQYAKOveBox+WQaL0AgRd98GYNHoO44MtiGRnVhcPezMsJR60xW1/d2dn2vS6 HKPg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=xvp7nfVs; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=7PXG36Ti; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from out1.vger.email (out1.vger.email. [2620:137:e000::1:20]) by mx.google.com with ESMTP id lk15-20020a17090b33cf00b00218792fa2b3si2755731pjb.160.2022.12.21.12.34.45; Wed, 21 Dec 2022 12:34:58 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) client-ip=2620:137:e000::1:20; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=xvp7nfVs; dkim=neutral (no key) header.i=@linutronix.de header.s=2020e header.b=7PXG36Ti; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 2620:137:e000::1:20 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S234924AbiLUU2L (ORCPT + 99 others); Wed, 21 Dec 2022 15:28:11 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:58790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S234866AbiLUU1t (ORCPT ); Wed, 21 Dec 2022 15:27:49 -0500 Received: from galois.linutronix.de (Galois.linutronix.de [IPv6:2a0a:51c0:0:12e:550::1]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 8C6AF24F2A for ; Wed, 21 Dec 2022 12:27:47 -0800 (PST) From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1671654457; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JpYeAsldPGyAqY4hxNmOiSJNyyD2urN7p0Yg2vrAx2c=; b=xvp7nfVsG/2UWcrRmq3FP1izPmpSS3nfNf7XsM8DFLHTcMaQKxlclgn3vj4MF63Y2fcwRB lBDcqnwdJZBDF59ZDVhf+2HYn3JfWiy0lNmDgPnE9ZVyXpvw/IlL/75BOhmoEMNGWueya0 Rvw5/VFvniQVej7shM7uckephlcKPYeOv9gaMPZzV9++d9/QXX9li5MbSP5eghwdlYkGfo +zEXfni+jHD8JSYOmDYZUqsEN+D0/COC1ulAeKTmA8RfpmkaNIQo/Rlj80v4UMnhtMNE1k aES5ugP0q1uaf4M5xESKztPeACzNwAh7M/4Vynjf3UweI/T4nVWTYQztxOlQpQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1671654457; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JpYeAsldPGyAqY4hxNmOiSJNyyD2urN7p0Yg2vrAx2c=; b=7PXG36TiyDcN4uGOntSv9FbBRnVA5iWktYsRZnRDlIT9BhKnjJqTQeMz8TLJG5LZ37LEEA 992Ssau2EPqDRdCA== To: Petr Mladek Cc: Sergey Senozhatsky , Steven Rostedt , Thomas Gleixner , linux-kernel@vger.kernel.org Subject: [PATCH printk v3 5/6] printk: introduce console_get_next_message() and console_message Date: Wed, 21 Dec 2022 21:33:03 +0106 Message-Id: <20221221202704.857925-6-john.ogness@linutronix.de> In-Reply-To: <20221221202704.857925-1-john.ogness@linutronix.de> References: <20221221202704.857925-1-john.ogness@linutronix.de> MIME-Version: 1.0 X-Spam-Status: No, score=-3.9 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,INVALID_DATE_TZ_ABSURD, RCVD_IN_DNSWL_MED,SPF_HELO_NONE,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?= X-GMAIL-THRID: =?utf-8?q?1752857206667153215?= X-GMAIL-MSGID: =?utf-8?q?1752857206667153215?= Code for performing the console output is intermixed with code that is formatting the output for that console. Introduce a new helper function console_get_next_message() to handle the reading and formatting of the console text. The helper does not require any locking so that in the future it can be used for other console printing contexts as well. This also introduces a new struct console_message to wrap the struct console_buffers adding meta-data about its contents. This allows users of console_get_next_message() to receive all relevant information about the message that was read and formatted. The reason a wrapper struct is introduced instead of adding the meta-data to struct console_buffers is because the upcoming atomic consoles will need per-cpu and per-context console_buffers. It would not make sense to make the meta-data also per-cpu and per-context as that data can be easily stored on the stack of the console printing context. Signed-off-by: John Ogness Reviewed-by: Petr Mladek --- kernel/printk/internal.h | 16 ++++++ kernel/printk/printk.c | 118 +++++++++++++++++++++++++++------------ 2 files changed, 97 insertions(+), 37 deletions(-) diff --git a/kernel/printk/internal.h b/kernel/printk/internal.h index f5ebbd392fee..4f2eb8c470bc 100644 --- a/kernel/printk/internal.h +++ b/kernel/printk/internal.h @@ -91,3 +91,19 @@ struct console_buffers { char outbuf[CONSOLE_EXT_LOG_MAX]; char scratchbuf[LOG_LINE_MAX]; }; + +/** + * console_message - Container for a prepared console message. + * @cbufs: Console buffers used to prepare the message. + * @outbuf_len: The length of prepared text in @cbufs->outbuf to output. This + * does not count the terminator. A value of 0 means there is + * nothing to output and this record should be skipped. + * @outbuf_seq: The sequence number of the record used for @cbufs->outbuf. + * @dropped: The number of dropped records from reading @outbuf_seq. + */ +struct console_message { + struct console_buffers *cbufs; + unsigned int outbuf_len; + u64 outbuf_seq; + unsigned long dropped; +}; diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 2e5e2eda1fa1..7cac636600f8 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -2725,34 +2725,34 @@ static void __console_unlock(void) } /* - * Print one record for the given console. The record printed is whatever - * record is the next available record for the given console. + * Read and format the specified record (or a later record if the specified + * record is not available). * - * @handover will be set to true if a printk waiter has taken over the - * console_lock, in which case the caller is no longer holding both the - * console_lock and the SRCU read lock. Otherwise it is set to false. + * @cmsg will contain the formatted result. @cmsg->cbufs must point to a + * struct console_buffers. * - * @cookie is the cookie from the SRCU read lock. + * @seq is the record to read and format. If it is not available, the next + * valid record is read. * - * Returns false if the given console has no next record to print, otherwise - * true. + * @is_extended specifies the message should be formatted for extended + * console output. * - * Requires the console_lock and the SRCU read lock. + * Returns false if no record is available. Otherwise true and all fields + * of @cmsg are valid. (See the documentation of struct console_message + * for information about the @cmsg fields.) */ -static bool console_emit_next_record(struct console *con, bool *handover, int cookie) -{ - bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; - static char dropped_text[DROPPED_TEXT_MAX]; - static struct console_buffers cbufs; - const size_t scratchbuf_sz = sizeof(cbufs.scratchbuf); - const size_t outbuf_sz = sizeof(cbufs.outbuf); - char *scratchbuf = &cbufs.scratchbuf[0]; - char *outbuf = &cbufs.outbuf[0]; +static bool console_get_next_message(struct console_message *cmsg, u64 seq, + bool is_extended) +{ + struct console_buffers *cbufs = cmsg->cbufs; + const size_t scratchbuf_sz = sizeof(cbufs->scratchbuf); + const size_t outbuf_sz = sizeof(cbufs->outbuf); + char *scratchbuf = &cbufs->scratchbuf[0]; + char *outbuf = &cbufs->outbuf[0]; static int panic_console_dropped; struct printk_info info; struct printk_record r; - unsigned long flags; - size_t len; + size_t len = 0; /* * Formatting extended messages requires a separate buffer, so use the @@ -2766,33 +2766,77 @@ static bool console_emit_next_record(struct console *con, bool *handover, int co else prb_rec_init_rd(&r, &info, outbuf, outbuf_sz); - *handover = false; - - if (!prb_read_valid(prb, con->seq, &r)) + if (!prb_read_valid(prb, 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"); - } + cmsg->outbuf_seq = r.info->seq; + cmsg->dropped = r.info->seq - seq; + + /* + * Check for dropped messages in panic here so that printk + * suppression can occur as early as possible if necessary. + */ + if (cmsg->dropped && + 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)) { - con->seq++; - goto skip; - } + if (suppress_message_printing(r.info->level)) + goto out; if (is_extended) { len = info_print_ext_header(outbuf, outbuf_sz, r.info); len += msg_print_ext_body(outbuf + len, outbuf_sz - len, - &r.text_buf[0], r.info->text_len, &r.info->dev_info); + r.text_buf, r.info->text_len, &r.info->dev_info); } else { len = record_print_text(&r, console_msg_format & MSG_FORMAT_SYSLOG, printk_time); } +out: + 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. + * + * @handover will be set to true if a printk waiter has taken over the + * console_lock, in which case the caller is no longer holding both the + * console_lock and the SRCU read lock. Otherwise it is set to false. + * + * @cookie is the cookie from the SRCU read lock. + * + * Returns false if the given console has no next record to print, otherwise + * true. + * + * Requires the console_lock and the SRCU read lock. + */ +static bool console_emit_next_record(struct console *con, bool *handover, int cookie) +{ + bool is_extended = console_srcu_read_flags(con) & CON_EXTENDED; + static char dropped_text[DROPPED_TEXT_MAX]; + static struct console_buffers cbufs; + static struct console_message cmsg = { + .cbufs = &cbufs, + }; + char *outbuf = &cbufs.outbuf[0]; + unsigned long flags; + + *handover = false; + + if (!console_get_next_message(&cmsg, con->seq, is_extended)) + return false; + + con->dropped += cmsg.dropped; + + /* Skip messages of formatted length 0. */ + if (cmsg.outbuf_len == 0) { + con->seq = cmsg.outbuf_seq + 1; + goto skip; + } /* * While actively printing out messages, if another printk() @@ -2808,11 +2852,11 @@ static bool console_emit_next_record(struct console *con, bool *handover, int co console_lock_spinning_enable(); stop_critical_timings(); /* don't trace print latency */ - call_console_driver(con, outbuf, len, + call_console_driver(con, outbuf, cmsg.outbuf_len, is_extended ? NULL : dropped_text); start_critical_timings(); - con->seq++; + con->seq = cmsg.outbuf_seq + 1; *handover = console_lock_spinning_disable_and_check(cookie); printk_safe_exit_irqrestore(flags);