From nobody Tue Dec 2 02:41:47 2025 Received: from mail-pf1-f170.google.com (mail-pf1-f170.google.com [209.85.210.170]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 379193A8D46 for ; Tue, 18 Nov 2025 19:07:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.210.170 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763492847; cv=none; b=qpn1RpcK/J8v/+BSVK9GhfaHuoIU09SeGI6xqCVTKkdIT1LL9Xt8mD14ixVWiAA8h0ezA1d9tsv7dn4rnCwcxRaogJ2xdKw25QOwsZDGBJ2WZRBO3fEtsAvs1bsN2Fsa4pLs6ifR5ckvBETDlNO603TMLP2M4Fya5kSq+tvKSLo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1763492847; c=relaxed/simple; bh=qbm+00Q0+MW5M7XDzk/uCTDsFeWU8UuoWfP/WdNt55A=; h=Date:From:To:Cc:Subject:Message-ID:References:MIME-Version: Content-Type:Content-Disposition:In-Reply-To; b=jWL3OSkj9Fg+pcw5JA34ljSRhwf4/yupWnjhw5b4xydaksRcJrL1OTly5tt9CZ7ugluWHV/+zi8JGOEscPisAIqRoQNTn1hFDTuFK0o8UuyQoJTFQQ+tlmcWtJO151w4LCz9ct00CMjGqVI4K1/d6yElgx4HOQDb3uuw1uDNoh4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=chrisdown.name; spf=pass smtp.mailfrom=chrisdown.name; dkim=pass (1024-bit key) header.d=chrisdown.name header.i=@chrisdown.name header.b=MJmc4YjV; arc=none smtp.client-ip=209.85.210.170 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=chrisdown.name Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=chrisdown.name Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=chrisdown.name header.i=@chrisdown.name header.b="MJmc4YjV" Received: by mail-pf1-f170.google.com with SMTP id d2e1a72fcca58-7b9215e55e6so3824686b3a.2 for ; Tue, 18 Nov 2025 11:07:24 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chrisdown.name; s=google; t=1763492844; x=1764097644; darn=vger.kernel.org; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:from:to:cc:subject:date :message-id:reply-to; bh=hZF4plzNtVV8hXnk1XlbxrXJNMMIMw3IrXz8MfwBF8U=; b=MJmc4YjVENVxlZdWyp0plmoYbtl+/nGPifYJ7iDPWy1eVqlEg6OP+SDiKUBIq0TjQA ZGeepDn2jg7xT5eg1ngXVfghwmjFxAGajiJ3fczaNLNL+1JVKUEmqTjmYVscKPABy/vZ vtslz9zjST/98Yr3hKzENn2mNGN6vWlHAIJu0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1763492844; x=1764097644; h=user-agent:in-reply-to:content-disposition:mime-version:references :message-id:subject:cc:to:from:date:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=hZF4plzNtVV8hXnk1XlbxrXJNMMIMw3IrXz8MfwBF8U=; b=xKflPdeky2qSkKBLFEtW2yeBw428hfNJUsTmT18DCI876fINSErA6ZuIAedPmy8PBB z/ke1EtfHicQyFGF9wyb+STiFBrO/so0ihZwadd7Ulpd3A5qfB/MiPREytpnI34SnAM8 MVDAHBCYxSNnWTiW0G+cp+4EAC66/FZp9cQ4GPJEikOLubkD5YfTcmVqQT+03QLcIo2F 7rNsi+7KIxkDsUZl212/nPohuPjHplWPYkCUXkXFDCE0RSiNmdcSzMiP6KqHGq/fKftY ad2Q4bYqUTpewtlmP6ACAbZLVhvwjCVM2L+KJ8cT2ONXjpzvXObYxdGYm/AVmWeCSBNa W19w== X-Gm-Message-State: AOJu0YwEttrY/0AMQeA1YhzeJQhTTND9nuXg6ndI1OVrfPKMlEtOWAf0 BF/ewTuQ0USJBCMIMvhIv6c73ee84YREAeqv4krA2ZEHBVfoIIiuA2RoN7ML2s+4+RQ= X-Gm-Gg: ASbGnct7LfOLxvFbZVeOkzGkGIDcyrdGLfo+Zfo+FBZrsuUI5oZf1A8T8z8Lt3h+knA 4KOu44uczYnZYe2KTSQjDK5Ecw2yHTKS44sW42HLQnMpr5GzwOlOJX9oTADkUIpuxiX8WlkCcgD l2qo4gs0wzV+h0iR9dw4m3DJS1/u5EV06QP2m2BzXVgaV3VmUY2yulCxf65PcFwKVQtZItssodd oNXWe3YN0xxLiNj/hkVtWOjRyThNEgLyaDzlCtkt9Jyb8ig0OidIPyk4LJ/b2nVeyymDKN2XEMN L9nOsZunjBvPj54Ke3prPwpILLO+gKPr/uEXdt0lqrJu82xdkutv353W7wgNtqJGXfOi8P0r1NK UyDtjeMHC4RtaazBDohmOcSWGYikYnzDIGwhpl3I8FEvK3L4DU3Nuk0R/J+J4c2WA+1FZUpcVGR xCc5DCFyyoUBX1QUTcFi0= X-Google-Smtp-Source: AGHT+IHHWcUsp7/rgUihcSI+AhlUWpfYBXVY1d279K2O0BnxymRMN9yYqq/Yb+6+gywkoEHssoCmvg== X-Received: by 2002:a05:6a20:3d1c:b0:35d:a2c1:3a15 with SMTP id adf61e73a8af0-35da2c1d84bmr11884810637.4.1763492844165; Tue, 18 Nov 2025 11:07:24 -0800 (PST) Received: from localhost ([116.86.198.140]) by smtp.gmail.com with ESMTPSA id 41be03b00d2f7-bc36db2242esm16530128a12.6.2025.11.18.11.07.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 18 Nov 2025 11:07:23 -0800 (PST) Date: Wed, 19 Nov 2025 03:07:22 +0800 From: Chris Down To: Petr Mladek Cc: linux-kernel@vger.kernel.org, Greg Kroah-Hartman , Sergey Senozhatsky , Steven Rostedt , John Ogness , Geert Uytterhoeven , Tony Lindgren , kernel-team@fb.com Subject: [PATCH v7 06/13] printk: Support toggling per-console loglevel via syslog() and cmdline Message-ID: <1c368ffff850a00b81d4b67c15c38b826251e27d.1763492585.git.chris@chrisdown.name> References: Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: User-Agent: Mutt/2.2.15 (2b349c5e) (2025-10-02) Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" A new module parameter (ignore_per_console_loglevel) is added, which can be set via the kernel command line or at runtime through /sys/module/printk/parameters/ignore_per_console_loglevel. When set, the per-console loglevels are ignored, and the global console loglevel (console_loglevel) is used for all consoles. During sysrq, we temporarily disable per-console loglevels to ensure all requisite messages are printed to the console. This is necessary because sysrq is often used in dire circumstances where access to /sys/class/console may not be trivially possible. Additionally, the syslog actions SYSLOG_ACTION_CONSOLE_ON and SYSLOG_ACTION_CONSOLE_OFF are augmented to save and restore the state of ignore_per_console_loglevel. This allows administrators to enable or disable per-console loglevels dynamically using the syslog() system call, as supported in userspace by things like dmesg. This is useful when debugging issues with message emission, or when needing to quickly break glass and revert to global loglevel only. Signed-off-by: Chris Down Reviewed-by: Petr Mladek --- Documentation/admin-guide/index.rst | 1 + .../admin-guide/kernel-parameters.txt | 7 ++ .../admin-guide/per-console-loglevel.rst | 71 +++++++++++++++++++ MAINTAINERS | 1 + drivers/tty/sysrq.c | 6 ++ include/linux/printk.h | 2 + kernel/printk/printk.c | 29 +++++++- 7 files changed, 114 insertions(+), 3 deletions(-) create mode 100644 Documentation/admin-guide/per-console-loglevel.rst diff --git a/Documentation/admin-guide/index.rst b/Documentation/admin-guid= e/index.rst index 259d79fbeb94..5f0ae9c4017b 100644 --- a/Documentation/admin-guide/index.rst +++ b/Documentation/admin-guide/index.rst @@ -155,6 +155,7 @@ How to configure your hardware within your Linux system. media/index nvme-multipath parport + per-console-loglevel pnp rapidio rtc diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentatio= n/admin-guide/kernel-parameters.txt index 3edc5ce0e2a3..7b62a99489b8 100644 --- a/Documentation/admin-guide/kernel-parameters.txt +++ b/Documentation/admin-guide/kernel-parameters.txt @@ -2177,6 +2177,13 @@ could change it dynamically, usually by /sys/module/printk/parameters/ignore_loglevel. =20 + ignore_per_console_loglevel [KNL,EARLY] + Ignore all per-console loglevel settings + and use only the global console_loglevel for all + consoles. This can also be set at runtime via + /sys/module/printk/parameters/ignore_per_console_loglevel. + See Documentation/admin-guide/per-console-loglevel.rst. + ignore_rlimit_data Ignore RLIMIT_DATA setting for data mappings, print warning at first misuse. Can be changed via diff --git a/Documentation/admin-guide/per-console-loglevel.rst b/Documenta= tion/admin-guide/per-console-loglevel.rst new file mode 100644 index 000000000000..1f8f1eabc75c --- /dev/null +++ b/Documentation/admin-guide/per-console-loglevel.rst @@ -0,0 +1,71 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _per_console_loglevel: + +Per-console loglevel support +=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D + +Motivation +---------- + +Consoles can have vastly different latencies and throughputs. For example, +writing a message to the serial console can take on the order of tens of +milliseconds to get the UART to successfully write a message. While this m= ight +be fine for a single, one-off message, this can cause significant +application-level stalls in situations where the kernel writes large amoun= ts of +information to the console. + +This means that while you might want to send at least INFO level messages = to +(for example) netconsole, which is relatively fast, you may only want to s= end at +least WARN level messages to the serial console. This permits debugging +using the serial console in cases that netconsole doesn't receive messages +during particularly bad system issues, while still keeping the noise low e= nough +to avoid inducing latency in userspace applications. + +Loglevel +-------- + +Kernel loglevels are defined thus: + ++---+--------------+-----------------------------------+ +| 0 | KERN_EMERG | system is unusable | ++---+--------------+-----------------------------------+ +| 1 | KERN_ALERT | action must be taken immediately | ++---+--------------+-----------------------------------+ +| 2 | KERN_CRIT | critical conditions | ++---+--------------+-----------------------------------+ +| 3 | KERN_ERR | error conditions | ++---+--------------+-----------------------------------+ +| 4 | KERN_WARNING | warning conditions | ++---+--------------+-----------------------------------+ +| 5 | KERN_NOTICE | normal but significant condition | ++---+--------------+-----------------------------------+ +| 6 | KERN_INFO | informational | ++---+--------------+-----------------------------------+ +| 7 | KERN_DEBUG | debug-level messages | ++---+--------------+-----------------------------------+ + +Tunables +-------- + +In order to allow tuning per-console loglevels, the following controls exi= st: + +Global +~~~~~~ + +The global loglevel is set by the ``kernel.console_loglevel`` sysctl, whic= h can +also be set as ``loglevel=3D`` on the kernel command line. + +The printk module also takes two parameters which modify this behaviour +further: + +* ``ignore_loglevel`` on the kernel command line or set in printk paramete= rs: + Emit all messages. All other controls are ignored if this is present. + +* ``ignore_per_console_loglevel`` on the kernel command line or set in pri= ntk + parameters: Ignore all per-console loglevels and use the global loglevel. + +The default value for ``kernel.console_loglevel`` comes from +``CONFIG_CONSOLE_LOGLEVEL_DEFAULT``, or ``CONFIG_CONSOLE_LOGLEVEL_QUIET`` = if +``quiet`` is passed on the kernel command line. + diff --git a/MAINTAINERS b/MAINTAINERS index e56494c7a956..8018a4db2d9f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -20505,6 +20505,7 @@ R: John Ogness R: Sergey Senozhatsky S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git +F: Documentation/admin-guide/per-console-loglevel.rst F: Documentation/core-api/printk-basics.rst F: include/linux/printk.h F: kernel/printk/ diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c index 1763eaefd581..6cd2750e962b 100644 --- a/drivers/tty/sysrq.c +++ b/drivers/tty/sysrq.c @@ -52,6 +52,7 @@ #include #include #include +#include =20 #include #include @@ -599,12 +600,16 @@ static void __sysrq_put_key_op(u8 key, const struct s= ysrq_key_op *op_p) void __handle_sysrq(u8 key, bool check_mask) { const struct sysrq_key_op *op_p; + bool orig_ignore_per_console_loglevel; int orig_suppress_printk; int i; =20 orig_suppress_printk =3D suppress_printk; suppress_printk =3D 0; =20 + orig_ignore_per_console_loglevel =3D ignore_per_console_loglevel; + ignore_per_console_loglevel =3D true; + rcu_sysrq_start(); rcu_read_lock(); /* @@ -650,6 +655,7 @@ void __handle_sysrq(u8 key, bool check_mask) rcu_read_unlock(); rcu_sysrq_end(); =20 + ignore_per_console_loglevel =3D orig_ignore_per_console_loglevel; suppress_printk =3D orig_suppress_printk; } =20 diff --git a/include/linux/printk.h b/include/linux/printk.h index 644584edf3e9..e36cae1805b2 100644 --- a/include/linux/printk.h +++ b/include/linux/printk.h @@ -73,6 +73,8 @@ extern int console_printk[]; #define minimum_console_loglevel (console_printk[2]) #define default_console_loglevel (console_printk[3]) =20 +extern bool ignore_per_console_loglevel; + extern void console_verbose(void); =20 /* strlen("ratelimit") + 1 */ diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index b8679b0da42f..80204cbb7bc8 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -104,6 +104,9 @@ DEFINE_STATIC_SRCU(console_srcu); */ int __read_mostly suppress_printk; =20 +/* The sysrq infrastructure needs this even on !CONFIG_PRINTK. */ +bool __read_mostly ignore_per_console_loglevel; + #ifdef CONFIG_LOCKDEP static struct lockdep_map console_lock_dep_map =3D { .name =3D "console_lock" @@ -1298,9 +1301,21 @@ module_param(ignore_loglevel, bool, S_IRUGO | S_IWUS= R); MODULE_PARM_DESC(ignore_loglevel, "ignore loglevel setting (prints all kernel messages to the console)"); =20 +static int __init ignore_per_console_loglevel_setup(char *str) +{ + ignore_per_console_loglevel =3D true; + return 0; +} + +early_param("ignore_per_console_loglevel", ignore_per_console_loglevel_set= up); +module_param(ignore_per_console_loglevel, bool, 0644); +MODULE_PARM_DESC( + ignore_per_console_loglevel, + "ignore per-console loglevel setting (only respect global console logleve= l)"); + bool has_per_console_loglevel(const struct console *con) { - return con && (console_srcu_read_loglevel(con) > 0); + return !ignore_per_console_loglevel && con && (console_srcu_read_loglevel= (con) > 0); } =20 /** @@ -1340,7 +1355,7 @@ console_effective_loglevel_source(int con_level) if (ignore_loglevel) return LLS_IGNORE_LOGLEVEL; =20 - if (is_valid_per_console_loglevel(con_level)) + if (!ignore_per_console_loglevel && is_valid_per_console_loglevel(con_lev= el)) return LLS_LOCAL; =20 return LLS_GLOBAL; @@ -1863,6 +1878,7 @@ int do_syslog(int type, char __user *buf, int len, in= t source) struct printk_info info; bool clear =3D false; static int saved_console_loglevel =3D LOGLEVEL_DEFAULT; + static bool saved_ignore_per_console_loglevel; int error; =20 error =3D check_syslog_permissions(type, source); @@ -1904,9 +1920,12 @@ int do_syslog(int type, char __user *buf, int len, i= nt source) /* Disable logging to console */ case SYSLOG_ACTION_CONSOLE_OFF: mutex_lock(&syslog_lock); - if (saved_console_loglevel =3D=3D LOGLEVEL_DEFAULT) + if (saved_console_loglevel =3D=3D LOGLEVEL_DEFAULT) { saved_console_loglevel =3D console_loglevel; + saved_ignore_per_console_loglevel =3D ignore_per_console_loglevel; + } console_loglevel =3D minimum_console_loglevel; + ignore_per_console_loglevel =3D true; mutex_unlock(&syslog_lock); break; /* Enable logging to console */ @@ -1914,12 +1933,16 @@ int do_syslog(int type, char __user *buf, int len, = int source) mutex_lock(&syslog_lock); if (saved_console_loglevel !=3D LOGLEVEL_DEFAULT) { console_loglevel =3D saved_console_loglevel; + ignore_per_console_loglevel =3D saved_ignore_per_console_loglevel; saved_console_loglevel =3D LOGLEVEL_DEFAULT; } mutex_unlock(&syslog_lock); break; /* Set level of messages printed to console */ case SYSLOG_ACTION_CONSOLE_LEVEL: + if (!ignore_per_console_loglevel) + pr_warn_once( + "SYSLOG_ACTION_CONSOLE_LEVEL is ignored by consoles with an explicitly= set per-console loglevel, see Documentation/admin-guide/per-console-loglev= el.rst\n"); if (len < 1 || len > 8) return -EINVAL; if (len < minimum_console_loglevel) --=20 2.51.2