forked from torvalds/linux
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
printk: console: Support console-specific loglevels
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 might be fine for a single, one-off message, this can cause significant application-level stalls in situations where the kernel writes large amounts 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 send at least WARN level messages to the serial console. Such an implementation would permit debugging using the serial console in cases that netconsole doesn't receive messages during particularly bad system issues, while still keeping the noise low enough to avoid inducing latency in userspace applications. This patch adds such an interface, extending the existing console loglevel controls to allow each console to have its own loglevel. One can't just disable the serial console, because one may actually need it in situations where the machine is in a bad enough state that nothing is received on netconsole. One also can't just bump the loglevel at runtime after the issue, because usually the machine is already so wedged by this point that it isn't responsive to such requests. In terms of technical implementation, this patch embeds a device pointer in the console struct, and registers each console using it so we can expose attributes in sysfs. We currently expose the following attributes: % ls -l /sys/class/console/ttyS/ total 0 lrwxrwxrwx 1 root root 0 Jul 20 17:37 subsystem -> ../../../../class/console/ -r--r--r-- 1 root root 4096 Jul 20 17:38 effective_loglevel -r--r--r-- 1 root root 4096 Jul 20 17:38 effective_loglevel_source -r--r--r-- 1 root root 4096 Jul 20 17:38 enabled -rw-r--r-- 1 root root 4096 Jul 20 17:38 loglevel -rw-r--r-- 1 root root 4096 Jul 20 17:37 uevent The lifecycle of this classdev looks like this on registration: register_console(con)/printk_late_init() console_register_device(con) device_initialize(con->classdev) # refcount++ device_add(con->classdev) # refcount++ At stable state, the refcount is two. Console unregistration looks like this: [con->classdev refcount drops to 0] console_classdev_release(con->classdev) kfree(con->classdev) unregister_console(con) device_unregister(con->classdev) device_del(con->classdev) # refcount-- device_remove_class_symlinks() kernfs_remove_by_name_ns() kernfs_drain() kernfs_drain_open_files() # wait for close() put_device(con->classdev) # refcount-- We also deprecate the kernel.printk sysctl as it doesn't know about per-console loglevels, and is generally pretty confusing. For information on the precedence and application of the new controls, see Documentation/ABI/testing/sysfs-class-console and Documentation/admin-guide/per-console-loglevel.rst. Signed-off-by: Chris Down <chris@chrisdown.name>
- Loading branch information
1 parent
6c872a2
commit fac1dc8
Showing
11 changed files
with
574 additions
and
36 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
What: /sys/class/console/ | ||
Date: May 2022 | ||
Contact: Chris Down <chris@chrisdown.name> | ||
Description: Interface for viewing and setting per-console attributes, like | ||
the per-console loglevel. For a high-level document describing | ||
the motivations for this interface and related non-sysfs | ||
controls, see | ||
Documentation/admin-guide/per-console-loglevel.rst. | ||
|
||
What: /sys/class/console/<C>/effective_loglevel | ||
Date: May 2022 | ||
Contact: Chris Down <chris@chrisdown.name> | ||
Description: Read only. The currently effective loglevel for this console. | ||
All messages emitted with a loglevel below the effective value | ||
will be emitted to the console. | ||
|
||
What: /sys/class/console/<C>/effective_loglevel_source | ||
Date: May 2022 | ||
Contact: Chris Down <chris@chrisdown.name> | ||
Description: Read only. The currently effective loglevel source for this | ||
console -- for example, whether it was set globally, or whether | ||
it was set locally for this console. Possible values are: | ||
|
||
local: The loglevel comes from the per-console loglevel. | ||
global: The loglevel comes from the global loglevel. | ||
ignore_loglevel: Both the per-console loglevel and global | ||
loglevels are ignored as ignore_loglevel is | ||
present on the kernel command line. | ||
|
||
What: /sys/class/console/<C>/enabled | ||
Date: May 2022 | ||
Contact: Chris Down <chris@chrisdown.name> | ||
Description: Read only. "1" if the console is enabled, "0" otherwise. | ||
|
||
What: /sys/class/console/<C>/loglevel | ||
Date: May 2022 | ||
Contact: Chris Down <chris@chrisdown.name> | ||
Description: Read write. The current per-console loglevel, which will take | ||
effect if not overridden by other non-sysfs controls (see | ||
Documentation/admin-guide/per-console-loglevel.rst). Bounds are | ||
0 (LOGLEVEL_EMERG) to 8 (LOGLEVEL_DEBUG + 1) inclusive. Also | ||
takes the special value "unset" to indicate that no per-console | ||
loglevel is set, and we should defer to the global controls. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,92 @@ | ||
.. SPDX-License-Identifier: GPL-2.0 | ||
.. _per_console_loglevel: | ||
|
||
Per-console loglevel support | ||
============================ | ||
|
||
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 might | ||
be fine for a single, one-off message, this can cause significant | ||
application-level stalls in situations where the kernel writes large amounts 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 send | ||
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 enough | ||
to avoid inducing latency in userspace applications. | ||
|
||
Tunables | ||
-------- | ||
|
||
In order to allow tuning this, the following controls exist: | ||
|
||
Global | ||
~~~~~~ | ||
|
||
The global loglevel is set by the ``kernel.console_loglevel`` sysctl, which can | ||
also be set as ``loglevel=`` 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 parameters: | ||
Emit all messages. All other controls are ignored if this is present. | ||
* ``ignore_per_console_loglevel`` on the kernel command line or set in printk | ||
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. | ||
|
||
Console attributes | ||
~~~~~~~~~~~~~~~~~~ | ||
|
||
Registered consoles are exposed at ``/sys/class/console``. For example, if you | ||
are using ``ttyS0``, the console backing it can be viewed at | ||
``/sys/class/console/ttyS/``. The following files are available: | ||
|
||
* ``effective_loglevel`` (r): The effective loglevel after considering all | ||
loglevel authorities. For example, if the console-specific loglevel is 3, but | ||
the global minimum console loglevel[*]_ is 5, then the value will be 5. | ||
* ``effective_loglevel_source`` (r): The loglevel authority which resulted in | ||
the effective loglevel being set. The following values can be present: | ||
|
||
* ``local``: The console-specific loglevel is in effect. | ||
* ``global``: The global loglevel (``kernel.console_loglevel``) is in | ||
effect. Set a console-specific loglevel to override it. | ||
* ``ignore_loglevel``: ``ignore_loglevel`` was specified on the kernel | ||
command line or at ``/sys/module/printk/parameters/ignore_loglevel``. | ||
Disable it to use level controls. | ||
* ``ignore_per_console_loglevel``: ``ignore_per_console_loglevel`` was | ||
specified on the kernel command line or at | ||
``/sys/module/printk/parameters/ignore_per_console_loglevel``. Disable it | ||
to use per-console level controls. | ||
|
||
* ``enabled`` (r): Whether the console is enabled. | ||
* ``loglevel`` (rw): The local, console-specific loglevel for this console. | ||
This will be in effect if no other global control overrides it. Look at | ||
``effective_loglevel`` and ``effective_loglevel_source`` to verify that. | ||
|
||
.. [*] The existence of a minimum console loglevel is generally considered to | ||
be a confusing and rarely used interface, and as such is not exposed through | ||
the modern printk sysctl APIs that obsoleted ``kernel.printk``. Use the | ||
legacy ``kernel.printk`` sysctl to control it if you have a rare use case | ||
that requires changing it. The default value is ``CONSOLE_LOGLEVEL_MIN``. | ||
Deprecated | ||
~~~~~~~~~~ | ||
|
||
* ``kernel.printk`` sysctl: this takes four values, setting | ||
``kernel.console_loglevel``, ``kernel.default_message_loglevel``, the minimum | ||
console loglevel, and a fourth unused value. The interface is generally | ||
considered to quite confusing, doesn't perform checks on the values given, | ||
and is unaware of per-console loglevel semantics. | ||
|
||
Chris Down <chris@chrisdown.name>, 17-May-2022 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.