Skip to contentSkip to conversation

printk: add per console loglevel

PATCH In review [email protected] 4 participants 11 messages Dec 20, 2014 – Jan 4, 2015

Subsystems (6)
lore
Share & tools
lore
#0 lore raw

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
index 4df73da..7e65d5b 100644
@@ -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
index 7571a16..99020d5 100644
@@ -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
index cbd69d8..6f6f98f 100644
@@ -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
index 02d6b6d..218d94d 100644
@@ -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
#1 lore raw
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,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.

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
---
 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
index 4df73da..7e65d5b 100644
@@ -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
index 7571a16..99020d5 100644
@@ -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
index cbd69d8..6f6f98f 100644
@@ -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
index 02d6b6d..218d94d 100644
@@ -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) {
#2 lore raw
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,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.

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>

#3 lore raw
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
#4 lore raw
In reply to Joe Perches
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

#5 lore raw
In reply to Bruno Prémont
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,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.

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.

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

#6 lore raw
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,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.

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.

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

#7 lore raw
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,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.

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.

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 3 and "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

#8 lore raw

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
index 99020d5..f3a8996 100644
@@ -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
index 218d94d..8f09f30 100644
@@ -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
#9 lore raw

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
index a5d574a..c1df516 100644
@@ -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
#10 lore raw

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
index a96cd8e..241c70f 100644
@@ -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
index f3a8996..6f53a54 100644
@@ -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
index 8f09f30..193665d 100644
@@ -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