printk: add per console loglevel
Subsystems (6)
PATCH 1/1 printk: add per console loglevel
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6
This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
--- Documentation/kernel-parameters.txt | 24 ++++++++++++++++++------ include/linux/console.h | 1 + kernel/printk/console_cmdline.h | 9 +++++---- kernel/printk/printk.c | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 11 deletions(-)
Documentation/kernel-parameters.txt +18 -6
@@ -696,30 +696,42 @@ bytes respectively. Such letter suffixes can also be entirely omitted. console= [KNL] Output console device and options. - tty<n> Use the virtual console device <n>. + tty<n>[,llX] Use the virtual console device <n>. - ttyS<n>[,options] - ttyUSB0[,options] + ttyS<n>[,options][,llX] + ttyUSB0[,options][,llX] Use the specified serial port. The options are of the form "bbbbpnf", 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". + "llX" explained below, + See Documentation/serial-console.txt for more information. See Documentation/networking/netconsole.txt for an alternative. - uart[8250],io,<addr>[,options] - uart[8250],mmio,<addr>[,options] + uart[8250],io,<addr>[,options][,llX] + uart[8250],mmio,<addr>[,options][,llX] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. The options are the same as for ttyS, above. - hvc<n> Use the hypervisor console device <n>. This is for + + "llX" explained below, + + hvc<n>[,llX] + Use the hypervisor console device <n>. This is for both Xen and PowerPC hypervisors. + "llX" is used to define the loglevel per console. The "X" + defines the loglevel number for this console. The usage + is similar to the "loglevel=" option, and the effect is + the same only per console. The "loglevel=" option takes + precedence of this option. + If the device connected to the port is not a TTY but a braille device, prepend "brl," before the device type, for instance console=brl,ttyS0
include/linux/console.h +1 -0
@@ -118,6 +118,7 @@ static inline int con_debug_leave(void)struct console {char name[16 ]; +int loglevel;void (*write)(struct console *,const char *,unsigned );int (*read)(struct console *,char *,unsigned );struct tty_driver *(*device)(struct console *,int *);
kernel/printk/console_cmdline.h +5 -4
@@ -3,11 +3,12 @@struct console_cmdline { -char name[8 ];/* Name of the driver */ -int index;/* Minor dev. to use */ -char *options;/* Options for the driver */ +char name[8 ];/* Name of the driver */ +int index;/* Minor dev. to use */ +int loglevel;/* Log level for this console */ +char *options;/* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE -char *brl_options;/* Options for braille driver */ +char *brl_options;/* Options for braille driver */ #endif };
kernel/printk/printk.c +36 -1
@@ -1414,6 +1414,9 @@ static void call_console_drivers(int level, const char *text, size_t len)if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))continue ; +if (con->loglevel && !ignore_loglevel && + level >= con->loglevel) +continue ; con->write (con, text, len); } }
@@ -1925,6 +1928,33 @@ asmlinkage __visible void early_printk(const char *fmt, ...) }#endif + +char *setup_per_console_loglevel (struct console_cmdline *con,char *options) +{ +int size = options ?strlen (options) :0 ; + +if (size >=3 && + options[size -3 ] =='l' && + options[size -2 ] =='l' && + options[size -1 ] >='1' && options[size -1 ] <='9' ) { + con->loglevel = options[size -1 ] -'0' ; + +/* Catch if the user added a comma after some serial console +* options, +* i.e. console=ttyS0,9600n8,ll3 +* the first comma is gone at this point, but we need to delete +* the second one. +*/ +if (size >3 && options[size -4 ] ==',' ) + options[size -4 ] =0 ; +else + options[size -3 ] =0 ; + }else + con->loglevel =0 ; + +return options; +} +static int __add_preferred_console (char *name,int idx,char *options,char *brl_options) {
@@ -1949,12 +1979,15 @@ static int __add_preferred_console(char *name, int idx, char *options,if (!brl_options) selected_console = i;strlcpy (c->name, name,sizeof (c->name)); - c->options = options; + + c->options =setup_per_console_loglevel (c, options); +braille_set_options (c, brl_options); c->index = idx;return 0 ; } +/* * Set up a console. Called via do_early_param() in init/main.c * for each "console=" parameter in the boot command line.
@@ -2478,6 +2511,8 @@ void register_console(struct console *newcon)if (newcon->setup && newcon->setup (newcon, console_cmdline[i].options) !=0 )break ; + + newcon->loglevel = c->loglevel; newcon->flags |=CON_ENABLED ; newcon->index = c->index;if (i == selected_console) {
Signature · 1 line
1.9.1
Quoted 10 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
What would be the best way to make these per-console loglevels configurable at runtime? dmesg -n $LEVEL only affects the global limit.
One drawback to letting global loglevel have precedence is that all consoles that should not get detailed log messages need to have their loglevel explicitly lowered and it's not possible to have one console forced to show more than the global loglevel.
An approach I would prefer is to have all consoles follow global loglevel except when something different had been explicitly requested for them.
This way a single console can be added later on (e.g. netconsole) and set to pass through debug messages without affecting anyone else.
Bruno
Quoted 168 lines
Signed-off-by Daniel Walker <[email protected]>--- Documentation/kernel-parameters.txt | 24 ++++++++++++++++++------ include/linux/console.h | 1 + kernel/printk/console_cmdline.h | 9 +++++---- kernel/printk/printk.c | 37 ++++++++++++++++++++++++++++++++++++- 4 files changed, 60 insertions(+), 11 deletions(-)Documentation/kernel-parameters.txt +18
-6@@ -696,30 +696,42 @@ bytes respectively. Such letter suffixes can also be entirely omitted. console= [KNL] Output console device and options. - tty<n> Use the virtual console device <n>. + tty<n>[,llX] Use the virtual console device <n>. - ttyS<n>[,options] - ttyUSB0[,options] + ttyS<n>[,options][,llX] + ttyUSB0[,options][,llX] Use the specified serial port. The options are of the form "bbbbpnf", 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". + "llX" explained below, + See Documentation/serial-console.txt for more information. See Documentation/networking/netconsole.txt for an alternative. - uart[8250],io,<addr>[,options] - uart[8250],mmio,<addr>[,options] + uart[8250],io,<addr>[,options][,llX] + uart[8250],mmio,<addr>[,options][,llX] Start an early, polled-mode console on the 8250/16550 UART at the specified I/O port or MMIO address, switching to the matching ttyS device later. The options are the same as for ttyS, above. - hvc<n> Use the hypervisor console device <n>. This is for + + "llX" explained below, + + hvc<n>[,llX] + Use the hypervisor console device <n>. This is for both Xen and PowerPC hypervisors. + "llX" is used to define the loglevel per console. The "X" + defines the loglevel number for this console. The usage + is similar to the "loglevel=" option, and the effect is + the same only per console. The "loglevel=" option takes + precedence of this option. + If the device connected to the port is not a TTY but a braille device, prepend "brl," before the device type, for instance console=brl,ttyS0include/linux/console.h +1
-0@@ -118,6 +118,7 @@ static inline int con_debug_leave(void)struct console {char name[16 ]; +int loglevel;void (*write)(struct console *,const char *,unsigned );int (*read)(struct console *,char *,unsigned );struct tty_driver *(*device)(struct console *,int *);kernel/printk/console_cmdline.h +5
-4@@ -3,11 +3,12 @@struct console_cmdline { -char name[8 ];/* Name of the driver */ -int index;/* Minor dev. to use */ -char *options;/* Options for the driver */ +char name[8 ];/* Name of the driver */ +int index;/* Minor dev. to use */ +int loglevel;/* Log level for this console */ +char *options;/* Options for the driver */ #ifdef CONFIG_A11Y_BRAILLE_CONSOLE -char *brl_options;/* Options for braille driver */ +char *brl_options;/* Options for braille driver */ #endif };kernel/printk/printk.c +36
-1@@ -1414,6 +1414,9 @@ static void call_console_drivers(int level, const char *text, size_t len)if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))continue ; +if (con->loglevel && !ignore_loglevel && + level >= con->loglevel) +continue ; con->write (con, text, len); } }@@ -1925,6 +1928,33 @@ asmlinkage __visible void early_printk(const char *fmt, ...) }#endif + +char *setup_per_console_loglevel (struct console_cmdline *con,char *options) +{ +int size = options ?strlen (options) :0 ; + +if (size >=3 && + options[size -3 ] =='l' && + options[size -2 ] =='l' && + options[size -1 ] >='1' && options[size -1 ] <='9' ) { + con->loglevel = options[size -1 ] -'0' ; + +/* Catch if the user added a comma after some serial console +* options, +* i.e. console=ttyS0,9600n8,ll3 +* the first comma is gone at this point, but we need to delete +* the second one. +*/ +if (size >3 && options[size -4 ] ==',' ) + options[size -4 ] =0 ; +else + options[size -3 ] =0 ; + }else + con->loglevel =0 ; + +return options; +} +static int __add_preferred_console (char *name,int idx,char *options,char *brl_options) {@@ -1949,12 +1979,15 @@ static int __add_preferred_console(char *name, int idx, char *options,if (!brl_options) selected_console = i;strlcpy (c->name, name,sizeof (c->name)); - c->options = options; + + c->options =setup_per_console_loglevel (c, options); +braille_set_options (c, brl_options); c->index = idx;return 0 ; } +/* * Set up a console. Called via do_early_param() in init/main.c * for each "console=" parameter in the boot command line. @@ -2478,6 +2511,8 @@ void register_console(struct console *newcon)if (newcon->setup && newcon->setup (newcon, console_cmdline[i].options) !=0 )break ; + + newcon->loglevel = c->loglevel; newcon->flags |=CON_ENABLED ; newcon->index = c->index;if (i == selected_console) {
Quoted 6 lines · Bruno Prémont
Quoted 5 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
Quoted 7 lines
Quoted 5 lines
console=ttyS0,ll4
console=tty0,ll6This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
I think this is reasonable to, but for consistency with other loglevel uses, I suggest using loglevel=<level> instead of ll<d>
Quoted 10 lines · Joe Perches
Quoted 9 lines · Bruno Prémont
Quoted 8 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6
Quoted 8 lines
Quoted 4 lines
Quoted 2 lines
This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
I think this is reasonable to, but for consistency with other loglevel uses, I suggest using loglevel=<level> instead of ll<d>
Oh those are l not 1. I read that as ,114 and ,116 and was wondering what that meant.
Signature · 1 line
Len Sorensen
Quoted 10 lines · Joe Perches
Quoted 9 lines · Bruno Prémont
Quoted 8 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6
Quoted 9 lines
Quoted 4 lines
Quoted 2 lines
This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
I think this is reasonable to, but for consistency with other loglevel uses, I suggest using loglevel=<level> instead of ll<d>
I can try it, I didn't do it initially because I didn't want to confuse the parsing of the other parameters ..
Daniel
Quoted 17 lines · Bruno Prémont
Quoted 10 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
What would be the best way to make these per-console loglevels configurable at runtime?dmesg -n $LEVELonly affects the global limit.
Quoted 4 lines
One drawback to letting global loglevel have precedence is that all consoles that should not get detailed log messages need to have their loglevel explicitly lowered and it's not possible to have one console forced to show more than the global loglevel.
Right, reason for the patch.
Quoted 4 lines
An approach I would prefer is to have all consoles follow global loglevel except when something different had been explicitly requested for them.
This patch is mostly like this. It breaks down when you set the "llX" parameter to something above KERN_NOTICE, and the global one is also set above that.
Quoted 2 lines
This way a single console can be added later on (e.g. netconsole) and set to pass through debug messages without affecting anyone else.
Not following the "added later" part.
Daniel
Quoted 26 lines · On Tue, 23 December 2014 [email protected] wrote:
Quoted 17 lines · Bruno Prémont
Quoted 10 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
What would be the best way to make these per-console loglevels configurable at runtime?dmesg -n $LEVELonly affects the global limit.Quoted 4 lines
One drawback to letting global loglevel have precedence is that all consoles that should not get detailed log messages need to have their loglevel explicitly lowered and it's not possible to have one console forced to show more than the global loglevel.
Right, reason for the patch.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
An approach I would prefer is to have all consoles follow global loglevel except when something different had been explicitly requested for them.
This patch is mostly like this. It breaks down when you set the "llX" parameter to something above
KERN_NOTICE, and the global one is also set above that.
In your patch global filter applies first, then what passes global filter gets filtered with the per-console filter.
So I can't have dmesg -n 3 and "console=ttyS0,ll8 console=tty0" to get my debugging output over serial console.
Quoted 2 lines
Quoted 2 lines
This way a single console can be added later on (e.g. netconsole) and set to pass through debug messages without affecting anyone else.
Netconsole console can be added at any time when system is running either through loading of its module or using dynamic configuration via configfs.
See also my patches.
Thanks,
Bruno
Quoted 35 lines · Bruno Prémont
Quoted 26 lines · On Tue, 23 December 2014 [email protected] wrote:
Quoted 17 lines · Bruno Prémont
Quoted 10 lines · On Sat, 20 December 2014 [email protected] wrote:
This adds to to the console= command line options allowing the addition of a per console log level setting.
examples,
console=ttyS0,ll4
console=tty0,ll6This can be used on systems which have multiple serial consoles, but it's desired for logging to be light on one and heavy on another.
Looks useful to me.
What would be the best way to make these per-console loglevels configurable at runtime?dmesg -n $LEVELonly affects the global limit.Quoted 4 lines
One drawback to letting global loglevel have precedence is that all consoles that should not get detailed log messages need to have their loglevel explicitly lowered and it's not possible to have one console forced to show more than the global loglevel.
Right, reason for the patch.
Quoted 1 line
Quoted 7 lines
Quoted 3 lines
An approach I would prefer is to have all consoles follow global loglevel except when something different had been explicitly requested for them.
This patch is mostly like this. It breaks down when you set the "llX" parameter to something above
KERN_NOTICE, and the global one is also set above that.
Quoted 5 lines
In your patch global filter applies first, then what passes global filter gets filtered with the per-console filter.
So I can't have
dmesg -n 3and "console=ttyS0,ll8 console=tty0" to get my debugging output over serial console.
Yeah .. This would improve things. I changed it after I sent the first patch, but it looks like one of your patches changes it also.
I was a little concerned about altering the fast path in call_console_drivers().. With the changes I made each call into call_console_drivers is forced to go thru the whole list of consoles, instead of short circuiting prior to the list.
I was thinking the max local and global log level could be saved and used for short circuiting instead of using the global log level.
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines
This way a single console can be added later on (e.g. netconsole) and set to pass through debug messages without affecting anyone else.
Netconsole console can be added at any time when system is running either through loading of its module or using dynamic configuration via configfs.
See also my patches.
Yeah, I saw them .. Not in too much detail, but it seems worth while for it to work with netconsole.
Daniel
PATCH 1/3 printk: Use a flag to indicate console-private loglevel
In reply to [email protected]In order to set loglevel for a given console that is not affected by global loglevel as adjusted via syslog(2), add a flag to the console and choose the level to match against msg level depending on this flag.
---
This depends on Daniel's patch "printk: add per console loglevel" and modifies the way its filtering is applied.
include/linux/console.h | 1 + kernel/printk/printk.c | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-)
include/linux/console.h +1 -0
@@ -115,6 +115,7 @@ static inline int con_debug_leave(void)#define CON_BOOT (8)#define CON_ANYTIME (16)/* Safe to call when cpu is offline */ #define CON_BRL (32)/* Used for a braille device */ +#define CON_LOGLEVEL (64)/* Per-console log-level filtering */ struct console {char name[16 ];
kernel/printk/printk.c +6 -6
@@ -1399,12 +1399,12 @@ static void call_console_drivers(int level, const char *text, size_t len)trace_console (text, len); -if (level >= console_loglevel && !ignore_loglevel) -return ;if (!console_drivers)return ;for_each_console (con) { +if (!ignore_loglevel && level >= (con->flags &CON_LOGLEVEL ? con->loglevel : console_loglevel)) +continue ;if (exclusive_console && con != exclusive_console)continue ;if (!(con->flags &CON_ENABLED ))
@@ -1414,9 +1414,6 @@ static void call_console_drivers(int level, const char *text, size_t len)if (!cpu_online (smp_processor_id ()) && !(con->flags &CON_ANYTIME ))continue ; -if (con->loglevel && !ignore_loglevel && - level >= con->loglevel) -continue ; con->write (con, text, len); } }
@@ -2512,7 +2509,10 @@ void register_console(struct console *newcon) newcon->setup(newcon, console_cmdline[i].options) != 0)break ; - newcon->loglevel = c->loglevel; +if (c->loglevel) { + newcon->loglevel = c->loglevel; + newcon->flags |=CON_LOGLEVEL ; + } newcon->flags |=CON_ENABLED ; newcon->index = c->index;if (i == selected_console) {
Signature · 1 line
2.0.4
PATCH 2/3 netconsole: make loglevel configurable per target
In reply to [email protected]Switch to registering a new console for each target so that loglevel based message filtering can be set individually for each target.
This adds a new loglevel= option to netconsole module parameter and also add a configfs file to configure the loglevel.
The loglevel conf be adjusted at any time for synamic netconsole consoles.
---
Note: only configuration via configfs has been runtime-tested.
Documentation/networking/netconsole.txt | 11 ++- drivers/net/netconsole.c | 114 +++++++++++++++++++++++--------- 2 files changed, 94 insertions(+), 31 deletions(-)
Documentation/networking/netconsole.txt +10 -1
@@ -24,7 +24,7 @@ Sender and receiver configuration: It takes a string configuration parameter "netconsole" in the following format: - netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr] + netconsole=[src-port]@[src-ip]/[<dev>],[tgt-port]@<tgt-ip>/[tgt-macaddr][,loglevel=level] where src-port source for UDP packets (defaults to 6665)
@@ -33,6 +33,9 @@ following format: tgt-port port for logging agent (6666) tgt-ip IP address for logging agent tgt-macaddr ethernet MAC address for logging agent (broadcast) + level limit messages printed to those whose loglevel is + smaller that value, range is 1 to 8 + If missing, loglevel limit as set via syslog(1) applies Examples:
@@ -114,11 +117,16 @@ The interface exposes these parameters of a netconsole target to userspace: remote_ip Remote agent's IP address (read-write) local_mac Local interface's MAC address (read-only) remote_mac Remote agent's MAC address (read-write) + loglevel Console loglevel filter (read-write) The "enabled" attribute is also used to control whether the parameters of a target can be updated or not -- you can modify the parameters of only disabled targets (i.e. if "enabled" is 0). +The "loglevel" parameter can be set at any time. When set to "0" it will +read back as empty string and global loglevel filter applies. Otherwise +specified loglevel filter applies. + To update a target's parameters: cat enabled # check if enabled is 1
@@ -164,6 +172,7 @@ priority messages to the console. You can change this at runtime using: dmesg -n 8 +or by specifying netconsole loglevel parameter or by specifying "debug" on the kernel command line at boot, to send all kernel messages to the console. A specific value for this parameter can also be set using the "loglevel" kernel boot option. See the
drivers/net/netconsole.c +84 -30
230 lines not on this page · raw message
Signature · 1 line
2.0.4
PATCH 3/3 netconsole: New console flag to dump full log buffer
In reply to [email protected]Be default only log messages not yet seen by userspace are output when enabling netconsole via module parameter (none when enabling dynamic targets).
When using netconsole to centrally log kernel messages it's of interest to have the whole kernel log sent over the same medium, even if netconsole setup happens rather late during system boot. The big advantage of netconsole over syslog for this task is that it usually allow catching much more messages when system crashes/panics.
This causes dynamic netconsoles to request full kernel log when first enabled.
---
Note, with this kernel is too quick at sending packets for some receiving machines to catch all of them. Either packets get dropped by the receiving NIC if can't buffer enough until OS has time to empty the buffers or they get lost between kernel and userspace socket if backlog is too small.
My test environment was 4core AMD APU with Gbit NIC to Marvell Kirkwood SheevaPlug with Gbit NIC. About first 100 lines get through, then lines start getting lost.
drivers/net/netconsole.c | 3 ++- include/linux/console.h | 1 + kernel/printk/printk.c | 12 +++++++++--- 3 files changed, 12 insertions(+), 4 deletions(-)
drivers/net/netconsole.c +2 -1
@@ -661,7 +661,8 @@ static struct config_item *make_netconsole_target(struct config_group *group,mutex_init (&nt->mutex);memset (nt->np.remote_mac,0xff ,ETH_ALEN );snprintf (nt->console.name,sizeof (nt->console.name),"netcon-%s" , name); - nt->console.flags =CON_ENABLED ; +/* Dump existing printks when we register */ + nt->console.flags =CON_ENABLED |CON_PRINTBUFFER |CON_PRINTALL ; nt->console.write = write_msg; nt->console.loglevel =0 ;
include/linux/console.h +1 -0
@@ -116,6 +116,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_LOGLEVEL (64)/* Per-console log-level filtering */ +#define CON_PRINTALL (128)/* Extends CON_PRINTBUFFER */ struct console {char name[16 ];
kernel/printk/printk.c +9 -3
@@ -2554,9 +2554,15 @@ void register_console(struct console *newcon)* for us. */ raw_spin_lock_irqsave (&logbuf_lock, flags); - console_seq = syslog_seq; - console_idx = syslog_idx; - console_prev = syslog_prev; +if (newcon->flags &CON_PRINTALL ) { + console_seq = log_first_seq; + console_idx = log_first_idx; + console_prev =LOG_NEWLINE ; + }else { + console_seq = syslog_seq; + console_idx = syslog_idx; + console_prev = syslog_prev; + }raw_spin_unlock_irqrestore (&logbuf_lock, flags);/* * We're about to replay the log buffer. Only do this to the
Signature · 1 line
2.0.4