LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole
@ 2007-03-20 12:10 Keiichi KII
  2007-03-20 12:24 ` [RFC][PATCH -mm take3 1/6][resend] marking __init Keiichi KII
                   ` (5 more replies)
  0 siblings, 6 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:10 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

The netconsole is a very useful module for collecting kernel message under
certain circumstances(e.g. disk logging fails, serial port is unavailable).

But current netconsole is not flexible. For example, if you want to change ip
address for logging agent, in the case of built-in netconsole, you can't change
config except for changing boot parameter and rebooting your system, or in the
case of module netconsole, you need to remove it and reload with different
parameters.

So, I propose the following extended features for netconsole.

1) support for multiple logging agents.
2) add interface to access each parameter of netconsole
   using sysfs.

[changes since take2]
-changing kernel base from 2.6.20-rc1-mm1 to 2.6.21-rc3.mm2.
-using symbolic link for network device.
-changing in part interface from sysfs to ioctl,
 because Stephen Hemminger advised us that it is a misuse that
 sysfs has the behavior with magic side effect such as adding/removing port.

This patch is for linux-2.6.21-rc3-mm2 and is divided to each function.
Your comments are very welcome.

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 1/6][resend] marking __init
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
@ 2007-03-20 12:24 ` Keiichi KII
  2007-03-20 15:36   ` Matt Mackall
  2007-03-20 12:26 ` [RFC][PATCH -mm take3 2/6][resend] support multiple logging Keiichi KII
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:24 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

This patch contains the following cleanups.
 - add __init for initialization functions(option_setup() and
   init_netconsole()).

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
Index: linux-mm/drivers/net/netconsole.c
===================================================================
--- linux-mm.orig/drivers/net/netconsole.c
+++ linux-mm/drivers/net/netconsole.c
@@ -91,7 +91,7 @@ static struct console netconsole = {
 	.write = write_msg
 };
 
-static int option_setup(char *opt)
+static int __init option_setup(char *opt)
 {
 	configured = !netpoll_parse_options(&np, opt);
 	return 1;
@@ -99,7 +99,7 @@ static int option_setup(char *opt)
 
 __setup("netconsole=", option_setup);
 
-static int init_netconsole(void)
+static int __init init_netconsole(void)
 {
 	int err;
 

-- 


^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 2/6][resend] support multiple logging
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
  2007-03-20 12:24 ` [RFC][PATCH -mm take3 1/6][resend] marking __init Keiichi KII
@ 2007-03-20 12:26 ` Keiichi KII
  2007-03-20 12:34   ` Alexey Dobriyan
  2007-03-20 12:28 ` [RFC][PATCH -mm take3 3/6][resend] add interface for netconsole using sysfs Keiichi KII
                   ` (3 subsequent siblings)
  5 siblings, 1 reply; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:26 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

This patch contains the following changes for supporting multiple logging
 agents.

1. extend netconsole to multiple netpolls
   To send kernel messages to multiple logging agents, extend netcosnole
    to be able to use multiple netpolls. Each netpoll sends kernel messages
    to its own logging agent.

2. change config parameter format
   We change config parameter format from single configuration to multiple 
   configurations separated by ';'.

   ex) sending kernel messages to destination1 and destination2 using eth0.
    modprobe netconsole \
            netconsole="@/eth0,@[destination1]/;@/eth0,@[destination2]/"

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
Index: linux-2.6.19.5/drivers/net/netconsole.c
===================================================================
--- linux-2.6.19.5.orig/drivers/net/netconsole.c
+++ linux-2.6.19.5/drivers/net/netconsole.c
@@ -54,6 +54,20 @@ static char config[256];
 module_param_string(netconsole, config, 256, 0);
 MODULE_PARM_DESC(netconsole, " netconsole=[src-port]@[src-ip]/[dev],[tgt-port]@<tgt-ip>/[tgt-macaddr]\n");
 
+struct netconsole_target {
+	struct list_head list;
+	int id;
+	struct netpoll np;
+};
+
+static int add_target(char* target_config);
+static void cleanup_netconsole(void);
+static void delete_target(struct netconsole_target *nt);
+
+static LIST_HEAD(target_list);
+
+static DEFINE_SPINLOCK(target_list_lock);
+
 static struct netpoll np = {
 	.name = "netconsole",
 	.dev_name = "eth0",
@@ -61,27 +75,85 @@ static struct netpoll np = {
 	.remote_port = 6666,
 	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 };
-static int configured = 0;
 
 #define MAX_PRINT_CHUNK 1000
+#define CONFIG_SEPARATOR ";"
+
+static int add_target(char* target_config)
+{
+	int retval = 0;
+	static atomic_t target_count = ATOMIC_INIT(0);
+	struct netconsole_target *new_target;
+
+	new_target = kzalloc(sizeof(*new_target), GFP_KERNEL);
+	if (!new_target) {
+		printk(KERN_ERR "netconsole: kmalloc() failed!\n");
+		retval = -ENOMEM;
+		goto out;
+	}
+
+	new_target->np = np;
+	if (netpoll_parse_options(&new_target->np, target_config)) {
+		printk(KERN_ERR "netconsole: can't parse config:%s\n",
+		       target_config);
+		kfree(new_target);
+		retval = -EINVAL;
+		goto out;
+	}
+	if (netpoll_setup(&new_target->np)) {
+		printk(KERN_ERR "netconsole: can't setup netpoll:%s\n",
+		       target_config);
+		kfree(new_target);
+		retval = -EINVAL;
+		goto out;
+	}
+
+	atomic_inc(&target_count);
+	new_target->id = atomic_read(&target_count);
+
+	printk(KERN_INFO "netconsole: add target: "
+	       "remote ip_addr=%d.%d.%d.%d remote port=%d\n",
+	       HIPQUAD(new_target->np.remote_ip), new_target->np.remote_port);
+
+	spin_lock(&target_list_lock);
+	list_add(&new_target->list, &target_list);
+	spin_unlock(&target_list_lock);
+
+ out:
+	return retval;
+}
+
+static void delete_target(struct netconsole_target *nt)
+{
+	spin_lock(&target_list_lock);
+	list_del(&nt->list);
+	spin_unlock(&target_list_lock);
+	netpoll_cleanup(&nt->np);
+	kfree(nt);
+}
 
 static void write_msg(struct console *con, const char *msg, unsigned int len)
 {
 	int frag, left;
 	unsigned long flags;
+	struct netconsole_target *target;
 
-	if (!np.dev)
+	if (list_empty(&target_list))
 		return;
 
 	local_irq_save(flags);
+	spin_lock(&target_list_lock);
 
 	for(left = len; left; ) {
 		frag = min(left, MAX_PRINT_CHUNK);
-		netpoll_send_udp(&np, msg, frag);
+		list_for_each_entry(target, &target_list, list) {
+			netpoll_send_udp(&target->np, msg, frag);
+		}
 		msg += frag;
 		left -= frag;
 	}
 
+	spin_unlock(&target_list_lock);
 	local_irq_restore(flags);
 }
 
@@ -91,39 +163,48 @@ static struct console netconsole = {
 	.write = write_msg
 };
 
+#ifndef MODULE
 static int __init option_setup(char *opt)
 {
-	configured = !netpoll_parse_options(&np, opt);
+	strncpy(config, opt, 256);
 	return 1;
 }
 
 __setup("netconsole=", option_setup);
+#endif
 
 static int __init init_netconsole(void)
 {
-	int err;
+	char *p;
+	char *tmp = config;
 
-	if(strlen(config))
-		option_setup(config);
+	register_console(&netconsole);
 
-	if(!configured) {
-		printk("netconsole: not configured, aborting\n");
+	if(!strlen(config)) {
+		printk(KERN_ERR "netconsole: not configured\n");
 		return 0;
 	}
+	while ((p = strsep(&tmp, CONFIG_SEPARATOR)) != NULL) {
+		if (add_target(p)) {
+			printk(KERN_ERR
+			       "netconsole: can't add target to netconsole\n");
+			cleanup_netconsole();
+			return -EINVAL;
+		}
+	}
 
-	err = netpoll_setup(&np);
-	if (err)
-		return err;
-
-	register_console(&netconsole);
 	printk(KERN_INFO "netconsole: network logging started\n");
 	return 0;
 }
 
 static void cleanup_netconsole(void)
 {
+	struct netconsole_target *nt, *tmp;
+
 	unregister_console(&netconsole);
-	netpoll_cleanup(&np);
+	list_for_each_entry_safe(nt, tmp, &target_list, list) {
+		delete_target(nt);
+	}
 }
 
 module_init(init_netconsole);

-- 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 3/6][resend] add interface for netconsole using sysfs
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
  2007-03-20 12:24 ` [RFC][PATCH -mm take3 1/6][resend] marking __init Keiichi KII
  2007-03-20 12:26 ` [RFC][PATCH -mm take3 2/6][resend] support multiple logging Keiichi KII
@ 2007-03-20 12:28 ` Keiichi KII
  2007-03-20 12:30 ` [RFC][PATCH -mm take3 4/6][resend] using symlink for the net_device Keiichi KII
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:28 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

This patch contains the following changes.

create a sysfs entry for netconsole in /sys/class/misc.
This entry has elements related to netconsole as follows.
You can change configuration of netconsole(writable attributes such as IP
address, port number and so on) and check current configuration of netconsole.

-+- /sys/class/misc/
 |-+- netconsole/
   |-+- port1/
   | |--- id          [r--r--r--]  unique port id
   | |--- local_ip    [rw-r--r--]  source IP to use, writable
   | |--- local_mac   [r--r--r--]  source MAC address
   | |--- local_port  [rw-r--r--]  source port number for UDP packets, writable
   | |--- remote_ip   [rw-r--r--]  port number for logging agent, writable
   | |--- remote_mac  [rw-r--r--]  MAC address for logging agent, writable
   | ---- remote_port [rw-r--r--]  IP address for logging agent, writable
   |--- port2/
   |--- port3/
   ...

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
Index: linux-mm/drivers/net/netconsole.c
===================================================================
--- linux-mm.orig/drivers/net/netconsole.c
+++ linux-mm/drivers/net/netconsole.c
@@ -45,6 +45,8 @@
 #include <linux/sysrq.h>
 #include <linux/smp.h>
 #include <linux/netpoll.h>
+#include <linux/miscdevice.h>
+#include <linux/inet.h>
 
 MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
 MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -56,18 +58,215 @@ MODULE_PARM_DESC(netconsole, " netconsol
 
 struct netconsole_target {
 	struct list_head list;
+	struct kobject obj;
 	int id;
 	struct netpoll np;
 };
 
+#define MAX_PRINT_CHUNK 1000
+#define CONFIG_SEPARATOR ";"
+
+struct target_attr {
+	struct attribute attr;
+	ssize_t (*show)(struct netconsole_target*, char*);
+	ssize_t (*store)(struct netconsole_target*, const char*,
+			 size_t count);
+};
+
 static int add_target(char* target_config);
+static int setup_target_sysfs(struct netconsole_target *nt);
 static void cleanup_netconsole(void);
 static void delete_target(struct netconsole_target *nt);
 
+static int miscdev_configured;
+
 static LIST_HEAD(target_list);
 
 static DEFINE_SPINLOCK(target_list_lock);
 
+static ssize_t show_id(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d\n", nt->id);
+}
+
+static ssize_t show_local_port(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d\n", nt->np.local_port);
+}
+
+static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d\n", nt->np.remote_port);
+}
+
+static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d.%d.%d.%d\n", HIPQUAD(nt->np.local_ip));
+}
+
+static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d.%d.%d.%d\n", HIPQUAD(nt->np.remote_ip));
+}
+
+static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       nt->np.local_mac[0], nt->np.local_mac[1],
+		       nt->np.local_mac[2], nt->np.local_mac[3],
+		       nt->np.local_mac[4], nt->np.local_mac[5]);
+}
+
+static ssize_t show_remote_mac(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x\n",
+		       nt->np.remote_mac[0], nt->np.remote_mac[1],
+		       nt->np.remote_mac[2], nt->np.remote_mac[3],
+		       nt->np.remote_mac[4], nt->np.remote_mac[5]);
+}
+
+static ssize_t store_local_port(struct netconsole_target *nt, const char *buf,
+				size_t count)
+{
+	spin_lock(&target_list_lock);
+	nt->np.local_port = simple_strtol(buf, NULL, 10);
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
+static ssize_t store_remote_port(struct netconsole_target *nt, const char *buf,
+				size_t count)
+{
+	spin_lock(&target_list_lock);
+	nt->np.remote_port = simple_strtol(buf, NULL, 10);
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
+static ssize_t store_local_ip(struct netconsole_target *nt, const char *buf,
+			      size_t count)
+{
+	spin_lock(&target_list_lock);
+	nt->np.local_ip = ntohl(in_aton(buf));
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
+static ssize_t store_remote_ip(struct netconsole_target *nt, const char *buf,
+			       size_t count)
+{
+	spin_lock(&target_list_lock);
+	nt->np.remote_ip = ntohl(in_aton(buf));
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
+static ssize_t store_remote_mac(struct netconsole_target *nt, const char *buf,
+			       size_t count)
+{
+	unsigned char input_mac[ETH_ALEN] =
+		{0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+	const char *cur = buf;
+	int i = 0;
+
+	input_mac[i++] = simple_strtol(cur, NULL, 16);
+	while ((cur = strchr(cur, ':')) != NULL) {
+		cur++;
+		input_mac[i++] = simple_strtol(cur, NULL, 16);
+	}
+	if (i != ETH_ALEN)
+		return -EINVAL;
+	spin_lock(&target_list_lock);
+	memcpy(nt->np.remote_mac, input_mac, ETH_ALEN);
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
+#define NETCON_CLASS_ATTR(_name, _mode, _show, _store) \
+struct target_attr target_attr_##_name = \
+                           __ATTR(_name, _mode, _show, _store)
+
+static NETCON_CLASS_ATTR(id, S_IRUGO, show_id, NULL);
+static NETCON_CLASS_ATTR(local_port, S_IRUGO | S_IWUSR,
+			 show_local_port, store_local_port);
+static NETCON_CLASS_ATTR(remote_port, S_IRUGO | S_IWUSR,
+			 show_remote_port, store_remote_port);
+static NETCON_CLASS_ATTR(local_ip, S_IRUGO | S_IWUSR,
+			 show_local_ip, store_local_ip);
+static NETCON_CLASS_ATTR(remote_ip, S_IRUGO | S_IWUSR,
+			 show_remote_ip, store_remote_ip);
+static NETCON_CLASS_ATTR(local_mac, S_IRUGO, show_local_mac, NULL);
+static NETCON_CLASS_ATTR(remote_mac, S_IRUGO | S_IWUSR,
+			 show_remote_mac, store_remote_mac);
+
+static struct attribute *target_attrs[] = {
+	&target_attr_id.attr,
+	&target_attr_local_port.attr,
+	&target_attr_remote_port.attr,
+	&target_attr_local_ip.attr,
+	&target_attr_remote_ip.attr,
+	&target_attr_local_mac.attr,
+	&target_attr_remote_mac.attr,
+	NULL
+};
+
+static ssize_t show_target_attr(struct kobject *kobj,
+				    struct attribute *attr,
+				    char *buffer)
+{
+	struct target_attr *na =
+		container_of(attr, struct target_attr, attr);
+	struct netconsole_target * nt =
+		container_of(kobj, struct netconsole_target, obj);
+	if (na->show)
+		return na->show(nt, buffer);
+	else
+		return -EIO;
+}
+
+static ssize_t store_target_attr(struct kobject *kobj,
+				     struct attribute *attr,
+				     const char *buffer, size_t count)
+{
+	struct target_attr *na =
+		container_of(attr, struct target_attr, attr);
+	struct netconsole_target *nt =
+		container_of(kobj, struct netconsole_target, obj);
+	if (na->store)
+		return na->store(nt, buffer, count);
+	else
+		return -EIO;
+}
+
+static void release_target(struct kobject *kobj)
+{
+	struct netconsole_target *nt =
+		container_of(kobj, struct netconsole_target, obj);
+
+	delete_target(nt);
+}
+
+static struct sysfs_ops target_sysfs_ops = {
+	.show = show_target_attr,
+	.store = store_target_attr
+};
+
+static struct kobj_type target_ktype = {
+	.release = release_target,
+	.sysfs_ops = &target_sysfs_ops,
+	.default_attrs = target_attrs,
+};
+
+static struct miscdevice netconsole_miscdev = {
+	.minor = MISC_DYNAMIC_MINOR,
+	.name = "netconsole",
+};
+
 static struct netpoll np = {
 	.name = "netconsole",
 	.dev_name = "eth0",
@@ -76,9 +275,6 @@ static struct netpoll np = {
 	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 };
 
-#define MAX_PRINT_CHUNK 1000
-#define CONFIG_SEPARATOR ";"
-
 static int add_target(char* target_config)
 {
 	int retval = 0;
@@ -119,10 +315,19 @@ static int add_target(char* target_confi
 	list_add(&new_target->list, &target_list);
 	spin_unlock(&target_list_lock);
 
+	retval = setup_target_sysfs(new_target);
  out:
 	return retval;
 }
 
+static int setup_target_sysfs(struct netconsole_target *nt)
+{
+	kobject_set_name(&nt->obj, "port%d", nt->id);
+	nt->obj.parent = &netconsole_miscdev.this_device->kobj;
+	nt->obj.ktype = &target_ktype;
+	return kobject_register(&nt->obj);
+}
+
 static void delete_target(struct netconsole_target *nt)
 {
 	spin_lock(&target_list_lock);
@@ -178,6 +383,15 @@ static int __init init_netconsole(void)
 	char *p;
 	char *tmp = config;
 
+	if (misc_register(&netconsole_miscdev)) {
+		printk(KERN_ERR
+		       "netconsole: failed to register misc device for "
+		       "name = %s, id = %d\n",
+		       netconsole_miscdev.name, netconsole_miscdev.minor);
+		return -EIO;
+	} else
+		miscdev_configured = 1;
+
 	register_console(&netconsole);
 
 	if(!strlen(config)) {
@@ -203,8 +417,10 @@ static void cleanup_netconsole(void)
 
 	unregister_console(&netconsole);
 	list_for_each_entry_safe(nt, tmp, &target_list, list) {
-		delete_target(nt);
+		kobject_unregister(&nt->obj);
 	}
+	if (miscdev_configured)
+		misc_deregister(&netconsole_miscdev);
 }
 
 module_init(init_netconsole);

-- 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 4/6][resend] using symlink for the net_device
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
                   ` (2 preceding siblings ...)
  2007-03-20 12:28 ` [RFC][PATCH -mm take3 3/6][resend] add interface for netconsole using sysfs Keiichi KII
@ 2007-03-20 12:30 ` Keiichi KII
  2007-03-20 12:31 ` [RFC][PATCH -mm take3 5/6][resend] switch function of netpoll Keiichi KII
  2007-03-20 12:34 ` [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target Keiichi KII
  5 siblings, 0 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:30 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

We use symbolic link for net_device.
The link in sysfs represents the corresponding network etherdevice.

-+- /sys/class/misc/
 |-+- netconsole/
 |-+- port1/
 | |--- id             [r--r--r--]  id
 | |--- net:<net_dev>  [rw-r--r--]  net_dev: eth0,eth1,...
 | ...
 |--- port2/
 ...

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
Index: linux-mm/drivers/net/netconsole.c
===================================================================
--- linux-mm.orig/drivers/net/netconsole.c
+++ linux-mm/drivers/net/netconsole.c
@@ -77,6 +77,9 @@ static int add_target(char* target_confi
 static int setup_target_sysfs(struct netconsole_target *nt);
 static void cleanup_netconsole(void);
 static void delete_target(struct netconsole_target *nt);
+static char* make_netdev_class_name(char *netdev_name);
+static int netconsole_event(struct notifier_block *this, unsigned long event,
+			    void *ptr);
 
 static int miscdev_configured;
 
@@ -275,6 +278,10 @@ static struct netpoll np = {
 	.remote_mac = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
 };
 
+static struct notifier_block netconsole_notifier = {
+	.notifier_call = netconsole_event,
+};
+
 static int add_target(char* target_config)
 {
 	int retval = 0;
@@ -322,10 +329,20 @@ static int add_target(char* target_confi
 
 static int setup_target_sysfs(struct netconsole_target *nt)
 {
+	int retval = 0;
+	char *name;
+
 	kobject_set_name(&nt->obj, "port%d", nt->id);
 	nt->obj.parent = &netconsole_miscdev.this_device->kobj;
 	nt->obj.ktype = &target_ktype;
-	return kobject_register(&nt->obj);
+	retval = kobject_register(&nt->obj);
+	name = make_netdev_class_name(nt->np.dev_name);
+	if (IS_ERR(name))
+		return PTR_ERR(name);
+	retval = sysfs_create_link(&nt->obj, &nt->np.dev->dev.kobj, name);
+	kfree(name);
+
+	return retval;
 }
 
 static void delete_target(struct netconsole_target *nt)
@@ -337,6 +354,57 @@ static void delete_target(struct netcons
 	kfree(nt);
 }
 
+static char* make_netdev_class_name(char *netdev_name)
+{
+	int size;
+	char *name;
+	char *netdev_class_prefix = "net:";
+
+	size = strlen(netdev_class_prefix) + strlen(netdev_name) + 1;
+	name = kmalloc(size, GFP_KERNEL);
+	if (!name) {
+		printk(KERN_ERR "netconsole: kmalloc() failed!\n");
+		return ERR_PTR(-ENOMEM);
+	}
+	strcpy(name, netdev_class_prefix);
+	strcat(name, netdev_name);
+
+	return name;
+}
+
+static int netconsole_event(struct notifier_block *this, unsigned long event,
+			    void *ptr)
+{
+	int error = 0;
+	char *old_link_name = NULL, *new_link_name = NULL;
+	struct netconsole_target *nt;
+	struct net_device *dev = ptr;
+
+	if (event == NETDEV_CHANGENAME) {
+		spin_lock(&target_list_lock);
+		list_for_each_entry(nt, &target_list, list) {
+			if (nt->np.dev != dev)
+				continue;
+			new_link_name = make_netdev_class_name(dev->name);
+			old_link_name =
+				make_netdev_class_name(nt->np.dev_name);
+			sysfs_remove_link(&nt->obj, old_link_name);
+			error = sysfs_create_link(&nt->obj,
+						  &nt->np.dev->dev.kobj,
+						  new_link_name);
+			if (error)
+				printk(KERN_ERR "can't create link: %s\n",
+				       new_link_name);
+			strcpy(nt->np.dev_name, dev->name);
+			kfree(new_link_name);
+			kfree(old_link_name);
+		}
+		spin_unlock(&target_list_lock);
+	}
+
+	return NOTIFY_DONE;
+}
+
 static void write_msg(struct console *con, const char *msg, unsigned int len)
 {
 	int frag, left;
@@ -393,6 +461,7 @@ static int __init init_netconsole(void)
 		miscdev_configured = 1;
 
 	register_console(&netconsole);
+	register_netdevice_notifier(&netconsole_notifier);
 
 	if(!strlen(config)) {
 		printk(KERN_ERR "netconsole: not configured\n");
@@ -416,6 +485,7 @@ static void cleanup_netconsole(void)
 	struct netconsole_target *nt, *tmp;
 
 	unregister_console(&netconsole);
+	unregister_netdevice_notifier(&netconsole_notifier);
 	list_for_each_entry_safe(nt, tmp, &target_list, list) {
 		kobject_unregister(&nt->obj);
 	}

-- 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 5/6][resend] switch function of netpoll
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
                   ` (3 preceding siblings ...)
  2007-03-20 12:30 ` [RFC][PATCH -mm take3 4/6][resend] using symlink for the net_device Keiichi KII
@ 2007-03-20 12:31 ` Keiichi KII
  2007-03-20 12:34 ` [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target Keiichi KII
  5 siblings, 0 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:31 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

This patch contains switch function of netpoll.

If "enabled" attribute of certain port is '1', this port is used
and the configurations of this port are uable to change.

If "enabled" attribute of certain port is '0', this port isn't used
and the configurations of this port are able to change.

-+- /sys/class/misc/
|-+- netconsole/
  |-+- port1/
  | |--- id          [r--r--r--]  id
  | |--- enabled     [rw-r--r--]  0: disable 1: enable, writable
  | ...
  |--- port2/
  ...

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
Index: linux-2.6.19.5/drivers/net/netconsole.c
===================================================================
--- linux-2.6.19.5.orig/drivers/net/netconsole.c
+++ linux-2.6.19.5/drivers/net/netconsole.c
@@ -60,6 +60,7 @@ struct netconsole_target {
 	struct list_head list;
 	struct kobject obj;
 	int id;
+	int enabled;
 	struct netpoll np;
 };
 
@@ -128,10 +129,19 @@ static ssize_t show_remote_mac(struct ne
 		       nt->np.remote_mac[4], nt->np.remote_mac[5]);
 }
 
+static ssize_t show_enabled(struct netconsole_target *nt, char *buf)
+{
+	return sprintf(buf, "%d\n", nt->enabled);
+}
+
 static ssize_t store_local_port(struct netconsole_target *nt, const char *buf,
 				size_t count)
 {
 	spin_lock(&target_list_lock);
+	if (nt->enabled) {
+		spin_unlock(&target_list_lock);
+		return -EINVAL;
+	}
 	nt->np.local_port = simple_strtol(buf, NULL, 10);
 	spin_unlock(&target_list_lock);
 
@@ -142,6 +152,10 @@ static ssize_t store_remote_port(struct 
 				size_t count)
 {
 	spin_lock(&target_list_lock);
+	if (nt->enabled) {
+		spin_unlock(&target_list_lock);
+		return -EINVAL;
+	}
 	nt->np.remote_port = simple_strtol(buf, NULL, 10);
 	spin_unlock(&target_list_lock);
 
@@ -152,6 +166,10 @@ static ssize_t store_local_ip(struct net
 			      size_t count)
 {
 	spin_lock(&target_list_lock);
+	if (nt->enabled) {
+		spin_unlock(&target_list_lock);
+		return -EINVAL;
+	}
 	nt->np.local_ip = ntohl(in_aton(buf));
 	spin_unlock(&target_list_lock);
 
@@ -162,6 +180,10 @@ static ssize_t store_remote_ip(struct ne
 			       size_t count)
 {
 	spin_lock(&target_list_lock);
+	if (nt->enabled) {
+		spin_unlock(&target_list_lock);
+		return -EINVAL;
+	}
 	nt->np.remote_ip = ntohl(in_aton(buf));
 	spin_unlock(&target_list_lock);
 
@@ -184,12 +206,39 @@ static ssize_t store_remote_mac(struct n
 	if (i != ETH_ALEN)
 		return -EINVAL;
 	spin_lock(&target_list_lock);
+	if (nt->enabled) {
+		spin_unlock(&target_list_lock);
+		return -EINVAL;
+	}
 	memcpy(nt->np.remote_mac, input_mac, ETH_ALEN);
 	spin_unlock(&target_list_lock);
 
 	return count;
 }
 
+static ssize_t store_enabled(struct netconsole_target *nt, const char *buf,
+			    size_t count)
+{
+	int enabled = 0;
+
+	if (count >= 2 && (count != 2 || buf[count - 1] != '\n')) {
+		printk(KERN_ERR "netconsole: invalid argument: %s\n", buf);
+		return -EINVAL;
+	} else if (strncmp(buf, "1", 1) == 0) {
+		enabled = 1;
+	} else if(strncmp(buf, "0", 1) == 0) {
+		enabled = 0;
+	} else {
+		printk(KERN_ERR "netconsole: invalid argument: %s\n", buf);
+		return -EINVAL;
+	}
+	spin_lock(&target_list_lock);
+	nt->enabled = enabled;
+	spin_unlock(&target_list_lock);
+
+	return count;
+}
+
 #define NETCON_CLASS_ATTR(_name, _mode, _show, _store) \
 struct target_attr target_attr_##_name = \
                            __ATTR(_name, _mode, _show, _store)
@@ -206,6 +255,8 @@ static NETCON_CLASS_ATTR(remote_ip, S_IR
 static NETCON_CLASS_ATTR(local_mac, S_IRUGO, show_local_mac, NULL);
 static NETCON_CLASS_ATTR(remote_mac, S_IRUGO | S_IWUSR,
 			 show_remote_mac, store_remote_mac);
+static NETCON_CLASS_ATTR(enabled, S_IRUGO | S_IWUSR,
+			 show_enabled, store_enabled);
 
 static struct attribute *target_attrs[] = {
 	&target_attr_id.attr,
@@ -215,6 +266,7 @@ static struct attribute *target_attrs[] 
 	&target_attr_remote_ip.attr,
 	&target_attr_local_mac.attr,
 	&target_attr_remote_mac.attr,
+	&target_attr_enabled.attr,
 	NULL
 };
 
@@ -313,6 +365,7 @@ static int add_target(char* target_confi
 
 	atomic_inc(&target_count);
 	new_target->id = atomic_read(&target_count);
+	new_target->enabled = 1;
 
 	printk(KERN_INFO "netconsole: add target: "
 	       "remote ip_addr=%d.%d.%d.%d remote port=%d\n",
@@ -420,7 +473,8 @@ static void write_msg(struct console *co
 	for(left = len; left; ) {
 		frag = min(left, MAX_PRINT_CHUNK);
 		list_for_each_entry(target, &target_list, list) {
-			netpoll_send_udp(&target->np, msg, frag);
+			if (target->enabled)
+				netpoll_send_udp(&target->np, msg, frag);
 		}
 		msg += frag;
 		left -= frag;

-- 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target
  2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
                   ` (4 preceding siblings ...)
  2007-03-20 12:31 ` [RFC][PATCH -mm take3 5/6][resend] switch function of netpoll Keiichi KII
@ 2007-03-20 12:34 ` Keiichi KII
  2007-03-20 12:50   ` Alexey Dobriyan
  2007-03-22 10:05   ` Keiichi KII
  5 siblings, 2 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-20 12:34 UTC (permalink / raw)
  To: mpm; +Cc: linux-kernel, netdev

From: Keiichi KII <k-keiichi@bx.jp.nec.com>

We add ioctls for adding/removing target.
If we use NETCONSOLE_ADD_TARGET ioctl, 
we can dynamically add netconsole target. 
If we use NETCONSOLE_REMOVE_TARGET ioctl,
we can dynamically remoe netconsole target.

We attach a sample program for ioctl.

Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
---
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stropts.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if_ether.h>

#define NETCONSOLE_DEV_NAME "/dev/netconsole"

struct command {
        char *name;
        char *options;
        int (*handle_command)(struct command* command,
                              int argc, char* argv[]);
        void (*usage)(char *msg);

extern char *optarg;

static void generic_usage(char *msg) {
        fprintf(stderr, "Usage  : netconfig command [option] [args]\n");
        fprintf(stderr, "command: add remove help\n");
        exit(-1);
                        break;
                case 's':
                        address = inet_addr(optarg);
                        if (address == -1)
                                (*command->usage)("invlid IP address!\n");
                        req.local_ip = address;
                        break;
                case 'h':
                default:
                        (*command->usage)(NULL);
                }
        }
        argc -= optind;
                if (i != ETH_ALEN)
                        (*command->usage)("Invalid MAC address!\n");
                memcpy(req.remote_mac, mac, ETH_ALEN);

        fd = open(NETCONSOLE_DEV_NAME, O_RDWR);
        if (fd < 0) {
                fprintf(stderr, "cannot open device" NETCONSOLE_DEV_NAME "\n");
                return -1;
        exit(-1);

static int handle_command_remove(struct command *command,
                                 int argc, char** argv)
{

        while ((ch = getopt(argc, argv, command->options)) != -1) {
                switch (ch) {
                case 'h':
                default:
                        (*command->usage)(NULL);
                }
        }
        argc -= optind;

        if (argc != 1)

        id = atoi(argv[0]);
        fd = open(NETCONSOLE_DEV_NAME, O_RDWR);
        if (fd < 0) {
                fprintf(stderr, "can't open device " NETCONSOLE_DEV_NAME "\n");
                return -1;
        }
        if(ioctl(fd, NETCON_REMOVE_TARGET, &id) != 0)
                perror("remove");

        return 0;

static void usage_remove(char *msg) {
        fprintf(stderr, "Usage  : netconfig remove id\n");
        exit(-1);

static int handle_command_help(struct command *command,
                               int argc, char** argv) {

        return 0;

static void usage_help(char *msg) {
        generic_usage(NULL);
                        break;
                }
        }

        if (command == NULL)
                generic_usage(NULL);
        argc--;
        argv++;

        if (command->handle_command)
                (*command->handle_command)(command, argc, argv);
        else {
                fprintf(stderr, "function handle_command() isn't set.");
                exit(-1);
        }
        return 0;
}

Index: linux-mm/fs/compat_ioctl.c
===================================================================
--- linux-mm.orig/fs/compat_ioctl.c
+++ linux-mm/fs/compat_ioctl.c
@@ -117,6 +117,8 @@
 #include <linux/dvb/video.h>
 #include <linux/lp.h>
 
+#include <linux/netconsole.h>
+
 static int do_ioctl32_pointer(unsigned int fd, unsigned int cmd,
 			      unsigned long arg, struct file *f)
 {
Index: linux-mm/include/linux/compat_ioctl.h
===================================================================
--- linux-mm.orig/include/linux/compat_ioctl.h
+++ linux-mm/include/linux/compat_ioctl.h
@@ -828,3 +828,6 @@ COMPATIBLE_IOCTL(VIDEO_GET_NAVI)
 COMPATIBLE_IOCTL(VIDEO_SET_ATTRIBUTES)
 COMPATIBLE_IOCTL(VIDEO_GET_SIZE)
 COMPATIBLE_IOCTL(VIDEO_GET_FRAME_RATE)
+/* netconsole */
+COMPATIBLE_IOCTL(NETCON_ADD_TARGET)
+ULONG_IOCTL(NETCON_REMOVE_TARGET)
Index: linux-mm/include/linux/netconsole.h
===================================================================
--- /dev/null
+++ linux-mm/include/linux/netconsole.h
@@ -0,0 +1,18 @@
+#ifndef __NETCONSOLE_H
+#define __NETCONSOLE_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+struct netconsole_request {
+	__u32 id;
+	__u8 netdev_name[IFNAMSIZ];
+	__u8 remote_mac[ETH_ALEN];
+	__u32 local_ip, remote_ip;
+	__u16 local_port, remote_port;
+};
+
+#define NETCON_ADD_TARGET _IOW(0xAE, 4, struct netconsole_request)
+#define NETCON_REMOVE_TARGET _IOW(0xAE, 5, int)
+
+#endif /* __NETCONSOLE_H */
Index: linux-mm/drivers/net/netconsole.c
===================================================================
--- linux-mm.orig/drivers/net/netconsole.c
+++ linux-mm/drivers/net/netconsole.c
@@ -47,6 +47,7 @@
 #include <linux/netpoll.h>
 #include <linux/miscdevice.h>
 #include <linux/inet.h>
+#include <linux/netconsole.h>
 
 MODULE_AUTHOR("Maintainer: Matt Mackall <mpm@selenic.com>");
 MODULE_DESCRIPTION("Console driver for network interfaces");
@@ -306,6 +307,64 @@ static void release_target(struct kobjec
 	delete_target(nt);
 }
 
+static int netconsole_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg)
+{
+	int id, count;
+	char config[256];
+	char *cur;
+	struct netconsole_request req;
+	struct netconsole_target *nt, *tmp;
+	void __user *argp = (void __user *)arg;
+
+	switch (cmd) {
+	case NETCON_ADD_TARGET:
+		printk(KERN_INFO "netconsole: cmd=NETCON_ADD_TARGET\n");
+		if (copy_from_user(&req, argp, sizeof(req)))
+			return -EFAULT;
+		cur = config;
+		count = sprintf(cur, "%d@", req.local_port);
+		cur += count;
+		if (req.local_ip)
+			count = sprintf(cur, "%d.%d.%d.%d/",
+					NIPQUAD(req.local_ip));
+		else
+			count = sprintf(cur, "/");
+		cur += count;
+		count = sprintf(cur, "%s,", req.netdev_name);
+		cur += count;
+		count = sprintf(cur, "%d@", req.remote_port);
+		cur += count;
+		count = sprintf(cur, "%d.%d.%d.%d/",
+				NIPQUAD(req.remote_ip));
+		cur += count;
+		count = sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x",
+				req.remote_mac[0], req.remote_mac[1],
+				req.remote_mac[2], req.remote_mac[3],
+				req.remote_mac[4], req.remote_mac[5]);
+		printk(KERN_INFO "count = %d config=[%s]\n", count, config);
+		if (add_target(config))
+			return -EINVAL;
+		break;
+	case NETCON_REMOVE_TARGET:
+		printk(KERN_INFO "netconsole: cmd=NETCON_REMOVE_TARGET\n");
+		if (copy_from_user(&id, argp, sizeof(int)))
+			return -EFAULT;
+		printk(KERN_INFO "netconsole: id=%d\n", id);
+		list_for_each_entry_safe(nt, tmp, &target_list, list) {
+			if (nt->id == id) {
+				kobject_unregister(&nt->obj);
+				break;
+			}
+		}
+		break;
+	default:
+		return -ENOTTY;
+	}
+
+	return 0;
+}
+
 static struct sysfs_ops target_sysfs_ops = {
 	.show = show_target_attr,
 	.store = store_target_attr
@@ -317,9 +376,14 @@ static struct kobj_type target_ktype = {
 	.default_attrs = target_attrs,
 };
 
+static struct file_operations miscdev_fops = {
+	.ioctl = netconsole_ioctl,
+};
+
 static struct miscdevice netconsole_miscdev = {
 	.minor = MISC_DYNAMIC_MINOR,
 	.name = "netconsole",
+	.fops = &miscdev_fops,
 };
 
 static struct netpoll np = {

-- 



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 2/6][resend] support multiple logging
  2007-03-20 12:26 ` [RFC][PATCH -mm take3 2/6][resend] support multiple logging Keiichi KII
@ 2007-03-20 12:34   ` Alexey Dobriyan
  2007-03-22 10:03     ` Keiichi KII
  0 siblings, 1 reply; 13+ messages in thread
From: Alexey Dobriyan @ 2007-03-20 12:34 UTC (permalink / raw)
  To: Keiichi KII; +Cc: mpm, linux-kernel, netdev

On 3/20/07, Keiichi KII <k-keiichi@bx.jp.nec.com> wrote:
> This patch contains the following changes for supporting multiple logging
>  agents.

> +#define CONFIG_SEPARATOR ";"

CONFIG_* is reserved for configuration options. Since you use
it in only one place just use semicolon directly.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target
  2007-03-20 12:34 ` [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target Keiichi KII
@ 2007-03-20 12:50   ` Alexey Dobriyan
  2007-03-20 16:59     ` Stephen Hemminger
  2007-03-22 10:05   ` Keiichi KII
  1 sibling, 1 reply; 13+ messages in thread
From: Alexey Dobriyan @ 2007-03-20 12:50 UTC (permalink / raw)
  To: Keiichi KII; +Cc: mpm, linux-kernel, netdev

On 3/20/07, Keiichi KII <k-keiichi@bx.jp.nec.com> wrote:
> We add ioctls for adding/removing target.
> If we use NETCONSOLE_ADD_TARGET ioctl,
> we can dynamically add netconsole target.
> If we use NETCONSOLE_REMOVE_TARGET ioctl,
> we can dynamically remoe netconsole target.
>
> We attach a sample program for ioctl.

> +static int netconsole_ioctl(struct inode *inode, struct file *file,
> +			    unsigned int cmd, unsigned long arg)
> +{
> +	int id, count;
> +	char config[256];
> +	char *cur;
> +	struct netconsole_request req;
> +	struct netconsole_target *nt, *tmp;
> +	void __user *argp = (void __user *)arg;
> +
> +	switch (cmd) {
> +	case NETCON_ADD_TARGET:
> +		printk(KERN_INFO "netconsole: cmd=NETCON_ADD_TARGET\n");
> +		if (copy_from_user(&req, argp, sizeof(req)))
> +			return -EFAULT;
> +		cur = config;
> +		count = sprintf(cur, "%d@", req.local_port);
> +		cur += count;
> +		if (req.local_ip)
> +			count = sprintf(cur, "%d.%d.%d.%d/",
> +					NIPQUAD(req.local_ip));
> +		else
> +			count = sprintf(cur, "/");
> +		cur += count;
> +		count = sprintf(cur, "%s,", req.netdev_name);
> +		cur += count;
> +		count = sprintf(cur, "%d@", req.remote_port);
> +		cur += count;
> +		count = sprintf(cur, "%d.%d.%d.%d/",
> +				NIPQUAD(req.remote_ip));
> +		cur += count;
> +		count = sprintf(cur, "%02x:%02x:%02x:%02x:%02x:%02x",
> +				req.remote_mac[0], req.remote_mac[1],
> +				req.remote_mac[2], req.remote_mac[3],
> +				req.remote_mac[4], req.remote_mac[5]);
> +		printk(KERN_INFO "count = %d config=[%s]\n", count, config);
> +		if (add_target(config))
> +			return -EINVAL;
> +		break;
> +	case NETCON_REMOVE_TARGET:
> +		printk(KERN_INFO "netconsole: cmd=NETCON_REMOVE_TARGET\n");
> +		if (copy_from_user(&id, argp, sizeof(int)))
> +			return -EFAULT;
> +		printk(KERN_INFO "netconsole: id=%d\n", id);
> +		list_for_each_entry_safe(nt, tmp, &target_list, list) {
> +			if (nt->id == id) {
> +				kobject_unregister(&nt->obj);
> +				break;
> +			}
> +		}
> +		break;
> +	default:
> +		return -ENOTTY;
> +	}
> +
> +	return 0;
> +}

If you go with misc device, then implement ->write method so you, say,
do

     echo "add [same format as with module parameter]" >/dev/netconsole

and avoid all that additional programs and ioctls.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 1/6][resend] marking __init
  2007-03-20 12:24 ` [RFC][PATCH -mm take3 1/6][resend] marking __init Keiichi KII
@ 2007-03-20 15:36   ` Matt Mackall
  0 siblings, 0 replies; 13+ messages in thread
From: Matt Mackall @ 2007-03-20 15:36 UTC (permalink / raw)
  To: Keiichi KII; +Cc: linux-kernel, netdev

On Tue, Mar 20, 2007 at 09:24:18PM +0900, Keiichi KII wrote:
> From: Keiichi KII <k-keiichi@bx.jp.nec.com>
> 
> This patch contains the following cleanups.
>  - add __init for initialization functions(option_setup() and
>    init_netconsole()).
> 
> Signed-off-by: Keiichi KII <k-keiichi@bx.jp.nec.com>
> Signed-off-by: Takayoshi Kochi <t-kochi@bq.jp.nec.com>
> ---
> Index: linux-mm/drivers/net/netconsole.c
> ===================================================================
> --- linux-mm.orig/drivers/net/netconsole.c
> +++ linux-mm/drivers/net/netconsole.c
> @@ -91,7 +91,7 @@ static struct console netconsole = {
>  	.write = write_msg
>  };
>  
> -static int option_setup(char *opt)
> +static int __init option_setup(char *opt)
>  {
>  	configured = !netpoll_parse_options(&np, opt);
>  	return 1;
> @@ -99,7 +99,7 @@ static int option_setup(char *opt)
>  
>  __setup("netconsole=", option_setup);
>  
> -static int init_netconsole(void)
> +static int __init init_netconsole(void)
>  {
>  	int err;

This is fine.

Acked-by: Matt Mackall <mpm@selenic.com>

-- 
Mathematics is the supreme nostalgia of our time.

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target
  2007-03-20 12:50   ` Alexey Dobriyan
@ 2007-03-20 16:59     ` Stephen Hemminger
  0 siblings, 0 replies; 13+ messages in thread
From: Stephen Hemminger @ 2007-03-20 16:59 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: Keiichi KII, mpm, linux-kernel, netdev

Since these are network device related ioctl's it might be clearer (and easier)
to use network device (struct ifreq) style ioctl's.


-- 
Stephen Hemminger <shemminger@linux-foundation.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 2/6][resend] support multiple logging
  2007-03-20 12:34   ` Alexey Dobriyan
@ 2007-03-22 10:03     ` Keiichi KII
  0 siblings, 0 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-22 10:03 UTC (permalink / raw)
  To: Alexey Dobriyan; +Cc: mpm, linux-kernel, netdev

Alexey Dobriyan wrote:
> On 3/20/07, Keiichi KII <k-keiichi@bx.jp.nec.com> wrote:
>> This patch contains the following changes for supporting multiple logging
>>  agents.
> 
>> +#define CONFIG_SEPARATOR ";"
> 
> CONFIG_* is reserved for configuration options. Since you use
> it in only one place just use semicolon directly.

Thank you for your reply.
I'm going to fix this when I send patches next time.



^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target
  2007-03-20 12:34 ` [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target Keiichi KII
  2007-03-20 12:50   ` Alexey Dobriyan
@ 2007-03-22 10:05   ` Keiichi KII
  1 sibling, 0 replies; 13+ messages in thread
From: Keiichi KII @ 2007-03-22 10:05 UTC (permalink / raw)
  To: Keiichi KII; +Cc: mpm, linux-kernel, netdev

Sorry, I sent the incomplete sample program. 
So, I send the complete one again.
Any comments welcom.

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stropts.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <net/if.h>
#include <linux/if_ether.h>
#include <linux/netconsole.h>

#define NETCONSOLE_DEV_NAME "/dev/netconsole"
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))

struct command {
	char *name;
	char *options;
	int (*handle_command)(struct command* command,
			      int argc, char* argv[]);
	void (*usage)(char *msg);
};

extern char *optarg;
extern int opterr, optind, errno;

static void generic_usage(char *msg) {
	fprintf(stderr, "Usage  : netconfig command [option] [args]\n");
	fprintf(stderr, "command: add remove help\n");
	exit(-1);
}

static int handle_command_add(struct command* command, int argc, char** argv)
{
	int i, fd, ch;
	unsigned int address;
	unsigned char mac[ETH_ALEN];
	struct netconsole_request req = {
		.netdev_name = "eth0",
		.local_port = 6665,
		.remote_port = 6666,
		.remote_mac = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
	};

	while ((ch = getopt(argc, argv, command->options)) != -1) {
		switch (ch) {
		case 'p':
			req.local_port = atoi(optarg);
			break;
		case 's':
			address = inet_addr(optarg);
			if (address == -1)
				(*command->usage)("invlid IP address!\n");
			req.local_ip = address;
			break;
		case 'h':
		default:
			(*command->usage)(NULL);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc < 3 || argc > 4)
		(*command->usage)(NULL);

	memcpy(req.netdev_name, argv[0], IFNAMSIZ);
	address = inet_addr(argv[1]);
	if (address == -1)
		(*command->usage)("invlid IP address!\n");
	req.remote_ip = address;
	req.remote_port = atoi(argv[2]);
	if (argc == 4) {
		i = 0;
		mac[i++] = strtol(argv[3], NULL, 16);
		while ((argv[3] = strchr(argv[3], ':')) != NULL) {
			argv[3]++;
			mac[i++] = strtol(argv[3], NULL, 16);
		}
		if (i != ETH_ALEN)
			(*command->usage)("Invalid MAC address!\n");
		memcpy(req.remote_mac, mac, ETH_ALEN);
	}

	fd = open(NETCONSOLE_DEV_NAME, O_RDWR);
	if (fd < 0) {
		fprintf(stderr, "cannot open device" NETCONSOLE_DEV_NAME "\n");
		return -1;
	}

	if(ioctl(fd, NETCON_ADD_TARGET, &req) != 0)
		perror("add");
	close(fd);

	return 0;
}

static void usage_add(char *msg)
{
	if (msg != NULL)
		fprintf(stderr, "%s", msg);
	fprintf(stderr, "Usage  : netconfig add [-options] dev_name remote_ip "
		"remote_port [remote_mac]\n");
	fprintf(stderr, "options:\n");
	fprintf(stderr, "        -p local_port     :local port number\n");
	fprintf(stderr, "        -s local_up       :local IP address\n");
	exit(-1);
}

static int handle_command_remove(struct command *command,
				 int argc, char** argv)
{
	int fd, id, ch;

	while ((ch = getopt(argc, argv, command->options)) != -1) {
		switch (ch) {
		case 'h':
		default:
			(*command->usage)(NULL);
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		(*command->usage)(NULL);

	id = atoi(argv[0]);
	fd = open(NETCONSOLE_DEV_NAME, O_RDWR);
	if (fd < 0) {
		fprintf(stderr, "can't open device " NETCONSOLE_DEV_NAME "\n");
		return -1;
	}
	if(ioctl(fd, NETCON_REMOVE_TARGET, &id) != 0)
		perror("remove");
	close(fd);

	return 0;
}

static void usage_remove(char *msg) {
	fprintf(stderr, "Usage  : netconfig remove id\n");
	exit(-1);
}

static int handle_command_help(struct command *command,
			       int argc, char** argv) {
	(*command->usage)(NULL);

	return 0;
}

static void usage_help(char *msg) {
	generic_usage(NULL);
}

static struct command s_commands[] = {
	{"add", "hp:s:", handle_command_add, usage_add},
	{"remove", "hp:", handle_command_remove, usage_remove},
	{"help", NULL, handle_command_help, usage_help},
};

int main(int argc, char* argv[]) {
	int i;
	struct command *command = NULL;

	for(i = 0; i < ARRAY_SIZE(s_commands); i++) {
		if (argc <= 1)
			break;
		if (strcmp(s_commands[i].name, argv[1]) == 0) {
			command = &s_commands[i];
			break;
		}
	}

	if (command == NULL)
		generic_usage(NULL);
	argc--;
	argv++;

	if (command->handle_command)
		(*command->handle_command)(command, argc, argv);
	else {
		fprintf(stderr, "function handle_command() isn't set.");
		exit(-1);
	}
	return 0;
}




^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-03-22 10:05 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-20 12:10 [RFC][PATCH -mm take3 0/6][resend] proposal for dynamic configurable netconsole Keiichi KII
2007-03-20 12:24 ` [RFC][PATCH -mm take3 1/6][resend] marking __init Keiichi KII
2007-03-20 15:36   ` Matt Mackall
2007-03-20 12:26 ` [RFC][PATCH -mm take3 2/6][resend] support multiple logging Keiichi KII
2007-03-20 12:34   ` Alexey Dobriyan
2007-03-22 10:03     ` Keiichi KII
2007-03-20 12:28 ` [RFC][PATCH -mm take3 3/6][resend] add interface for netconsole using sysfs Keiichi KII
2007-03-20 12:30 ` [RFC][PATCH -mm take3 4/6][resend] using symlink for the net_device Keiichi KII
2007-03-20 12:31 ` [RFC][PATCH -mm take3 5/6][resend] switch function of netpoll Keiichi KII
2007-03-20 12:34 ` [RFC][PATCH -mm take3 6/6][resend] add ioctls for adding/removing target Keiichi KII
2007-03-20 12:50   ` Alexey Dobriyan
2007-03-20 16:59     ` Stephen Hemminger
2007-03-22 10:05   ` Keiichi KII

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).