Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp826778pxa; Wed, 19 Aug 2020 16:28:04 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxR7dXAVMzvC6yNJ85ug99EEdjATwQat2ZzCP0SkgiuX9Z/PdNWzThRoukv3R1DzIuMLu6O X-Received: by 2002:a17:907:7251:: with SMTP id ds17mr628227ejc.289.1597879684315; Wed, 19 Aug 2020 16:28:04 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597879684; cv=none; d=google.com; s=arc-20160816; b=b7xjJIzV2DpCz6RJ1HojiVlcOKfuM9AiPmtEpZej6SvZtwZOUNUZ/HtsfLXlLGB68b WUeJoTWPzYRFLfJM5XeEgVKL2mFoFiarc356L7X/FmIZwHUBIoW8WrctFjwVXUwnq/c7 LHtxelZfbemnqHWzFdKUuvkOYtdKkFrl0jRM+t01aK/lE/aALciv2rlQCE6NS8e0L71V vDK/rozg50fmkMXWWhQilpFpDrJU06dOo2F9lYGM/QW1DEHYDK47F3Fh57jw+NEH7/Lk ce9bW7dshmrOKS9Q27WaRSqO5kK2ZllyN6vztq5bxMTpXy72rAOc/kbGZonF4oo3I9d2 6Prg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:dkim-signature :dkim-signature:from; bh=eRBjhZhhrhF0UYQCJzJiLHsoinXyh5/zkxgKSxesxYI=; b=ULKXjlfgxWo5sm5onhUWH9W7V3I4QCcHLnudjhPizx0Xmyt2A5JxK4Fasq1Q8aiRRr mcuHjk5ah9lFCga6AD3HyzbDlJtqLRubTGQqCPfCmJGHvh9xZPra72mCx3moPRSLvmtT Gh1r+7vcbJ3+pm8OGJJDk+51M6LbPf1opCRN/iY0AG7kefUnbmJCqFmbBgf+LnIRmOYP U3eaN3EC4GSMQro0HEIAS3oV4c7mEawkL7rw3fB7iMMZF2NjwBur2ESn7GCB0FbvYfXR nqGhSIMJRKgth1C87PTBgLnsNZV0kj1UjDxkOOBVZ8m4QlzpEHmvq8ckqy3uPlr0VIBp 1L1A== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=FVQtiUgb; dkim=neutral (no key) header.i=@vger.kernel.org; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id d10si290230edu.284.2020.08.19.16.27.24; Wed, 19 Aug 2020 16:28:04 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=FVQtiUgb; dkim=neutral (no key) header.i=@vger.kernel.org; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 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 S1727885AbgHSX0i (ORCPT + 99 others); Wed, 19 Aug 2020 19:26:38 -0400 Received: from Galois.linutronix.de ([193.142.43.55]:42892 "EHLO galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726466AbgHSX0f (ORCPT ); Wed, 19 Aug 2020 19:26:35 -0400 From: John Ogness DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1597879593; 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=eRBjhZhhrhF0UYQCJzJiLHsoinXyh5/zkxgKSxesxYI=; b=FVQtiUgbmgNIeF5Y88dn7FVed06p2FoDFa98u2Gz7TrEcdvq5oRAxvKVA+Rm7uLLP6HPNa 4ewn1RTEF8u4P9Pv9LVU/BDwPhKj999I65a4yrDnPpFLkoUR+SAZVvwODpxB8j7nGqXUwp SXK07tm+b+jUGQxg9DcJvvlAlM9NNrdpfYXp0O/gkPhBrouWgwkWoTmYm3ch3Hlsv9+a+q /RrPQ5+0eT0D4TzMD5sOHdBBcTaWmDZaHO5qs30acveT6qlrfA0ipCZiu7rVzgd0HPVDDy Tpv9rYl6axSDwMdYP2fxs64bRakePrieRtH3se6+7WYIBXoh2mzHkrVwAtS8Iw== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1597879593; 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=eRBjhZhhrhF0UYQCJzJiLHsoinXyh5/zkxgKSxesxYI=; b=YSlmzFZYLthA5TkrkAuDlKTzvkzqYsPUYyDpmBt/2ISELE8Giv4qlcFnQ3GoGB1SysvtFz /s/OvT6G2JhQs4Dw== To: Linus Torvalds Cc: Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Greg Kroah-Hartman , Thomas Gleixner , Sergey Senozhatsky , linux-kernel@vger.kernel.org Subject: [RFC PATCH 1/5] printk: implement pr_cont_t Date: Thu, 20 Aug 2020 01:32:28 +0206 Message-Id: <20200819232632.13418-2-john.ogness@linutronix.de> In-Reply-To: <20200819232632.13418-1-john.ogness@linutronix.de> References: <20200819232632.13418-1-john.ogness@linutronix.de> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Implement a new buffering mechanism for pr_cont messages. Old mechanism syntax: printk(KERN_INFO "text"); printk(KERN_CONT " continued"); printk(KERN_CONT "\n"); New mechanism syntax: pr_cont_t c; pr_cont_begin(&c, KERN_INFO "text"); pr_cont_append(&c, " continued"); pr_cont_end(&c); Signed-off-by: John Ogness --- include/linux/printk.h | 19 ++++++ kernel/printk/printk.c | 137 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 156 insertions(+) diff --git a/include/linux/printk.h b/include/linux/printk.h index 34c1a7be3e01..4d9ce18e4afa 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -380,6 +380,25 @@ extern int kptr_restrict; #define pr_cont(fmt, ...) \ printk(KERN_CONT fmt, ##__VA_ARGS__) +/* opaque handle for continuous printk messages */ +typedef struct { + u8 index; + u8 loglevel; + u16 text_len; +} pr_cont_t; + +/* initialize handle, provide loglevel and initial message text */ +int pr_cont_begin(pr_cont_t *c, const char *fmt, ...); + +/* append message text */ +int pr_cont_append(pr_cont_t *c, const char *fmt, ...); + +/* flush message to kernel buffer */ +void pr_cont_flush(pr_cont_t *c); + +/* flush message to kernel buffer, cleanup handle */ +void pr_cont_end(pr_cont_t *c); + /** * pr_devel - Print a debug-level message conditionally * @fmt: format string diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index ad8d1dfe5fbe..10113e7ea350 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -3495,3 +3495,140 @@ void kmsg_dump_rewind(struct kmsg_dumper *dumper) EXPORT_SYMBOL_GPL(kmsg_dump_rewind); #endif + +#define CONT_LINE_MAX LOG_LINE_MAX +#define CONT_BUF_COUNT 10 +static char cont_buf[CONT_BUF_COUNT][CONT_LINE_MAX]; +static DECLARE_BITMAP(cont_buf_map, CONT_BUF_COUNT); + +static int get_cont_buf(void) +{ + int bit; + + do { + bit = find_first_zero_bit(cont_buf_map, CONT_BUF_COUNT); + if (bit == CONT_BUF_COUNT) + break; + } while (test_and_set_bit(bit, cont_buf_map)); + + return bit; +} + +static void put_cont_buf(int index) +{ + if (WARN_ON(index >= CONT_BUF_COUNT)) + return; + if (WARN_ON(!test_bit(index, cont_buf_map))) + return; + clear_bit(index, cont_buf_map); +} + +/* alloc buffer, get loglevel, setup initial text */ +int pr_cont_begin(pr_cont_t *c, const char *fmt, ...) +{ + int kern_level; + va_list args; + char *text; + + c->index = get_cont_buf(); + if (c->index == CONT_BUF_COUNT) { + /* Fallback to printk parts individually. */ + int text_len; + + va_start(args, fmt); + text_len = vprintk(fmt, args); + va_end(args); + return text_len; + } + + text = &cont_buf[c->index][0]; + + va_start(args, fmt); + c->text_len = vscnprintf(text, CONT_LINE_MAX, fmt, args); + va_end(args); + + c->loglevel = default_message_loglevel; + while (c->text_len > 1 && + (kern_level = printk_get_level(text)) != 0) { + switch (kern_level) { + case '0' ... '7': + c->loglevel = kern_level - '0'; + break; + } + + c->text_len -= 2; + memmove(text, text + 2, c->text_len); + } + + return c->text_len; +} + +/* printk existing buffer, reset buffer */ +void pr_cont_flush(pr_cont_t *c) +{ + char *text; + + if (c->index == CONT_BUF_COUNT || !c->text_len) + return; + + text = &cont_buf[c->index][0]; + + printk("%c%c%s\n", KERN_SOH_ASCII, c->loglevel + '0', text); + + c->text_len = 0; +} + +/* printk existing buffer, free buffer */ +void pr_cont_end(pr_cont_t *c) +{ + if (c->index == CONT_BUF_COUNT) + return; + + pr_cont_flush(c); + put_cont_buf(c->index); + c->index = CONT_BUF_COUNT; +} + +/* append to buffer */ +int pr_cont_append(pr_cont_t *c, const char *fmt, ...) +{ + va_list args_copy; + va_list args; + int text_len; + char *text; + + if (c->index == CONT_BUF_COUNT) { + /* Fallback to printk parts individually. */ + va_start(args, fmt); + text_len = vprintk(fmt, args); + va_end(args); + return text_len; + } + + text = &cont_buf[c->index][0]; + + /* Try to append directly. */ + va_start(args, fmt); + va_copy(args_copy, args); + text_len = vsnprintf(text + c->text_len, CONT_LINE_MAX - c->text_len, fmt, args); + va_end(args); + + if (text_len >= CONT_LINE_MAX - c->text_len) { + /* + * Not enough space remaining. Set the overwritten terminator, + * Flush any existing parts and start with a clean buffer. + * The loglevel is preserved. + */ + + text[c->text_len] = 0; + pr_cont_flush(c); + + va_start(args_copy, fmt); + c->text_len = vscnprintf(text, CONT_LINE_MAX, fmt, args_copy); + va_end(args_copy); + return c->text_len; + } + + c->text_len += text_len; + return text_len; +} -- 2.20.1