mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Bruno Prémont" <bonbons@linux-vserver.org>
To: dwalker@fifo99.com, Matt Mackall <mpm@selenic.com>,
	Satyam Sharma <satyam.sharma@gmail.com>,
	Cong Wang <xiyou.wangcong@gmail.com>
Cc: linux-kernel@vger.kernel.org,
	Andrew Morton <akpm@linux-foundation.org>,
	Joe Perches <joe@perches.com>
Subject: [PATCH 2/3] netconsole: make loglevel configurable per target
Date: Tue, 23 Dec 2014 22:27:38 +0100	[thread overview]
Message-ID: <20141223222738.14e3fcd0@neptune.home> (raw)
In-Reply-To: <20141220224908.GB4466@fifo99.com>

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.

Signed-off-by: Bruno Prémont <bonbons@linux-vserver.org>
---
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(-)

diff --git a/Documentation/networking/netconsole.txt b/Documentation/networking/netconsole.txt
index a5d574a..c1df516 100644
--- a/Documentation/networking/netconsole.txt
+++ b/Documentation/networking/netconsole.txt
@@ -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
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index ba2f5e7..a96cd8e 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -103,10 +103,12 @@ struct netconsole_target {
 #ifdef	CONFIG_NETCONSOLE_DYNAMIC
 	struct config_item	item;
 #endif
+	struct console		console;
 	int			enabled;
 	struct mutex		mutex;
 	struct netpoll		np;
 };
+static void write_msg(struct console *con, const char *msg, unsigned int len);
 
 #ifdef	CONFIG_NETCONSOLE_DYNAMIC
 
@@ -171,6 +173,7 @@ static struct netconsole_target *alloc_param_target(char *target_config)
 {
 	int err = -ENOMEM;
 	struct netconsole_target *nt;
+	char *loglevel;
 
 	/*
 	 * Allocate and initialize with defaults.
@@ -186,8 +189,26 @@ static struct netconsole_target *alloc_param_target(char *target_config)
 	nt->np.remote_port = 6666;
 	mutex_init(&nt->mutex);
 	memset(nt->np.remote_mac, 0xff, ETH_ALEN);
+	snprintf(nt->console.name, sizeof(nt->console.name), "netcon");
+	/* Dump existing printks when we register */
+	nt->console.flags = CON_ENABLED | CON_PRINTBUFFER;
+	nt->console.write = write_msg;
 
 	/* Parse parameters and setup netpoll */
+	loglevel = strstr(target_config, ",loglevel=");
+	if (loglevel) {
+		int level;
+		err = kstrtoint(loglevel+10, 10, &level);
+		if (err < 0)
+			goto fail;
+		if (level < 1 || level > 8) {
+			err = -EINVAL;
+			goto fail;
+		}
+		nt->console.loglevel = level;
+		nt->console.flags |= CON_LOGLEVEL;
+		*loglevel = '\0';
+	}
 	err = netpoll_parse_options(&nt->np, target_config);
 	if (err)
 		goto fail;
@@ -228,6 +249,7 @@ static void free_param_target(struct netconsole_target *nt)
  *				|	remote_ip
  *				|	local_mac
  *				|	remote_mac
+ *				|	loglevel
  *				|
  *				<target>/...
  */
@@ -301,6 +323,14 @@ static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
 	return snprintf(buf, PAGE_SIZE, "%pM\n", nt->np.remote_mac);
 }
 
+static ssize_t show_loglevel(struct netconsole_target *nt, char *buf)
+{
+	if (nt->console.flags & CON_LOGLEVEL)
+		return snprintf(buf, PAGE_SIZE, "%u\n", nt->console.loglevel);
+	else
+		return snprintf(buf, PAGE_SIZE, "\n");
+}
+
 /*
  * This one is special -- targets created through the configfs interface
  * are not enabled (and the corresponding netpoll activated) by default.
@@ -338,6 +368,8 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 		if (err)
 			return err;
 
+		nt->enabled = 1;
+		register_console(&nt->console);
 		pr_info("netconsole: network logging started\n");
 	} else {	/* 0 */
 		/* We need to disable the netconsole before cleaning it up
@@ -347,11 +379,11 @@ static ssize_t store_enabled(struct netconsole_target *nt,
 		spin_lock_irqsave(&target_list_lock, flags);
 		nt->enabled = 0;
 		spin_unlock_irqrestore(&target_list_lock, flags);
+		unregister_console(&nt->console);
 		netpoll_cleanup(&nt->np);
+		nt->console.flags = nt->console.flags & ~CON_PRINTBUFFER;
 	}
 
-	nt->enabled = enabled;
-
 	return strnlen(buf, count);
 }
 
@@ -494,6 +526,27 @@ static ssize_t store_remote_mac(struct netconsole_target *nt,
 	return strnlen(buf, count);
 }
 
+static ssize_t store_loglevel(struct netconsole_target *nt,
+				 const char *buf,
+				 size_t count)
+{
+	int rv, level;
+
+	rv = kstrtoint(buf, 10, &level);
+	if (rv < 0)
+		return rv;
+	if (level < 0 || level > 8)
+		return -EINVAL;
+
+	if (level > 0) {
+		nt->console.loglevel = level;
+		nt->console.flags |= CON_LOGLEVEL;
+	} else
+		nt->console.flags &= ~CON_LOGLEVEL;
+
+	return strnlen(buf, count);
+}
+
 /*
  * Attribute definitions for netconsole_target.
  */
@@ -514,6 +567,7 @@ NETCONSOLE_TARGET_ATTR_RW(local_ip);
 NETCONSOLE_TARGET_ATTR_RW(remote_ip);
 NETCONSOLE_TARGET_ATTR_RO(local_mac);
 NETCONSOLE_TARGET_ATTR_RW(remote_mac);
+NETCONSOLE_TARGET_ATTR_RW(loglevel);
 
 static struct configfs_attribute *netconsole_target_attrs[] = {
 	&netconsole_target_enabled.attr,
@@ -524,6 +578,7 @@ static struct configfs_attribute *netconsole_target_attrs[] = {
 	&netconsole_target_remote_ip.attr,
 	&netconsole_target_local_mac.attr,
 	&netconsole_target_remote_mac.attr,
+	&netconsole_target_loglevel.attr,
 	NULL,
 };
 
@@ -605,6 +660,10 @@ static struct config_item *make_netconsole_target(struct config_group *group,
 	nt->np.remote_port = 6666;
 	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;
+	nt->console.write = write_msg;
+	nt->console.loglevel = 0;
 
 	/* Initialize the config_item member */
 	config_item_init_type_name(&nt->item, name, &netconsole_target_type);
@@ -626,6 +685,7 @@ static void drop_netconsole_target(struct config_group *group,
 	spin_lock_irqsave(&target_list_lock, flags);
 	list_del(&nt->list);
 	spin_unlock_irqrestore(&target_list_lock, flags);
+	unregister_console(&nt->console);
 
 	/*
 	 * The target may have never been enabled, or was manually disabled
@@ -732,7 +792,7 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 {
 	int frag, left;
 	unsigned long flags;
-	struct netconsole_target *nt;
+	struct netconsole_target *nt = container_of(con, struct netconsole_target, console);
 	const char *tmp;
 
 	if (oops_only && !oops_in_progress)
@@ -742,34 +802,26 @@ static void write_msg(struct console *con, const char *msg, unsigned int len)
 		return;
 
 	spin_lock_irqsave(&target_list_lock, flags);
-	list_for_each_entry(nt, &target_list, list) {
-		netconsole_target_get(nt);
-		if (nt->enabled && netif_running(nt->np.dev)) {
-			/*
-			 * We nest this inside the for-each-target loop above
-			 * so that we're able to get as much logging out to
-			 * at least one target if we die inside here, instead
-			 * of unnecessarily keeping all targets in lock-step.
-			 */
-			tmp = msg;
-			for (left = len; left;) {
-				frag = min(left, MAX_PRINT_CHUNK);
-				netpoll_send_udp(&nt->np, tmp, frag);
-				tmp += frag;
-				left -= frag;
-			}
+	netconsole_target_get(nt);
+	if (nt->enabled && netif_running(nt->np.dev)) {
+		/*
+		 * We nest this inside the for-each-target loop above
+		 * so that we're able to get as much logging out to
+		 * at least one target if we die inside here, instead
+		 * of unnecessarily keeping all targets in lock-step.
+		 */
+		tmp = msg;
+		for (left = len; left;) {
+			frag = min(left, MAX_PRINT_CHUNK);
+			netpoll_send_udp(&nt->np, tmp, frag);
+			tmp += frag;
+			left -= frag;
 		}
-		netconsole_target_put(nt);
 	}
+	netconsole_target_put(nt);
 	spin_unlock_irqrestore(&target_list_lock, flags);
 }
 
-static struct console netconsole = {
-	.name	= "netcon",
-	.flags	= CON_ENABLED,
-	.write	= write_msg,
-};
-
 static int __init init_netconsole(void)
 {
 	int err;
@@ -785,8 +837,6 @@ static int __init init_netconsole(void)
 				err = PTR_ERR(nt);
 				goto fail;
 			}
-			/* Dump existing printks when we register */
-			netconsole.flags |= CON_PRINTBUFFER;
 
 			spin_lock_irqsave(&target_list_lock, flags);
 			list_add(&nt->list, &target_list);
@@ -802,7 +852,9 @@ static int __init init_netconsole(void)
 	if (err)
 		goto undonotifier;
 
-	register_console(&netconsole);
+	list_for_each_entry_safe(nt, tmp, &target_list, list) {
+		register_console(&nt->console);
+	}
 	pr_info("network logging started\n");
 
 	return err;
@@ -830,7 +882,9 @@ static void __exit cleanup_netconsole(void)
 {
 	struct netconsole_target *nt, *tmp;
 
-	unregister_console(&netconsole);
+	list_for_each_entry_safe(nt, tmp, &target_list, list) {
+		unregister_console(&nt->console);
+	}
 	dynamic_netconsole_exit();
 	unregister_netdevice_notifier(&netconsole_netdev_notifier);
 
-- 
2.0.4


  parent reply	other threads:[~2014-12-23 21:27 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-20 22:49 [PATCH] printk: add per console loglevel dwalker
2014-12-21 18:47 ` Bruno Prémont
2014-12-21 19:03   ` Joe Perches
2014-12-22  1:49     ` Lennart Sorensen
2014-12-23 16:11     ` dwalker
2014-12-23 16:20   ` dwalker
2014-12-23 21:13     ` Bruno Prémont
2015-01-04 20:19       ` dwalker
2014-12-23 21:22 ` [PATCH 1/3] printk: Use a flag to indicate console-private loglevel Bruno Prémont
2014-12-23 21:27 ` Bruno Prémont [this message]
2014-12-23 21:37 ` [PATCH 3/3] netconsole: New console flag to dump full log buffer Bruno Prémont

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141223222738.14e3fcd0@neptune.home \
    --to=bonbons@linux-vserver.org \
    --cc=akpm@linux-foundation.org \
    --cc=dwalker@fifo99.com \
    --cc=joe@perches.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mpm@selenic.com \
    --cc=satyam.sharma@gmail.com \
    --cc=xiyou.wangcong@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®