Received: by 2002:ac0:946b:0:0:0:0:0 with SMTP id j40csp3919536imj; Tue, 12 Feb 2019 06:56:58 -0800 (PST) X-Google-Smtp-Source: AHgI3IbTji1hNLOTc+xANn11rSGJoyn8LkEy85Bh/7ITP/4/xaeaHiEFen4xHgOX/DOBX1PtDBIE X-Received: by 2002:a17:902:e492:: with SMTP id cj18mr4428517plb.341.1549983418371; Tue, 12 Feb 2019 06:56:58 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1549983418; cv=none; d=google.com; s=arc-20160816; b=aotpyvAUhgDGPbegJgEZthu4D7Bpt/R4k0VeLqQ0P5aTX7Htu6xMBaGWLLUtJAzx5n /wL7DVwG3i8Kbnhy5/VaEYZ++AG6OIw0XDIjvEGbXbdibUIZUZgFN/owL6WXdD/fJ/gc yci8fw0+9QYNKVwE3n6Utqi310a7YK5ybhkHOi0v0x8fEZ5nrlaAkUEf0MZcApyAj0m0 iOTZDcdBQuvVWYyeY2RU1NAgjB94WLPiJeXmQlXba4Tlcb/j+9QcuwCC8UlWPqLL7ttA rx8B8VP3nj+waR4GSsaucKOCMeWNfQHUfF/3KNw+qmx4u63YMre+N8ZPZj5XeF9m03DS WfNg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from; bh=26rAiVHSeEODD2/I9AWDIHN1vqSVaRrrCT0IO7Y4i2I=; b=o6teTgQg0NLURt0sZLzYtVRRzrbixQtsXyT5qBAWM2x6OoCSuOgnTAGsaY9pdPDx2Y jQcHG8sIupHByjzRbBkdug06IcT8yLZvrYycO3VSx3J/EI4ZDMwtXh5IWSok7zrayQcI xoRix9JR6quKERQ0W22iuGFf0LrjFFMEqc73VUgIiLBoV/A9KzlzlXcrroq3op8FWa+p TH02fyRnB/Yqxt4lO7QREI2tb6smXg2qNhd0pJ6ucRrVGQ3IEkmbF+140RpPsiRcezBM RkIpgLOCKLTgO54/W/XYrz4Mo1kYqCX3/qEYSfmS54Af8L9qEX0q3u6UptOcVpuWcCLi Lp7w== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id x26si12416913pgk.107.2019.02.12.06.56.42; Tue, 12 Feb 2019 06:56:58 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1729383AbfBLOdD (ORCPT + 99 others); Tue, 12 Feb 2019 09:33:03 -0500 Received: from Galois.linutronix.de ([146.0.238.70]:43705 "EHLO Galois.linutronix.de" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727343AbfBLOa3 (ORCPT ); Tue, 12 Feb 2019 09:30:29 -0500 Received: from [5.158.153.53] (helo=linux.lab.linutronix.de.) by Galois.linutronix.de with esmtpsa (TLS1.2:DHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.80) (envelope-from ) id 1gtZ4h-0005Af-QL; Tue, 12 Feb 2019 15:30:16 +0100 From: John Ogness To: linux-kernel@vger.kernel.org Cc: Peter Zijlstra , Petr Mladek , Sergey Senozhatsky , Steven Rostedt , Daniel Wang , Andrew Morton , Linus Torvalds , Greg Kroah-Hartman , Alan Cox , Jiri Slaby , Peter Feiner , linux-serial@vger.kernel.org, Sergey Senozhatsky Subject: [RFC PATCH v1 08/25] printk: add ring buffer and kthread Date: Tue, 12 Feb 2019 15:29:46 +0100 Message-Id: <20190212143003.48446-9-john.ogness@linutronix.de> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20190212143003.48446-1-john.ogness@linutronix.de> References: <20190212143003.48446-1-john.ogness@linutronix.de> X-Linutronix-Spam-Score: -1.0 X-Linutronix-Spam-Level: - X-Linutronix-Spam-Status: No , -1.0 points, 5.0 required, ALL_TRUSTED=-1,SHORTCIRCUIT=-0.0001 Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The printk ring buffer provides an NMI-safe interface for writing messages to a ring buffer. Using such a buffer for alleviates printk callers from the current burdens of disabled preemption while calling the console drivers (and possibly printing out many messages that another task put into the log buffer). Create a ring buffer to be used for storing messages to be printed to the consoles. Create a dedicated printk kthread to block on the ring buffer and call the console drivers for the read messages. NOTE: The printk_delay is relocated to _after_ the message is printed, where it makes more sense. Signed-off-by: John Ogness --- kernel/printk/printk.c | 105 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index d3d170374ceb..08e079b95652 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -44,6 +44,8 @@ #include #include #include +#include +#include #include #include #include @@ -397,7 +399,12 @@ DEFINE_RAW_SPINLOCK(logbuf_lock); printk_safe_exit_irqrestore(flags); \ } while (0) +DECLARE_STATIC_PRINTKRB_CPULOCK(printk_cpulock); + #ifdef CONFIG_PRINTK +/* record buffer */ +DECLARE_STATIC_PRINTKRB(printk_rb, CONFIG_LOG_BUF_SHIFT, &printk_cpulock); + DECLARE_WAIT_QUEUE_HEAD(log_wait); /* the next printk record to read by syslog(READ) or /proc/kmsg */ static u64 syslog_seq; @@ -744,6 +751,10 @@ static ssize_t msg_print_ext_body(char *buf, size_t size, return p - buf; } +#define PRINTK_SPRINT_MAX (LOG_LINE_MAX + PREFIX_MAX) +#define PRINTK_RECORD_MAX (sizeof(struct printk_log) + \ + CONSOLE_EXT_LOG_MAX + PRINTK_SPRINT_MAX) + /* /dev/kmsg - userspace message inject/listen interface */ struct devkmsg_user { u64 seq; @@ -1566,6 +1577,34 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len) return do_syslog(type, buf, len, SYSLOG_FROM_READER); } +static void format_text(struct printk_log *msg, u64 seq, + char *ext_text, size_t *ext_len, + char *text, size_t *len, bool time) +{ + if (suppress_message_printing(msg->level)) { + /* + * Skip record that has level above the console + * loglevel and update each console's local seq. + */ + *len = 0; + *ext_len = 0; + return; + } + + *len = msg_print_text(msg, console_msg_format & MSG_FORMAT_SYSLOG, + time, text, PRINTK_SPRINT_MAX); + if (nr_ext_console_drivers) { + *ext_len = msg_print_ext_header(ext_text, CONSOLE_EXT_LOG_MAX, + msg, seq); + *ext_len += msg_print_ext_body(ext_text + *ext_len, + CONSOLE_EXT_LOG_MAX - *ext_len, + log_dict(msg), msg->dict_len, + log_text(msg), msg->text_len); + } else { + *ext_len = 0; + } +} + /* * Special console_lock variants that help to reduce the risk of soft-lockups. * They allow to pass console_lock to another printk() call using a busy wait. @@ -2899,6 +2938,72 @@ void wake_up_klogd(void) preempt_enable(); } +static int printk_kthread_func(void *data) +{ + struct prb_iterator iter; + struct printk_log *msg; + size_t ext_len; + char *ext_text; + u64 master_seq; + size_t len; + char *text; + char *buf; + int ret; + + ext_text = kmalloc(CONSOLE_EXT_LOG_MAX, GFP_KERNEL); + text = kmalloc(PRINTK_SPRINT_MAX, GFP_KERNEL); + buf = kmalloc(PRINTK_RECORD_MAX, GFP_KERNEL); + if (!ext_text || !text || !buf) + return -1; + + prb_iter_init(&iter, &printk_rb, NULL); + + /* the printk kthread never exits */ + for (;;) { + ret = prb_iter_wait_next(&iter, buf, + PRINTK_RECORD_MAX, &master_seq); + if (ret == -ERESTARTSYS) { + continue; + } else if (ret < 0) { + /* iterator invalid, start over */ + prb_iter_init(&iter, &printk_rb, NULL); + continue; + } + + msg = (struct printk_log *)buf; + format_text(msg, master_seq, ext_text, &ext_len, text, + &len, printk_time); + + console_lock(); + if (len > 0 || ext_len > 0) { + call_console_drivers(ext_text, ext_len, text, len); + boot_delay_msec(msg->level); + printk_delay(); + } + console_unlock(); + } + + kfree(ext_text); + kfree(text); + kfree(buf); + + return 0; +} + +static int __init init_printk_kthread(void) +{ + struct task_struct *thread; + + thread = kthread_run(printk_kthread_func, NULL, "printk"); + if (IS_ERR(thread)) { + pr_err("printk: unable to create printing thread\n"); + return PTR_ERR(thread); + } + + return 0; +} +late_initcall(init_printk_kthread); + void defer_console_output(void) { preempt_disable(); -- 2.11.0