printk: console: Allow each console to have its own loglevel
Subsystems (6)
RFC PATCH v2 1/1 printk: console: Allow each console to have its own loglevel
[Once the goals of this patch are generally agreed upon, it can be split out further with more detailed changelogs if desired.]
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.
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.
--- Documentation/ABI/testing/sysfs-class-console | 50 +++ .../admin-guide/kernel-parameters.txt | 18 +- .../admin-guide/per-console-loglevel.rst | 116 ++++++ Documentation/admin-guide/serial-console.rst | 17 +- Documentation/core-api/printk-basics.rst | 34 +- Documentation/networking/netconsole.rst | 17 + MAINTAINERS | 3 + include/linux/console.h | 23 ++ include/linux/kern_levels.h | 2 + init/main.c | 2 +- kernel/printk/console_cmdline.h | 2 + kernel/printk/printk.c | 352 ++++++++++++++++-- kernel/printk/sysctl.c | 95 ++++- 13 files changed, 680 insertions(+), 51 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-console create mode 100644 Documentation/admin-guide/per-console-loglevel.rst
Documentation/ABI/testing/sysfs-class-console new file +50 -0
@@ -0,0 +1,50 @@ +What: /sys/class/console/ +Date: May 2022 +Contact: Chris Down <[email protected]> +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 <[email protected]> +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 <[email protected]> +Description: Read only. The currently effective loglevel source for this + console -- for example, whether it was set globally based on + the default loglevel, or whether it was set locally. Possible + values are: + + local: The loglevel comes from the per-console loglevel. + global: The loglevel comes from the global default loglevel. + forced: The loglevel comes from the global forced loglevel. + minimum: The loglevel comes from the global minimum loglevel. + forced_minimum: A forced global loglevel is active, but it is + below the global minimum loglevel. The loglevel + comes from the global minimum loglevel and is + forced regardless of the console's current + local loglevel setting. + ignore_loglevel: The loglevel is ignored as ignore_loglevel is + present on the kernel command line. + +What: /sys/class/console/<C>/enabled +Date: May 2022 +Contact: Chris Down <[email protected]> +Description: Read only. "1" if the console is enabled, "0" otherwise. + +What: /sys/class/console/<C>/loglevel +Date: May 2022 +Contact: Chris Down <[email protected]> +Description: Read write. The current local 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 local + loglevel is set, and we should defer to the global controls.
Documentation/admin-guide/kernel-parameters.txt +11 -7
@@ -696,10 +696,11 @@ ttyS<n>[,options] ttyUSB0[,options] Use the specified serial port. The options are of - the form "bbbbpnf", where "bbbb" is the baud rate, + the form "bbbbpnf/l", where "bbbb" is the baud rate, "p" is parity ("n", "o", or "e"), "n" is number of - bits, and "f" is flow control ("r" for RTS or - omit it). Default is "9600n8". + bits, "f" is flow control ("r" for RTS or omit it), + and "l" is the minimum loglevel ([0,8], can be + omitted). The default is "9600n8". See Documentation/admin-guide/serial-console.rst for more information. See
@@ -2709,10 +2710,13 @@ logibm.irq= [HW,MOUSE] Logitech Bus Mouse Driver Format: <irq> - loglevel= All Kernel Messages with a loglevel smaller than the - console loglevel will be printed to the console. It can - also be changed with klogd or other programs. The - loglevels are defined as follows: + loglevel= Sets the default loglevel. All messages with a loglevel + smaller than the console loglevel will be printed to + the console. Note that this can be overridden + per-console, see + Documentation/admin-guide/per-console-loglevel.rst. + + The loglevels are defined as follows: 0 (KERN_EMERG) system is unusable 1 (KERN_ALERT) action must be taken immediately
Documentation/admin-guide/per-console-loglevel.rst new file +116 -0
116 lines not on this page · raw message
Documentation/admin-guide/serial-console.rst +13 -4
@@ -17,7 +17,7 @@ use for console output. The format of this option is:: - console=device,options + console=device,options/loglevel device: tty0 for the foreground virtual console ttyX for any other virtual console
@@ -32,15 +32,23 @@ The format of this option is:: and F is flow control ('r' for RTS). Default is 9600n8. The maximum baudrate is 115200. + loglevel: optional. a number can be provided from 0 + (LOGLEVEL_EMERG) to 8 (LOGLEVEL_DEBUG + 1), and + messages below that will be emitted onto the console as + they become available. + You can specify multiple console= options on the kernel command line. Output will appear on all of them. The last device will be used when you open ``/dev/console``. So, for example:: - console=ttyS1,9600 console=tty0 + console=ttyS1,9600/5 console=tty0 defines that opening ``/dev/console`` will get you the current foreground -virtual console, and kernel messages will appear on both the VGA -console and the 2nd serial port (ttyS1 or COM2) at 9600 baud. +virtual console, and kernel messages will appear on both the VGA console and +the 2nd serial port (ttyS1 or COM2) at 9600 baud. The optional loglevel "5" +indicates that this console will emit messages more serious than +LOGLEVEL_NOTICE (that is, LOGLEVEL_WARNING and below, since more serious +messages have lower ordering). Note that you can only define one console per device type (serial, video).
@@ -113,3 +121,4 @@ Replace the sample values as needed. the integration of these patches into m68k, ppc and alpha. Miquel van Smoorenburg <[email protected]>, 11-Jun-2000 +Chris Down <[email protected]>, 17-May-2020
Documentation/core-api/printk-basics.rst +17 -17
@@ -54,32 +54,32 @@ string, the log level is not a separate argument). The available log levels are: The log level specifies the importance of a message. The kernel decides whether to show the message immediately (printing it to the current console) depending -on its log level and the current *console_loglevel* (a kernel variable). If the -message priority is higher (lower log level value) than the *console_loglevel* -the message will be printed to the console. +on its log level and the current global *console_loglevel* or local per-console +loglevel (kernel variables). If the message priority is higher (lower log level +value) than the effective loglevel the message will be printed to the console. If the log level is omitted, the message is printed with ``KERN_DEFAULT`` level. -You can check the current *console_loglevel* with:: +You can check the current console's loglevel -- for example if you want to +check the loglevel for serial consoles: - $ cat /proc/sys/kernel/printk - 4 4 1 7 + $ cat /sys/class/console/ttyS/effective_loglevel + 6 + $ cat /sys/class/console/ttyS/effective_loglevel_source + local -The result shows the *current*, *default*, *minimum* and *boot-time-default* log -levels. +To change the current loglevel for all consoles, simply write the desired level +to ``/proc/sys/kernel/forced_console_loglevel``. For example, to print all +messages to all consoles:: -To change the current console_loglevel simply write the desired level to -``/proc/sys/kernel/printk``. For example, to print all messages to the console:: + # echo 5 > /proc/sys/kernel/forced_console_loglevel - # echo 8 > /proc/sys/kernel/printk +This sets the console_loglevel to print KERN_WARNING (4) or more severe +messages to console. -Another way, using ``dmesg``:: - - # dmesg -n 5 - -sets the console_loglevel to print KERN_WARNING (4) or more severe messages to -console. See ``dmesg(1)`` for more information. +For more information on per-console loglevels, see +Documentation/admin-guide/per-console-loglevel.rst. As an alternative to printk() you can use the ``pr_*()`` aliases for logging. This family of macros embed the log level in the macro names. For
Documentation/networking/netconsole.rst +17 -0
@@ -67,6 +67,23 @@ Built-in netconsole starts immediately after the TCP stack is initialized and attempts to bring up the supplied dev at the supplied address. +You can also set a loglevel at boot time on the kernel command line:: + + console=netcon0/2 + +This can also be changed at runtime:: + + $ ls -l /sys/class/console/netcon/ + total 0 + lrwxrwxrwx 1 root root 0 May 18 13:28 subsystem -> ../../../../class/console/ + -r--r--r-- 1 root root 4096 May 18 13:28 effective_loglevel + -r--r--r-- 1 root root 4096 May 18 13:28 effective_loglevel_source + -r--r--r-- 1 root root 4096 May 18 13:28 enabled + -rw-r--r-- 1 root root 4096 May 18 13:28 loglevel + -rw-r--r-- 1 root root 4096 May 18 13:28 uevent + +See Documentation/admin-guide/per-console-loglevel.rst for more information. + The remote host has several options to receive the kernel messages, for example:
MAINTAINERS +3 -0
@@ -15579,6 +15579,9 @@ R: Steven Rostedt <[email protected]> R: John Ogness <[email protected]> S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/printk/linux.git +F: Documentation/ABI/testing/sysfs-class-console +F: Documentation/admin-guide/per-console-loglevel.rst +F: Documentation/core-api/printk-basics.rst F: include/linux/printk.h F: kernel/printk/
include/linux/console.h +23 -0
@@ -15,6 +15,7 @@#define _LINUX_CONSOLE_H_ 1#include <linux/atomic.h> +#include <linux/device.h> #include <linux/types.h> struct vc_data ;
@@ -137,6 +138,24 @@ static inline int con_debug_leave(void)#define CON_BRL (32)/* Used for a braille device */ #define CON_EXTENDED (64)/* Use the extended output format a la /dev/kmsg */ +/* +* The loglevel for a console can be set in many places: +* +* 1. It can be forced to a certain value permanently (ignore_loglevel); +* 2. It can be forced temporarily to a value (sysctls kernel.printk +* (deprecated), kernel.force_console_loglevel, +* kernel.minimum_console_loglevel, magic sysrq) +* 3. It can be locally set (console=.../N on kernel command line, +* /sys/class/console/.../loglevel); +* 4. It can be set by a global default +* (CONFIG_CONSOLE_LOGLEVEL_{DEFAULT,QUIET}, loglevel= on kernel command +* line, sysctl kernel.default_console_loglevel). +* +* If case 3 happens, even if another forced value in effect, CON_LOGLEVEL will +* be set. +*/ +#define CON_LOGLEVEL (128)/* Level set locally for this console */ +struct console {char name[16 ];void (*write)(struct console *,const char *,unsigned );
@@ -153,8 +172,12 @@ struct console {uint ospeed;void *data;struct console *next; +int level; +struct device *classdev; }; +#define classdev_to_console (dev) dev_get_drvdata(dev) +/* * for_each_console() allows you to iterate on each console */
include/linux/kern_levels.h +2 -0
@@ -24,6 +24,8 @@#define KERN_CONT KERN_SOH "c"/* integer equivalents of KERN_<LEVEL> */ +#define LOGLEVEL_INVALID -127/* Invalid loglevel, used to indicate +this loglevel is not used */ #define LOGLEVEL_SCHED -2/* Deferred messages from sched code * are set to this special level */ #define LOGLEVEL_DEFAULT -1/* default (or last) loglevel */
init/main.c +1 -1
@@ -255,7 +255,7 @@ static int __init loglevel(char *str)* are quite hard to debug */ if (get_option (&str, &newlevel)) { - console_loglevel = newlevel; + default_console_loglevel = newlevel;return 0 ; }
kernel/printk/console_cmdline.h +2 -0
@@ -6,6 +6,8 @@ struct console_cmdline {char name[16 ];/* Name of the driver */ int index;/* Minor dev. to use */ +int level;/* Log level to use */ +short flags;/* Initial flags */ bool user_specified;/* Specified by command line vs. platform */ char *options;/* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE
kernel/printk/printk.c +331 -21
531 lines not on this page · raw message
kernel/printk/sysctl.c +94 -1
122 lines not on this page · raw message
base-commit: 3ef4ea3d84ca568dcd57816b9521e82e3bd94f08
Signature · 1 line
2.36.0
Quoted 4 lines · Chris Down
[Once the goals of this patch are generally agreed upon, it can be split
out further with more detailed changelogs if desired.]
Quoted 10 lines
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.
It's more than just application-level stalls. I have seen some cases of the kernel spending so much time logging things to serial console that it thinks it locked up, and panics as a result of how slow the serial console is.
Adding insult to injury, because the log level is sytem wide, we only see _some_ of the hints of why the kernel started spewing like that in the netcons logs.
If we print all the information, we will have more hosts panic because we spent too much time in the serial console code.
If we print less information, we won't find out some of the other things causing issues on systems.
Having per console log levels will allow us to avoid the serial console issues, and gather all the info we need on other stuff happening on the system.
Signature · 1 line
All Rights Reversed.
Petr Mladek
maintainerQuoted 27 lines · Rik van Riel
Quoted 4 lines · Chris Down
[Once the goals of this patch are generally agreed upon, it can be split
out further with more detailed changelogs if desired.]Quoted 10 lines
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.It's more than just application-level stalls. I have seen some cases of the kernel spending so much time logging things to serial console that it thinks it locked up, and panics as a result of how slow the serial console is.
Adding insult to injury, because the log level is sytem wide, we only see _some_ of the hints of why the kernel started spewing like that in the netcons logs.
If we print all the information, we will have more hosts panic because we spent too much time in the serial console code.
Quoted 6 lines
If we print less information, we won't find out some of the other things causing issues on systems.
Having per console log levels will allow us to avoid the serial console issues, and gather all the info we need on other stuff happening on the system.
The problem is clear. But the big part of the problem is that printk() tries to show the messages on all consoles immediately.
I wonder how much the per-console loglevel would be needed when the console handling is offloaded to per-console kthreads, see
https://lore.kernel.org/all/[email protected]/
It causes that printk() should "never" block and each console might run on its own speed.
It still might be useful from some reasons:
+ Serial consoles might miss messages because the old messages are over-written before they reach the console. It might be solved by big enough buffer.
+ printk() still tries to show the messages immediately in some critical situations, for example, early boot, watchdog warnings, suspend, reboot, OOps, panic(). The slow consoles might still cause stalls and put the system into its knees.
+ People might need to explicitly disable the kthreads, for example, when debugging a situation when kthreads are not scheduled.
So, I think that the per-console loglevels might still be useful. But I wonder if they really will be used in practice. It does not make sense to add feature that would get obsoleted by the kthreads.
Note that the per-console kthreads were added into 5.19-rc1. Unfortunately they were reverted in 5.19-rc4 because there were some issues that need more work. But we still believe that they are needed and we could make them working reliably.
Best Regards,
Petr
PS: I am sorry for the late response. I am still snowed under many tasks. The printk kthreads are complicated and need a lot of attention. Plus there was a sickness, vacations, and other tasks.
Quoted 15 lines · Petr Mladek
The problem is clear. But the big part of the problem is that
printk()tries to show the messages on all consoles immediately.I wonder how much the per-console loglevel would be needed when the console handling is offloaded to per-console kthreads, see
https://lore.kernel.org/all/[email protected]/
It causes thatprintk()should "never" block and each console might run on its own speed.It still might be useful from some reasons:
+ Serial consoles might miss messages because the old messages are over-written before they reach the console. It might be solved by big enough buffer.
Quoted 8 lines
+
printk()still tries to show the messages immediately in some critical situations, for example, early boot, watchdog warnings, suspend, reboot, OOps,panic(). The slow consoles might still cause stalls and put the system into its knees.+ People might need to explicitly disable the kthreads, for example, when debugging a situation when kthreads are not scheduled.
Indeed. In addition to these, there are cases (like the pstore case mentioned by Vincent) where we want to bump the console loglevel up to the maximum for debugging, but it still doesn't make sense to emit it over all consoles -- especially netconsoles where processing capacity on the netconsole receiver/server is likely limited. The same is true for things like baseboard management controllers where they may blindly store the console output in a similar fashion.
The kthread offloading is definitely going to help a lot here here, but to capably be able to use netconsole in prod we're going to need both.
Quoted 4 lines
PS: I am sorry for the late response. I am still snowed under many tasks. The printk kthreads are complicated and need a lot of attention. Plus there was a sickness, vacations, and other tasks.
Don't worry, I totally understand :-) I really appreciate you getting back.
Greg Kroah-Hartman
maintainerQuoted 71 lines · Chris Down
[Once the goals of this patch are generally agreed upon, it can be split out further with more detailed changelogs if desired.]
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.
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-consoleandDocumentation/admin-guide/per-console-loglevel.rst.Signed-off-by Chris Down <[email protected]>--- Documentation/ABI/testing/sysfs-class-console | 50 +++ .../admin-guide/kernel-parameters.txt | 18 +- .../admin-guide/per-console-loglevel.rst | 116 ++++++ Documentation/admin-guide/serial-console.rst | 17 +- Documentation/core-api/printk-basics.rst | 34 +- Documentation/networking/netconsole.rst | 17 + MAINTAINERS | 3 + include/linux/console.h | 23 ++
Quoted 8 lines
include/linux/kern_levels.h | 2 + init/main.c | 2 +- kernel/printk/console_cmdline.h | 2 + kernel/printk/printk.c | 352 ++++++++++++++++-- kernel/printk/sysctl.c | 95 ++++- 13 files changed, 680 insertions(+), 51 deletions(-) create mode 100644 Documentation/ABI/testing/sysfs-class-console create mode 100644 Documentation/admin-guide/per-console-loglevel.rst
You forgot what changed from v1 :(
Anyway, the driver model interaction looks good to me, nice work, no objections at all.
gre gk-h
Quoted 1 line · Greg Kroah-Hartman
You forgot what changed from v1 :(
Whoops! I must have accidentally nuked it when writing the mail.
The list should be:
- Dynamically allocate struct device*
- Document sysfs attributes in Documentation/ABI/
- Use sysfs_emit() instead of sprintf() in dev sysfs files
- Remove WARN_ON() for device_add/IS_ERR(console_class)
- Remove "soon" comment for kernel.printk, wait to discuss timeline with Petr
- Fix !CONFIG_PRINTK build
- Fix device_unregister() NULL dereference if called before class setup
- Add new documentation to MAINTAINERS
Quoted 2 lines
Anyway, the driver model interaction looks good to me, nice work, no objections at all.
Great, thanks for checking it over :-)
Quoted 10 lines · Chris Down
[Once the goals of this patch are generally agreed upon, it can be split out further with more detailed changelogs if desired.]
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.
Quoted 9 lines
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.
I've had to do something similar for my systems, to allow all messages to always be logged to the pstore console while still allowing the UART console loglevel to be adjusted. I've been carrying the following pstore-specific hack for a while now. This patch set looks like it will be able to solve the problem in a generic way.
8<-------
printk: Add support for "always" consoles for pstore
We normally disable most non-critical messages to the serial console since it's very slow. However, when we have a pstore console, speed is not a problem, and we want to write all messages to the pstore regardless of the console loglevel. The console loglevel is currently shared, so disabling messages from the serial console disables them from the pstore too.
To allow both these consoles and use cases to co-exist, add a flag to allow console drivers to ask for output always, and implement support for this in the printk core. Mark the pstore console as an Always console.
We support only one always console for now.
--- fs/pstore/platform.c | 2 +- include/linux/console.h | 1 + kernel/printk/printk.c | 26 +++++++++++++++++++++----- 3 files changed, 23 insertions(+), 6 deletions(-)
fs/pstore/platform.c +1 -1
@@ -591,7 +591,7 @@ static void pstore_console_write(struct console *con, const char *s, unsigned c)static struct console pstore_console = { .name ="pstore" , .write = pstore_console_write, - .flags =CON_PRINTBUFFER |CON_ENABLED |CON_ANYTIME , + .flags =CON_PRINTBUFFER |CON_ENABLED |CON_ANYTIME |CON_ALWAYS , .index =-1 , };
include/linux/console.h +1 -0
@@ -123,6 +123,7 @@ static inline int con_debug_leave(void)#define CON_ANYTIME (16)/* Safe to call when cpu is offline */ #define CON_BRL (32)/* Used for a braille device */ #define CON_EXTENDED (64)/* Use the extended output format a la /dev/kmsg */ +#define CON_ALWAYS (128)/* Always print to this console */ struct console {char name[16 ];
kernel/printk/printk.c +21 -5
@@ -240,6 +240,9 @@ static int console_locked, console_suspended;*/ static struct console *exclusive_console; +/* Always print to this console, regardless of loglevel */ +static struct console *always_console; +/* * Array of consoles built from command line options (console=) */
@@ -1537,7 +1540,7 @@ SYSCALL_DEFINE3(syslog, int, type, char __user *, buf, int, len)*/ static void call_console_drivers (int level,const char *ext_text,size_t ext_len, -const char *text,size_t len) +const char *text,size_t len,bool suppress) {struct console *con;
@@ -1547,6 +1550,8 @@ static void call_console_drivers(int level,return ;for_each_console (con) { +if (suppress && con != always_console) +continue ;if (exclusive_console && con != exclusive_console)continue ;if (!(con->flags &CON_ENABLED ))
@@ -2265,6 +2270,7 @@ static inline int can_use_console(void)static void console_cont_flush (char *text,size_t size) {unsigned long flags; +bool suppress;size_t len;raw_spin_lock_irqsave (&logbuf_lock, flags);
@@ -2272,7 +2278,8 @@ static void console_cont_flush(char *text, size_t size)if (!cont.len) goto out; -if (suppress_message_printing (cont.level)) { + suppress =suppress_message_printing (cont.level); +if (suppress && !always_console) { cont.cons = cont.len;if (cont.flushed) cont.len =0 ;
@@ -2290,7 +2297,7 @@ static void console_cont_flush(char *text, size_t size) len =cont_print_text (text, size);raw_spin_unlock (&logbuf_lock);stop_critical_timings (); -call_console_drivers (cont.level,NULL ,0 , text, len); +call_console_drivers (cont.level,NULL ,0 , text, len, suppress);start_critical_timings ();local_irq_restore (flags);return ;
@@ -2361,6 +2368,7 @@ void console_unlock(void)for (;;) {struct printk_log *msg;size_t ext_len =0 ; +bool suppress;size_t len;int level;
@@ -2386,8 +2394,9 @@ void console_unlock(void) msg =log_from_idx (console_idx); level = msg->level; + suppress =suppress_message_printing (level);if ((msg->flags &LOG_NOCONS ) || -suppress_message_printing (level)) { + (suppress && !always_console)) {/* * Skip record we have buffered and already printed * directly to the console when we received it, and
@@ -2419,7 +2428,7 @@ void console_unlock(void)raw_spin_unlock (&logbuf_lock);stop_critical_timings ();/* don't trace print latency */ -call_console_drivers (level, ext_text, ext_len, text, len); +call_console_drivers (level, ext_text, ext_len, text, len, suppress);start_critical_timings ();local_irq_restore (flags);
@@ -2718,6 +2727,10 @@ void register_console(struct console *newcon)*/ exclusive_console = newcon; } + +if (!always_console && (newcon->flags &CON_ALWAYS )) + always_console = newcon; +console_unlock ();console_sysfs_notify ();
@@ -2783,6 +2796,9 @@ int unregister_console(struct console *console)if (console_drivers !=NULL && console->flags &CON_CONSDEV ) console_drivers->flags |=CON_CONSDEV ; +if (always_console == console) + always_console =NULL ; + console->flags &= ~CON_ENABLED ;console_unlock ();console_sysfs_notify ();
Signature · 1 line
2.28.0
Hi Vincent,
Quoted 5 lines · Vincent Whitchurch
I've had to do something similar for my systems, to allow all messages to always be logged to the pstore console while still allowing the UART console loglevel to be adjusted. I've been carrying the following pstore-specific hack for a while now. This patch set looks like it will be able to solve the problem in a generic way.
Thanks, nice to hear about other usecases :-) Yes, this should allow this generically for any console, including pstore.
Just to update on v3: I planned to quickly get it out today but it turns out that there's some work needed to add compatibility for John's threaded console printing patches for 5.19.
I'll add support for threaded console printing and send v3 when I'm back from being away at the beginning of July. In the meantime, any further feedback on the general concept is welcome. :-)
Petr Mladek
maintainerdesign: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
In reply to Chris DownQuoted 7 lines · Chris Down
Documentation/admin-guide/per-console-loglevel.rst new file +4
-0@@ -0,0 +1,116 @@ +.. SPDX-License-Identifier: GPL-2.0 + +.. _per_console_loglevel: +
Documentation/admin-guide/per-console-loglevel.rst line 14
Quoted 10 lines
Documentation/admin-guide/per-console-loglevel.rst new file +10
-0+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 signiifcant
s/signiifcant/significant/
Quoted 13 lines
Documentation/admin-guide/per-console-loglevel.rst new file +13
-0+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 +-------- +
Documentation/admin-guide/per-console-loglevel.rst line 37
Quoted 10 lines
Documentation/admin-guide/per-console-loglevel.rst new file +10
-0+In order to allow tuning this, the following controls exist: + +Global +~~~~~~ + +In order of authority: + +* ``ignore_loglevel`` on the kernel command line: Emit all messages. Cannot be + disabled without restarting the kernel. All other controls are ignored if + this is present.
It actually can be enabled/disabled at runtime by
echo 0/1 >/sys/module/printk/parameters/ignore_loglevel
Documentation/admin-guide/per-console-loglevel.rst line 39
Quoted 2 lines
Documentation/admin-guide/per-console-loglevel.rst new file +2
-0+* ``loglevel=...`` on the kernel command line: Equivalent to sysctl + ``kernel.default_console_loglevel``.
This does not fit the 'In order of authority' because it can be overridden with per-console loglevel or force_console_loglevel
Documentation/admin-guide/per-console-loglevel.rst line 41
Quoted 2 lines
Documentation/admin-guide/per-console-loglevel.rst new file +2
-0+* ``kernel.minimum_console_loglevel`` sysctl: Clamp all consoles to emit + messages beyond this loglevel.
This is a limit. It does not really set any loglevel.
Documentation/admin-guide/per-console-loglevel.rst line 47
Quoted 7 lines
Documentation/admin-guide/per-console-loglevel.rst new file +6
-0+* ``kernel.force_console_loglevel`` sysctl: Force all consoles to the given + loglevel. If this value is lower than ``kernel.minimum_console_loglevel``, + ``kernel.minimum_console_loglevel`` is respected. Can also be set to the + special value "unset" which removes any existing forced level. +* ``kernel.default_console_loglevel`` sysctl: The default console loglevel if + there is no local loglevel for the console, and
"local loglevel" is confusing. Better might be "console-specific loglevel".
Documentation/admin-guide/per-console-loglevel.rst line 50
Quoted 3 lines
Documentation/admin-guide/per-console-loglevel.rst new file +3
-0+ ``kernel.force_console_loglevel`` is unset. If this value is lower than + ``kernel.minimum_console_loglevel``, ``kernel.minimum_console_loglevel`` is + respected.
Hmm, "default" is a bit confusing. My view is that default is the built-in value defined as CONSOLE_LOGLEVEL_DEFAULT. Any value defined on the command line or at runtime is not default.
I see, "default" has another meaning here. It means that it is the loglevel that will used when there is no explicit console-specific loglevel.
See below for another proposal.
Documentation/admin-guide/per-console-loglevel.rst line 55
Quoted 5 lines
Documentation/admin-guide/per-console-loglevel.rst new file +5
-0+* ``kernel.default_console_loglevel`` sysctl: The default console loglevel if + there is no local loglevel for the console, and + ``kernel.force_console_loglevel`` is unset. If this value is lower than + ``kernel.minimum_console_loglevel``, ``kernel.minimum_console_loglevel`` is + forced.
``kernel.default_console_loglevel`` description is repeated twice.
Quoted 20 lines
Documentation/admin-guide/per-console-loglevel.rst new file +20
-0+* ``kernel.default_message_loglevel`` sysctl: The default loglevel to send + messages at if they are sent with no explicit loglevel. + +The default value for ``kernel.default_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 local 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: +
Documentation/admin-guide/per-console-loglevel.rst line 85
Quoted 10 lines
Documentation/admin-guide/per-console-loglevel.rst new file +10
-0+ * ``local``: The console-specific loglevel is in effect. + * ``global``: The global default loglevel + (``kernel.default_console_loglevel``) is in effect. Set a console-specific + loglevel to override it. + * ``forced``: The global forced loglevel (``kernel.force_console_loglevel``) + is in effect. Write "unset" to ``kernel.force_console_loglevel`` to disable + it. + * ``minimum``: The global minimum loglevel + (``kernel.minimum_console_loglevel``) is in effect. Set a higher + console-specific loglevel to override it.
This is confusing. It might be because I am not a native speaker. It sounds like a higher console-specific loglevel might update (override) the minimum value.
A better explanation is that it is a limit. Neither the global nor the per-console loglevel could be set below this value.
Documentation/admin-guide/per-console-loglevel.rst line 94
Quoted 9 lines
Documentation/admin-guide/per-console-loglevel.rst new file +9
-0+ * ``forced_minimum``: The global minimum loglevel + (``kernel.minimum_console_loglevel``) is in effect. Even if the local + console-specific loglevel is higher, it is in effect because the global + forced loglevel (``kernel.force_console_loglevel``) is present, but is + below ``kernel.minimum_console_loglevel``. Write "unset" to + ``kernel.force_console_loglevel`` to disable the forcing, and make sure + ``kernel.minimum_console_loglevel`` is below the local console loglevel + if you want the per-console loglevel to take effect. + console-specific loglevel to override it.
IMHO, this makes things too complicated. A better solution is to do not allow to set any log level below this limit in the first place.
Documentation/admin-guide/per-console-loglevel.rst line 106
Quoted 12 lines
Documentation/admin-guide/per-console-loglevel.rst new file +11
-0+ * ``ignore_loglevel``: ``ignore_loglevel`` was specified on the kernel + command line. Restart without it to use other controls. + +* ``enabled`` (r): Whether the console is enabled. +* ``loglevel`` (rw): The local 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. +Deprecated +~~~~~~~~~~ + +* ``syslog(SYSLOG_ACTION_CONSOLE_*)``: This sets
Why does it use "_*"? It looks like the entire syslog interface is obsolete. But this patch affects only three actions: ON, OFF, LEVEL.
Documentation/admin-guide/per-console-loglevel.rst line 109
Quoted 3 lines
Documentation/admin-guide/per-console-loglevel.rst new file +3
-0+ ``kernel.force_console_loglevel``. It is unaware of per-console loglevel + semantics and is not recommended. A warning will be emitted if it is used + while local loglevels are in effect.
Do we really want to obsolete it? It might be enough to say that it works as force_console_loglevel.
Documentation/admin-guide/per-console-loglevel.rst line 114
Quoted 5 lines
Documentation/admin-guide/per-console-loglevel.rst new file +5
-0+* ``kernel.printk`` sysctl: this takes four values, setting + ``kernel.force_console_loglevel``, ``kernel.default_message_loglevel``, + ``kernel.minimum_console_loglevel``, and ``kernel.default_console_loglevel`` + respectively. The interface is generally considered to quite confusing, and + is unaware of per-console loglevel semantics.
OK, I know that you made it according to the proposal that I sent you in a private mail. I think that there are several good ideas. But some parts are still too complicated or weird.
The main principle must be really simple so that people could understand it.
I have one idea. A big difference might be replacing "force_console_loglevel" value with "ignore_per_console_loglevel" parameter.
I propose the following:
--- cut ---
Each kernel message has defined a log level. It defines the purpose and importance of the messages. The log levels are:
+ 0 emergency - system is unusable
+ 1 alert - action must be taken immediately
+ 2 critical conditions
...
(the above is based on include/linux/kern_levels.h)
Consoles can have vastly different latencies and throughputs.... (explanation why people want to see only the most important messages on consoles.)
The limit for messages that reach the console is defined by a global console loglevel value. It might be optionally overridden for a particular console by a console_specific value.
--- cut ---
The above is the explanation of the basic approach. Especially the last paragraph is important. It describes the basic logic a very simple way. Anything else are details.
The description of the details:
--- cut ---
There are many ways how the console loglevels can be modified. The global value might be set by:
+ CONFIG_CONSOLE_LOGLEVEL_DEFAULT at built time.
+ "loglevel=" or "quiet" kernel parameters at boot time.
+ sysctl kernel.console_loglevel at runtime
The console-specific loglevel might be set by:
+ "console=device,options/loglevel" kernel parameter at boot time
+ echo <level> > /sys/class/console/<console>/loglevel at runtime
The console loglevel parameters might also be ignored by:
+ "ignore_loglevel" kernel parameter allows to ignore both the global and console specific loglevel values. As a result, all messages are shown on all consoles.
+ "ignore_per_console_loglevel" kernel parameter allows to ignore console specific loglevels. The global loglevel is used instead.
Both parameters might be switched also at runtime by
echo <0/1> >/sys/module/printk/parameters/<parameter>
There is also a hard limit that prevents setting either the global or the console specific loglevel below this value. It can be set by:
+ CONFIG_CONSOLE_LOGLEVEL_MIN at build time
+ sysctl kernel.console_minimal_loglevel at runtime
--- cut ---
The main logic difference is that we do not have 4 loglevel values (global,per-console,minimum,forced) and complicated rules which one will be used in the end.
Instead we have only two values: global, and optional console-specific. 2nd one is used when and only when defined. Plus one or both might ignored when the "ignore*" parameter is used.
Everything else are ways how to set the values at build/boot/run time.
How does it sounds, please?
PS: I am sorry for the late review. I needed some bigger window to
be able to think about it. All the previous attempts made the logic really hard to understand. The following table from your code shows it nicely:
static const char *const loglevel_source_names[] = {
[LLS_GLOBAL] = "global",
[LLS_LOCAL] = "local",
[LLS_FORCED] = "forced",
[LLS_MINIMUM] = "minimum",
[LLS_FORCED_MINIMUM] = "forced_minimum",
[LLS_IGNORE_LOGLEVEL] = "ignore_loglevel",
};It looks scary. Just imagine a system administrator that sees one of these values and want to change it somehow. They would need to understand what it means and how to move the state into the desired one without breaking other consoles.
John Ogness
maintainerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 3 lines · Petr Mladek
The console-specific loglevel might be set by:
+ "console=device,options/loglevel" kernel parameter at boot time
I ask if we avoid the use of "/loglevel" and instead use a generic scheme of:
console=device,option,option,option
Of course, it would mean that the type of option would need to be specified. Something like:
console=ttyS0,115200n8,loglevel=3
The reason why I make such a request is because I would like to be able to support disabling threading for certain consoles. Something like:
console=ttyS0,115200n8,nothread
or when we have atomic consoles that we can specify that they are always used with a "sync" option:
console=ttyS0,115200n8,sync
This is not the time to discuss what those strings should be. The point is that we should use a syntax that allows adding more options for the future.
Linus already [0] showed some approval to this method of option extending as I suggested the "mute" option to have consoles keep quiet.
John Ogness
P.S. FWIW, I think this is a nice feature. I even mentioned it in my LPC2019 printk talk, as there were previous efforts [1] to get this feature implemented.
[0] https://lore.kernel.org/lkml/CAHk-=wif0QueN8ovkm_x7TsOgOHjRrOa4wU-zHgBP=FTAnzvNA@mail.gmail.com
Petr Mladek
maintainerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 8 lines · John Ogness
Quoted 3 lines · Petr Mladek
The console-specific loglevel might be set by:
+ "console=device,options/loglevel" kernel parameter at boot time
I ask if we avoid the use of "/loglevel" and instead use a generic scheme of:
Quoted 6 lines
console=device,option,option,option
Of course, it would mean that the type of option would need to be specified. Something like:
console=ttyS0,115200n8,loglevel=3
I like this. It is longer but it makes the meaning very obvious.
I just think about using ':' instead of '=' to distinguish the assignment of outer 'console' vs the inner 'loglevel' parameters.
It seems to be used in some cases, for example, for ca_keys, crashkernel, drm.edid_firmware, efi_fake_mem. Even earlyprintk uses it for bus:device.function.
Quoted 9 lines
The reason why I make such a request is because I would like to be able to support disabling threading for certain consoles. Something like:
console=ttyS0,115200n8,nothread
or when we have atomic consoles that we can specify that they are always used with a "sync" option:
console=ttyS0,115200n8,sync
Good point.
Best Regards,
Petr
Sergey Senozhatsky
reviewerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 9 lines · Petr Mladek
Quoted 8 lines · John Ogness
Quoted 3 lines · Petr Mladek
The console-specific loglevel might be set by:
+ "console=device,options/loglevel" kernel parameter at boot time
I ask if we avoid the use of "/loglevel" and instead use a generic scheme of:
Quoted 8 lines
Quoted 6 lines
console=device,option,option,option
Of course, it would mean that the type of option would need to be specified. Something like:
console=ttyS0,115200n8,loglevel=3
I like this. It is longer but it makes the meaning very obvious.
Looks beautiful.
Re: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
In reply to Petr MladekQuoted 6 lines · Petr Mladek
Quoted 4 lines
Of course, it would mean that the type of option would need to be specified. Something like:
console=ttyS0,115200n8,loglevel=3
I like this. It is longer but it makes the meaning very obvious.
Yes, this looks good to me and I'll implement it for v3. Thanks!
Quoted 2 lines
I just think about using ':' instead of '=' to distinguish the assignment of outer 'console' vs the inner 'loglevel' parameters.
Agreed, I'll use ":".
Re: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
In reply to Petr MladekThanks for the detailed feedback! Anything not explicitly discussed is acked for v3. :-)
Quoted 7 lines · Petr Mladek
Documentation/admin-guide/per-console-loglevel.rst line 85
Quoted 3 lines
Documentation/admin-guide/per-console-loglevel.rst new file +3
-0+ * ``minimum``: The global minimum loglevel + (``kernel.minimum_console_loglevel``) is in effect. Set a higher + console-specific loglevel to override it.This is confusing. It might be because I am not a native speaker. It sounds like a higher console-specific loglevel might update (override) the minimum value.
Ah, yes. I think this higher/lower confusion also has something to do with the historic artefacts of using lower-numbered integers to represent higher-priority messages.
Quoted 3 lines
A better explanation is that it is a limit. Neither the global nor the per-console loglevel could be set below this value.
Yes, that sounds better. :-)
Quoted 10 lines
Documentation/admin-guide/per-console-loglevel.rst line 94
Quoted 9 lines
Documentation/admin-guide/per-console-loglevel.rst new file +9
-0+ * ``forced_minimum``: The global minimum loglevel + (``kernel.minimum_console_loglevel``) is in effect. Even if the local + console-specific loglevel is higher, it is in effect because the global + forced loglevel (``kernel.force_console_loglevel``) is present, but is + below ``kernel.minimum_console_loglevel``. Write "unset" to + ``kernel.force_console_loglevel`` to disable the forcing, and make sure + ``kernel.minimum_console_loglevel`` is below the local console loglevel + if you want the per-console loglevel to take effect. + console-specific loglevel to override it.
Quoted 2 lines
IMHO, this makes things too complicated. A better solution is to do not allow to set any log level below this limit in the first place.
Hmm, how should we then handle the case that you have set the per-console loglevel to 3 and minimum_console_loglevel later gets changed to 5?
We had this problem when designing cgroup v2 as well, for example in cases where a child requests a higher memory protection than can be afforded by the parent, or where a child sets a higher memory limit than a parent specifies. We went back and forth and eventually settled on allowing these, because the alternatives seemed difficult to reason about or unnecessarily inflexible.
From the per-console loglevel side, one option is to return ERANGE or EINVAL on values we know won't be honoured when setting the per-console loglevel. The problem with that is that it doesn't allow to specify a "desired" limit in case the external factors (in this case, the minimum loglevel) change. This is even more difficult to reason about in our case because the minimum loglevel may be changed dynamically outside of user control.
Another is to disallow setting the minimum loglevel without first resetting consoles which are above the value that is desired to be set, but this seems really cumbersome, and again it doesn't account for cases like panic() and elsewhere where we blindly change it anyway.
Maybe you have another idea about how it should work in the case that the minimum loglevel would take precedence over an existing loglevel?
Quoted 8 lines
Quoted 8 lines
Documentation/admin-guide/per-console-loglevel.rst new file +7
-0+ * ``ignore_loglevel``: ``ignore_loglevel`` was specified on the kernel + command line. Restart without it to use other controls. + +* ``enabled`` (r): Whether the console is enabled. +* ``loglevel`` (rw): The local 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.
Quoted 7 lines
Documentation/admin-guide/per-console-loglevel.rst line 106
Quoted 4 lines
Documentation/admin-guide/per-console-loglevel.rst new file +4
-0+Deprecated +~~~~~~~~~~ + +* ``syslog(SYSLOG_ACTION_CONSOLE_*)``: This setsWhy does it use "_*"? It looks like the entire syslog interface is obsolete. But this patch affects only three actions: ON, OFF, LEVEL.
Not totally sure I know what you mean -- SYSLOG_ACTION_CONSOLE_* limits it to those, no?
% git grep -ho 'SYSLOG_ACTION_CONSOLE_[A-Z0-9]\+' | sort -u
SYSLOG_ACTION_CONSOLE_LEVEL
SYSLOG_ACTION_CONSOLE_OFF
SYSLOG_ACTION_CONSOLE_ONQuoted 6 lines
Documentation/admin-guide/per-console-loglevel.rst line 109
Quoted 3 lines
Documentation/admin-guide/per-console-loglevel.rst new file +3
-0+ ``kernel.force_console_loglevel``. It is unaware of per-console loglevel + semantics and is not recommended. A warning will be emitted if it is used + while local loglevels are in effect.Do we really want to obsolete it? It might be enough to say that it works as
force_console_loglevel.
That's also fine -- my only concern with syslog() is that it's not very explicit about what will happen to consoles with a per-console loglevel set.
That said, once this is merged I suppose we can make it more clear in downstream consumers like dmesg -n, so not a big issue either way. :-)
Quoted 9 lines
I have one idea. A big difference might be replacing "
force_console_loglevel" value with "ignore_per_console_loglevel" parameter.[...]
The main logic difference is that we do not have 4 loglevel values (global,per-console,minimum,forced) and complicated rules which one will be used in the end.
Quoted 7 lines
Instead we have only two values: global, and optional console-specific. 2nd one is used when and only when defined. Plus one or both might ignored when the "ignore*" parameter is used.
Everything else are ways how to set the values at build/boot/run time.
How does it sounds, please?
This sounds pretty good! It had bothered me that we have these two default/forced options, and I think this does make things simpler.
Thanks for your detailed feedback! I will incorporate it into v3.
Petr Mladek
maintainerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 7 lines · Chris Down
Quoted 2 lines · Petr Mladek
IMHO, this makes things too complicated. A better solution is to do not allow to set any log level below this limit in the first place.
Hmm, how should we then handle the case that you have set the per-console loglevel to 3 and
minimum_console_loglevellater gets changed to 5?
Quoted 6 lines
We had this problem when designing cgroup v2 as well, for example in cases where a child requests a higher memory protection than can be afforded by the parent, or where a child sets a higher memory limit than a parent specifies. We went back and forth and eventually settled on allowing these, because the alternatives seemed difficult to reason about or unnecessarily inflexible.
I see.
Quoted 7 lines
From the per-console loglevel side, one option is to return ERANGE or EINVAL on values we know won't be honoured when setting the per-console loglevel. The problem with that is that it doesn't allow to specify a "desired" limit in case the external factors (in this case, the minimum loglevel) change. This is even more difficult to reason about in our case because the minimum loglevel may be changed dynamically outside of user control.
Quoted 7 lines
Another is to disallow setting the minimum loglevel without first resetting consoles which are above the value that is desired to be set, but this seems really cumbersome, and again it doesn't account for cases like
panic()and elsewhere where we blindly change it anyway.Maybe you have another idea about how it should work in the case that the minimum loglevel would take precedence over an existing loglevel?
minimum_console_loglevel is currently used only in syslog interface. It is ignored when the levels are set using sysctl.
IMHO, the reason is that sysctl might eventually get called even with
less privileged user.
I would keep this behavior. I mean that a change of minimum_console_loglevel would not affect other values immediately. It will be used to crop the value when anyone wants to change the global loglevel via syslog later.
Well, it would make sense to crop the global or per-console loglevels even when they are later changed via the new sysctl or sysfs interface. It would be a limit for less privileged users.
Maybe, it is over-engineered. I wonder if anyone really uses the minimum level in practice.
Quoted 16 lines
Quoted 8 lines
Quoted 8 lines
Documentation/admin-guide/per-console-loglevel.rst new file +7
-0+ * ``ignore_loglevel``: ``ignore_loglevel`` was specified on the kernel + command line. Restart without it to use other controls. + +* ``enabled`` (r): Whether the console is enabled. +* ``loglevel`` (rw): The local 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.Quoted 7 lines
Documentation/admin-guide/per-console-loglevel.rst line 106
Quoted 4 lines
Documentation/admin-guide/per-console-loglevel.rst new file +4
-0+Deprecated +~~~~~~~~~~ + +* ``syslog(SYSLOG_ACTION_CONSOLE_*)``: This setsWhy does it use "_*"? It looks like the entire syslog interface is obsolete. But this patch affects only three actions: ON, OFF, LEVEL.
Quoted 7 lines
Not totally sure I know what you mean -- SYSLOG_ACTION_CONSOLE_* limits it to those, no?
% git grep -ho 'SYSLOG_ACTION_CONSOLE_[A-Z0-9]\+' | sort -u SYSLOG_ACTION_CONSOLE_LEVEL SYSLOG_ACTION_CONSOLE_OFF SYSLOG_ACTION_CONSOLE_ON
I see. I missed that the other SYSLOG_ACTIONs do not have the "_CONSOLE". Forget about it.
Quoted 4 lines
Quoted 4 lines
Quoted 3 lines
Documentation/admin-guide/per-console-loglevel.rst new file +3
-0+ ``kernel.force_console_loglevel``. It is unaware of per-console loglevel + semantics and is not recommended. A warning will be emitted if it is used + while local loglevels are in effect.
Quoted 8 lines
Quoted 2 lines
Do we really want to obsolete it? It might be enough to say that it works as
force_console_loglevel.That's also fine -- my only concern with
syslog()is that it's not very explicit about what will happen to consoles with a per-console loglevel set.That said, once this is merged I suppose we can make it more clear in downstream consumers like
dmesg -n, so not a big issue either way. :-)
Honestly, I consider syslog as a legacy code. It supports only one reader. A better way to read the messages is /dev/kmsg and dmesg uses it be default now.
I am not sure if people/admins really use dmesg to change the console loglevel. IMHO, sysctl or sysfs should be the preferred way.
I think that it is enough to make the behavior clear in the documentation.
Best Regards,
Petr
Petr Mladek
maintainerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 43 lines · Petr Mladek
Quoted 7 lines · Chris Down
Quoted 2 lines · Petr Mladek
IMHO, this makes things too complicated. A better solution is to do not allow to set any log level below this limit in the first place.
Hmm, how should we then handle the case that you have set the per-console loglevel to 3 and
minimum_console_loglevellater gets changed to 5?Quoted 6 lines
We had this problem when designing cgroup v2 as well, for example in cases where a child requests a higher memory protection than can be afforded by the parent, or where a child sets a higher memory limit than a parent specifies. We went back and forth and eventually settled on allowing these, because the alternatives seemed difficult to reason about or unnecessarily inflexible.
I see.
Quoted 7 lines
From the per-console loglevel side, one option is to return ERANGE or EINVAL on values we know won't be honoured when setting the per-console loglevel. The problem with that is that it doesn't allow to specify a "desired" limit in case the external factors (in this case, the minimum loglevel) change. This is even more difficult to reason about in our case because the minimum loglevel may be changed dynamically outside of user control.
Quoted 7 lines
Another is to disallow setting the minimum loglevel without first resetting consoles which are above the value that is desired to be set, but this seems really cumbersome, and again it doesn't account for cases like
panic()and elsewhere where we blindly change it anyway.Maybe you have another idea about how it should work in the case that the minimum loglevel would take precedence over an existing loglevel?
minimum_console_loglevelis currently used only in syslog interface. It is ignored when the levels are set using sysctl.IMHO, the reason is that sysctl might eventually get called even with
less privileged user.I would keep this behavior. I mean that a change of
minimum_console_loglevelwould not affect other values immediately. It will be used to crop the value when anyone wants to change the global loglevel via syslog later.
Quoted 7 lines
Well, it would make sense to crop the global or per-console loglevels even when they are later changed via the new sysctl or sysfs interface. It would be a limit for less privileged users.
Maybe, it is over-engineered. I wonder if anyone really uses the minimum level in practice.
I checked the history:
1. The possibility to change "console_loglevel" was added in 0.99.13k, 1992. The syslog syscall was the only way to change the value at runtime at that time.
2. MINIMUM_CONSOLE_LOGLEVEL was added in 1.3.37, 1995 It was hardcoded at that time.
3. minimum_console_loglevel was exported via sysctl in 2.1.32, between 1996-1999. This version added the sysctl interface for all 4 values:
console_loglevel, minimum_console_loglevel, default_console_loglevel, default_message_loglevel. Before it was possible to change only console_loglevel via the syslog syscall.
sysctl allows to set all four values to any value. It does not check if they make any sense. And it does not check if console_loglevel is above minimum_console_loglevel. Only the syslog syscall checks minimum_console_loglevel.
I guess that nobody really though how the interface could be used. It just made the four "configurable" values accessible.
IMHO, it confirms the theory that the minimum value should prevent less privileged users to change the loglevel below this minimum. And I would do it as I suggested. I mean that minimum_console_loglevel will be used only when anyone tries to change the global
or per-console loglevel.
It would make sense to return -EINVAL when anyone wants to set loglevel below the minimum value via sysctl or sysfs interface.
I suggested to just crop the value yesterday. It is what the syslog sycall does. But I think that it is actually quite ugly and we could do better in the new (more modern) interface.
Best Regards,
Petr
Re: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Thanks for writing this up, this is very helpful.
Ok, I will incorporate the EINVAL return for sysctl in a separate patch first, and then add the new sysfs one to the existing changes for v3. :-)
Re: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 1 line · Chris Down
Ok, I will incorporate the EINVAL return for sysctl in a separate patch first, and then add the new sysfs one to the existing changes for v3. :-)
Thinking more about this, I will probably not change the existing kernel.printk semantics to return EINVAL, since it could silently(ish) cause regressions for existing misconfigured systems on boot. I'll just add the clamps to the new controls.
Petr Mladek
maintainerRe: design: was: Re: [RFC PATCH v2] printk: console: Allow each console to have its own loglevel
Quoted 9 lines · Chris Down
Quoted 3 lines · Chris Down
Ok, I will incorporate the EINVAL return for sysctl in a separate patch first, and then add the new sysfs one to the existing changes for v3. :-)
Thinking more about this, I will probably not change the existing kernel.printk semantics to return EINVAL, since it could silently(ish) cause regressions for existing misconfigured systems on boot. I'll just add the clamps to the new controls.
I guess that you are talking about the obsoleted sysctl 'kernel.printk' that has 4 values. And about syslog behavior. I agree that changing he behavior might be risky.
But I think that we should return EINVAL in the newly added interface. IMHO, people should know when the entered value can't be used instead of silently changing it.
When talking about the new interface. I would either do not create /proc/sys/kernel/minimum_console_loglevel or I would make it read only. IMHO, this value was supposed to be a built in value and was exported without much thinking. I guess that only few people know what it really does and it is better to hide it.
Best Regards,
Petr