login
Header Space

 
 

Re: [PATCH 3/14][TUN]: Introduce the tun_net structure.

Previous thread: [PATCH]: net/bonding: Enable to change device type before enslaving by Moni Shoua on Thursday, April 10, 2008 - 11:09 am. (5 messages)

Next thread: [PATCH] [NET] [ISDN]: Do not validate ISDN net device address prior to interface-up by Paul Bolle on Thursday, April 10, 2008 - 11:00 am. (13 messages)
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 10:57 am

Hi, guys.

I've recently sent a TUN devices virtualization, but it was rejected
by Dave, since the struct net is becoming a dumping ground.

I agree with him - we really need some way to register on-net data
dynamically. That's my view of such a thing and two examples of how
to use it (TUN and VLAN devices virtualization).

If this will be found good, I'll send these sets to David, hoping he
will accept them :)

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;
--
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 11:42 am

Pavel,

seems to be a smart solution :)

I am just afraid with the performances when the network resources are to 
be accessed in the fast path like a routing table (that seems not to be 
the case for tun and vlan). Shall we assume the fast path should always 
go to struct net and non critical path can go to net_generic ?

   -- Daniel
--
To: Daniel Lezcano <dlezcano@...>
Cc: Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 11:57 am

Hm... I put call to net_generic() into tunnels rcv call and measured 
the performance with netperf - no performance penalty. I tried to make 
net_generic() work w/o any locks and looks like I've managed to make 
it fast enough :)

I think, that core kernel code and protocols should/may use the struct 
net, while modules are better to work via generic pointers. However, if
the generic pointers cause noticeable performance degradation, then we

--
To: <xemul@...>
Cc: <dlezcano@...>, <netdev@...>, <den@...>, <containers@...>, <benjamin.thery@...>
Date: Friday, April 11, 2008 - 2:11 pm

From: Pavel Emelyanov &lt;xemul@openvz.org&gt;

This sounds fine.
--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:23 am

The preparations to this are done with my patch, that fixed 
proc on vlan device rename. 

This makes /proc/net/vlan/&lt;device&gt; file migrate from one
proc tree to another...

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 7e9d22e..2a739ad 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -154,8 +154,6 @@ void unregister_vlan_dev(struct net_device *dev)
 	grp = __vlan_find_group(real_dev);
 	BUG_ON(!grp);
 
-	vlan_proc_rem_dev(dev);
-
 	/* Take it out of our own structures, but be sure to interlock with
 	 * HW accelerating devices or SW vlan input packet processing.
 	 */
@@ -278,9 +276,6 @@ int register_vlan_dev(struct net_device *dev)
 	if (real_dev-&gt;features &amp; NETIF_F_HW_VLAN_FILTER)
 		real_dev-&gt;vlan_rx_add_vid(real_dev, vlan_id);
 
-	if (vlan_proc_add_dev(dev) &lt; 0)
-		pr_warning("8021q: failed to add proc entry for %s\n",
-			   dev-&gt;name);
 	return 0;
 
 out_free_group:
@@ -396,6 +391,14 @@ static void __vlan_device_event(struct net_device *dev, unsigned long event)
 			pr_warning("8021q: failed to change proc name for %s\n",
 					dev-&gt;name);
 		break;
+	case NETDEV_REGISTER:
+		if (vlan_proc_add_dev(dev) &lt; 0)
+			pr_warning("8021q: failed to add proc entry for %s\n",
+					dev-&gt;name);
+		break;
+	case NETDEV_UNREGISTER:
+		vlan_proc_rem_dev(dev);
+		break;
 	}
 }
 
-- 
1.5.3.4

--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:22 am

This one is similar to what I've done for TUN - set the proper
net after device allocation and clean VLANs on net exit.

Plus, drop explicit init_net usage.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.c         |    7 +++----
 net/8021q/vlan_dev.c     |    3 ---
 net/8021q/vlan_netlink.c |    2 +-
 3 files changed, 4 insertions(+), 8 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 5cacad0..7e9d22e 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -340,6 +340,7 @@ static int register_vlan_device(struct net_device *real_dev,
 	if (new_dev == NULL)
 		return -ENOBUFS;
 
+	dev_net_set(new_dev, net);
 	/* need 4 bytes for extra VLAN header info,
 	 * hope the underlying device can handle it.
 	 */
@@ -406,9 +407,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event,
 	int i, flgs;
 	struct net_device *vlandev;
 
-	if (dev_net(dev) != &amp;init_net)
-		return NOTIFY_DONE;
-
 	if (is_vlan_dev(dev)) {
 		__vlan_device_event(dev, event);
 		goto out;
@@ -534,7 +532,7 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 	case GET_VLAN_REALDEV_NAME_CMD:
 	case GET_VLAN_VID_CMD:
 		err = -ENODEV;
-		dev = __dev_get_by_name(&amp;init_net, args.device1);
+		dev = __dev_get_by_name(net, args.device1);
 		if (!dev)
 			goto out;
 
@@ -665,6 +663,7 @@ static void vlan_exit_net(struct net *net)
 	struct vlan_net *vn;
 
 	vn = net_generic(net, vlan_net_id);
+	rtnl_kill_links(net, &amp;vlan_link_ops);
 	vlan_proc_cleanup(net);
 	kfree(vn);
 }
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c
index 0e3b2d3..9fa6b90 100644
--- a/net/8021q/vlan_dev.c
+++ b/net/8021q/vlan_dev.c
@@ -153,9 +153,6 @@ int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev,
 	struct net_device_stats *stats;
 	unsigned short vlan_TCI;
 
-	if (dev_net(dev) != &amp;init_net)
-		goto err_free;
-
 	skb = skb_share_check(skb, GFP_ATOMIC);
 	if (skb == NULL)
 		goto err_free;
diff...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:20 am

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.c     |   14 +++++++++-----
 net/8021q/vlan.h     |    4 ++--
 net/8021q/vlanproc.c |    7 +++++--
 3 files changed, 16 insertions(+), 9 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 541542e..5cacad0 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -52,9 +52,6 @@ static char vlan_version[] = DRV_VERSION;
 static char vlan_copyright[] = "Ben Greear &lt;greearb@candelatech.com&gt;";
 static char vlan_buggyright[] = "David S. Miller &lt;davem@redhat.com&gt;";
 
-/* Determines interface naming scheme. */
-unsigned short vlan_name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PAD;
-
 static struct packet_type vlan_packet_type = {
 	.type = __constant_htons(ETH_P_8021Q),
 	.func = vlan_skb_recv, /* VLAN receive method */
@@ -299,6 +296,8 @@ static int register_vlan_device(struct net_device *real_dev,
 				unsigned short VLAN_ID)
 {
 	struct net_device *new_dev;
+	struct net *net = dev_net(real_dev);
+	struct vlan_net *vn = net_generic(net, vlan_net_id);
 	char name[IFNAMSIZ];
 	int err;
 
@@ -310,7 +309,7 @@ static int register_vlan_device(struct net_device *real_dev,
 		return err;
 
 	/* Gotta set up the fields for the device. */
-	switch (vlan_name_type) {
+	switch (vn-&gt;name_type) {
 	case VLAN_NAME_TYPE_RAW_PLUS_VID:
 		/* name will look like:	 eth1.0005 */
 		snprintf(name, IFNAMSIZ, "%s.%.4i", real_dev-&gt;name, VLAN_ID);
@@ -580,7 +579,10 @@ static int vlan_ioctl_handler(struct net *net, void __user *arg)
 			break;
 		if ((args.u.name_type &gt;= 0) &amp;&amp;
 		    (args.u.name_type &lt; VLAN_NAME_TYPE_HIGHEST)) {
-			vlan_name_type = args.u.name_type;
+			struct vlan_net *vn;
+
+			vn = net_generic(net, vlan_net_id);
+			vn-&gt;name_type = args.u.name_type;
 			err = 0;
 		} else {
 			err = -EINVAL;
@@ -642,6 +644,8 @@ static int vlan_init_net(struct net *net)
 	if (err &lt; 0)
 		goto err_assign;
 
+	vn-&gt;name_type = VLAN_NAME_TYPE_RAW_PLUS_VID_NO_PA...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:19 am

And this one if PATCH #9 part 3 :)
After this proc may show relevant to each net namespace info.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlanproc.c |   13 ++++++++-----
 1 files changed, 8 insertions(+), 5 deletions(-)

diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 995544b..cc17b72 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -80,7 +80,8 @@ static const struct seq_operations vlan_seq_ops = {
 
 static int vlan_seq_open(struct inode *inode, struct file *file)
 {
-	return seq_open(file, &amp;vlan_seq_ops);
+	return seq_open_net(inode, file, &amp;vlan_seq_ops,
+			sizeof(struct seq_net_private));
 }
 
 static const struct file_operations vlan_fops = {
@@ -88,7 +89,7 @@ static const struct file_operations vlan_fops = {
 	.open    = vlan_seq_open,
 	.read    = seq_read,
 	.llseek  = seq_lseek,
-	.release = seq_release,
+	.release = seq_release_net,
 };
 
 /*
@@ -211,6 +212,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 	__acquires(dev_base_lock)
 {
 	struct net_device *dev;
+	struct net *net = seq_file_net(seq);
 	loff_t i = 1;
 
 	read_lock(&amp;dev_base_lock);
@@ -218,7 +220,7 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 	if (*pos == 0)
 		return SEQ_START_TOKEN;
 
-	for_each_netdev(&amp;init_net, dev) {
+	for_each_netdev(net, dev) {
 		if (!is_vlan_dev(dev))
 			continue;
 
@@ -232,14 +234,15 @@ static void *vlan_seq_start(struct seq_file *seq, loff_t *pos)
 static void *vlan_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct net_device *dev;
+	struct net *net = seq_file_net(seq);
 
 	++*pos;
 
 	dev = (struct net_device *)v;
 	if (v == SEQ_START_TOKEN)
-		dev = net_device_entry(&amp;init_net.dev_base_head);
+		dev = net_device_entry(&amp;net-&gt;dev_base_head);
 
-	for_each_netdev_continue(&amp;init_net, dev) {
+	for_each_netdev_continue(net, dev) {
 		if (!is_vlan_dev(dev))
 			continue;
 
-- 
1.5.3.4

--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:18 am

This is essentially a PATCH #9 part 2 - use the net
pointer passed in.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.h     |    6 ++++++
 net/8021q/vlanproc.c |   44 +++++++++++++++++---------------------------
 2 files changed, 23 insertions(+), 27 deletions(-)

diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h
index f27d8d6..7258357 100644
--- a/net/8021q/vlan.h
+++ b/net/8021q/vlan.h
@@ -52,7 +52,13 @@ static inline int is_vlan_dev(struct net_device *dev)
 
 extern int vlan_net_id;
 
+struct proc_dir_entry;
+
 struct vlan_net {
+	/* /proc/net/vlan */
+	struct proc_dir_entry *proc_vlan_dir;
+	/* /proc/net/vlan/config */
+	struct proc_dir_entry *proc_vlan_conf;
 };
 
 #endif /* !(__BEN_VLAN_802_1Q_INC__) */
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 4d13aeb..995544b 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -34,6 +34,7 @@
 #include &lt;linux/netdevice.h&gt;
 #include &lt;linux/if_vlan.h&gt;
 #include &lt;net/net_namespace.h&gt;
+#include &lt;net/netns/generic.h&gt;
 #include "vlanproc.h"
 #include "vlan.h"
 
@@ -111,18 +112,6 @@ static const struct file_operations vlandev_fops = {
  * Proc filesystem derectory entries.
  */
 
-/*
- *	/proc/net/vlan
- */
-
-static struct proc_dir_entry *proc_vlan_dir;
-
-/*
- *	/proc/net/vlan/config
- */
-
-static struct proc_dir_entry *proc_vlan_conf;
-
 /* Strings */
 static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
     [VLAN_NAME_TYPE_RAW_PLUS_VID]        = "VLAN_NAME_TYPE_RAW_PLUS_VID",
@@ -140,14 +129,13 @@ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHEST] = {
 
 void vlan_proc_cleanup(struct net *net)
 {
-	if (net != &amp;init_net)
-		return;
+	struct vlan_net *vn = net_generic(net, vlan_net_id);
 
-	if (proc_vlan_conf)
-		remove_proc_entry(name_conf, proc_vlan_dir);
+	if (vn-&gt;proc_vlan_conf)
+		remove_proc_entry(name_conf, vn-&gt;proc_vlan_dir);
 
-	if (proc_vlan_dir)
-		proc_net_remove(&amp;init_...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:16 am

Proc files will be created in each net, so prepare them for this
change just to make patches smaller.

The net != &amp;init_net checks in them are for git-bisect sanity, but
I'll drop them soon.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.c     |   15 +++++++--------
 net/8021q/vlanproc.c |   12 +++++++++---
 net/8021q/vlanproc.h |   10 ++++++----
 3 files changed, 22 insertions(+), 15 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 9296601..541542e 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -642,8 +642,14 @@ static int vlan_init_net(struct net *net)
 	if (err &lt; 0)
 		goto err_assign;
 
+	err = vlan_proc_init(net);
+	if (err &lt; 0)
+		goto err_proc;
+
 	return 0;
 
+err_proc:
+	/* nothing */
 err_assign:
 	kfree(vn);
 err_alloc:
@@ -655,6 +661,7 @@ static void vlan_exit_net(struct net *net)
 	struct vlan_net *vn;
 
 	vn = net_generic(net, vlan_net_id);
+	vlan_proc_cleanup(net);
 	kfree(vn);
 }
 
@@ -674,10 +681,6 @@ static int __init vlan_proto_init(void)
 	if (err &lt; 0)
 		goto err0;
 
-	err = vlan_proc_init();
-	if (err &lt; 0)
-		goto err1;
-
 	err = register_netdevice_notifier(&amp;vlan_notifier_block);
 	if (err &lt; 0)
 		goto err2;
@@ -693,8 +696,6 @@ static int __init vlan_proto_init(void)
 err3:
 	unregister_netdevice_notifier(&amp;vlan_notifier_block);
 err2:
-	vlan_proc_cleanup();
-err1:
 	unregister_pernet_gen_device(vlan_net_id, &amp;vlan_net_ops);
 err0:
 	return err;
@@ -715,8 +716,6 @@ static void __exit vlan_cleanup_module(void)
 	for (i = 0; i &lt; VLAN_GRP_HASH_SIZE; i++)
 		BUG_ON(!hlist_empty(&amp;vlan_group_hash[i]));
 
-	vlan_proc_cleanup();
-
 	unregister_pernet_gen_device(vlan_net_id, &amp;vlan_net_ops);
 
 	synchronize_net();
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c
index 24cd96e..4d13aeb 100644
--- a/net/8021q/vlanproc.c
+++ b/net/8021q/vlanproc.c
@@ -138,8 +138,11 @@ static const char *vlan_name_type_str[VLAN_NAME_TYPE_HIGHE...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:14 am

It is empty now, but it will be populated later.
And it uses net generic pointers like TUN does.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 net/8021q/vlan.c |   46 ++++++++++++++++++++++++++++++++++++++++++++++
 net/8021q/vlan.h |    5 +++++
 2 files changed, 51 insertions(+), 0 deletions(-)

diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index cf8d810..9296601 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -32,6 +32,7 @@
 #include &lt;linux/rtnetlink.h&gt;
 #include &lt;linux/notifier.h&gt;
 #include &lt;net/net_namespace.h&gt;
+#include &lt;net/netns/generic.h&gt;
 
 #include &lt;linux/if_vlan.h&gt;
 #include "vlan.h"
@@ -41,6 +42,8 @@
 
 /* Global VLAN variables */
 
+int vlan_net_id;
+
 /* Our listing of VLAN group(s) */
 static struct hlist_head vlan_group_hash[VLAN_GRP_HASH_SIZE];
 
@@ -625,6 +628,41 @@ out:
 	return err;
 }
 
+static int vlan_init_net(struct net *net)
+{
+	int err;
+	struct vlan_net *vn;
+
+	err = -ENOMEM;
+	vn = kzalloc(sizeof(struct vlan_net), GFP_KERNEL);
+	if (vn == NULL)
+		goto err_alloc;
+
+	err = net_assign_generic(net, vlan_net_id, vn);
+	if (err &lt; 0)
+		goto err_assign;
+
+	return 0;
+
+err_assign:
+	kfree(vn);
+err_alloc:
+	return err;
+}
+
+static void vlan_exit_net(struct net *net)
+{
+	struct vlan_net *vn;
+
+	vn = net_generic(net, vlan_net_id);
+	kfree(vn);
+}
+
+static struct pernet_operations vlan_net_ops = {
+	.init = vlan_init_net,
+	.exit = vlan_exit_net,
+};
+
 static int __init vlan_proto_init(void)
 {
 	int err;
@@ -632,6 +670,10 @@ static int __init vlan_proto_init(void)
 	pr_info("%s v%s %s\n", vlan_fullname, vlan_version, vlan_copyright);
 	pr_info("All bugs added by %s\n", vlan_buggyright);
 
+	err = register_pernet_gen_device(&amp;vlan_net_id, &amp;vlan_net_ops);
+	if (err &lt; 0)
+		goto err0;
+
 	err = vlan_proc_init();
 	if (err &lt; 0)
 		goto err1;
@@ -653,6 +695,8 @@ err3:
 err2:
 	vlan_proc_cleanup();
 err1:
+	unregister_pernet_gen_dev...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:13 am

We'll have to lookup the vlan_group by two keys - ifindex and
net. Turning the vlan_group lookup key to struct net_device
pointer will make this process easier.

Besides, this will eliminate one more place in the networking,
that assumes that indexes are unique in the kernel.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 include/linux/if_vlan.h |    4 +++-
 net/8021q/vlan.c        |   22 +++++++++++-----------
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index edd55af..15ace02 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -81,7 +81,9 @@ extern void vlan_ioctl_set(int (*hook)(struct net *, void __user *));
 #define VLAN_GROUP_ARRAY_PART_LEN     (VLAN_GROUP_ARRAY_LEN/VLAN_GROUP_ARRAY_SPLIT_PARTS)
 
 struct vlan_group {
-	int real_dev_ifindex; /* The ifindex of the ethernet(like) device the vlan is attached to. */
+	struct net_device	*real_dev; /* The ethernet(like) device
+					    * the vlan is attached to.
+					    */
 	unsigned int		nr_vlans;
 	struct hlist_node	hlist;	/* linked list */
 	struct net_device **vlan_devices_arrays[VLAN_GROUP_ARRAY_SPLIT_PARTS];
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c
index 5975ec3..cf8d810 100644
--- a/net/8021q/vlan.c
+++ b/net/8021q/vlan.c
@@ -65,14 +65,14 @@ static inline unsigned int vlan_grp_hashfn(unsigned int idx)
 }
 
 /* Must be invoked with RCU read lock (no preempt) */
-static struct vlan_group *__vlan_find_group(int real_dev_ifindex)
+static struct vlan_group *__vlan_find_group(struct net_device *real_dev)
 {
 	struct vlan_group *grp;
 	struct hlist_node *n;
-	int hash = vlan_grp_hashfn(real_dev_ifindex);
+	int hash = vlan_grp_hashfn(real_dev-&gt;ifindex);
 
 	hlist_for_each_entry_rcu(grp, n, &amp;vlan_group_hash[hash], hlist) {
-		if (grp-&gt;real_dev_ifindex == real_dev_ifindex)
+		if (grp-&gt;real_dev == real_dev)
 			return grp;
 	}
 
@@ -86,7 +86,7 @@ static struct vlan_group *__vlan_find_group(...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:10 am

... which will kill all the devices in the given net with
the given rtnl_link_ops. Will be used in VLAN patches later.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 include/net/rtnetlink.h |    1 +
 net/core/rtnetlink.c    |   29 +++++++++++++++++++++--------
 2 files changed, 22 insertions(+), 8 deletions(-)

diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h
index 793863e..3c1895e 100644
--- a/include/net/rtnetlink.h
+++ b/include/net/rtnetlink.h
@@ -74,6 +74,7 @@ struct rtnl_link_ops {
 
 extern int	__rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	__rtnl_link_unregister(struct rtnl_link_ops *ops);
+extern void	rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops);
 
 extern int	rtnl_link_register(struct rtnl_link_ops *ops);
 extern void	rtnl_link_unregister(struct rtnl_link_ops *ops);
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index da99ac0..bc39e41 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -269,6 +269,26 @@ int rtnl_link_register(struct rtnl_link_ops *ops)
 
 EXPORT_SYMBOL_GPL(rtnl_link_register);
 
+static void __rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+	struct net_device *dev;
+restart:
+	for_each_netdev(net, dev) {
+		if (dev-&gt;rtnl_link_ops == ops) {
+			ops-&gt;dellink(dev);
+			goto restart;
+		}
+	}
+}
+
+void rtnl_kill_links(struct net *net, struct rtnl_link_ops *ops)
+{
+	rtnl_lock();
+	__rtnl_kill_links(net, ops);
+	rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(rtnl_kill_links);
+
 /**
  * __rtnl_link_unregister - Unregister rtnl_link_ops from rtnetlink.
  * @ops: struct rtnl_link_ops * to unregister
@@ -277,17 +297,10 @@ EXPORT_SYMBOL_GPL(rtnl_link_register);
  */
 void __rtnl_link_unregister(struct rtnl_link_ops *ops)
 {
-	struct net_device *dev, *n;
 	struct net *net;
 
 	for_each_net(net) {
-restart:
-		for_each_netdev_safe(net, dev, n) {
-			if (dev-&gt;rtnl_link_ops == ops) {
-				ops-&gt;dellink(dev);
-				goto restart;
-			}
-	...
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Linux Containers <containers@...>, Denis Lunev <den@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 6:09 pm

-- 
Daniel Hokka Zakrisson
--
To: Daniel Hokka Zakrisson <daniel@...>
Cc: Linux Netdev List <netdev@...>, Linux Containers <containers@...>, Denis Lunev <den@...>, Benjamin Thery <benjamin.thery@...>, Patrick McHardy <kaber@...>
Date: Friday, April 11, 2008 - 4:01 am

Yup - we goto restart in case we del some link, so there's no need
in _safe iteration. 

This goto was added by Partick (commit 68365458 [NET]: rtnl_link: 
fix use-after-free) and I suspect he simply forgot to remove the 

--
To: Pavel Emelyanov <xemul@...>
Cc: Daniel Hokka Zakrisson <daniel@...>, Linux Netdev List <netdev@...>, Linux Containers <containers@...>, Denis Lunev <den@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 8:48 am

No, that was an oversight, it should be safe to remove.
--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:09 am

This is basically means that a net is set for a new device, but
actually this involves two more steps:

1. mark the tun device as "local", i.e. do not allow for it to
   move across namespaces.

This is done so, since tun device is most often associated to some
file (and thus to some process) and moving the device alone is not
valid while keeping the file and the process outside (and the tun 
devices are not always "persistent" ;) ).

2. get the tun device's net when tun becomes attached and put one
   when it becomes detached.

This is needed to handle the case when a task owning the tun dies,
but a files lives for some more time - in this case we must not
allow for net to be freed, since its exit hook will spoil that file's
private data by unregistering the tun from under tun_chr_close.

(The TUN virtualization patches were approved by TUN maintainer)

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 drivers/net/tun.c |    4 ++++
 1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 74263a4..893e92f 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -441,6 +441,7 @@ static void tun_setup(struct net_device *dev)
 	dev-&gt;stop = tun_net_close;
 	dev-&gt;ethtool_ops = &amp;tun_ethtool_ops;
 	dev-&gt;destructor = free_netdev;
+	dev-&gt;features |= NETIF_F_NETNS_LOCAL;
 }
 
 static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
@@ -508,6 +509,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 		if (!dev)
 			return -ENOMEM;
 
+		dev_net_set(dev, net);
 		tun = netdev_priv(dev);
 		tun-&gt;dev = dev;
 		tun-&gt;flags = flags;
@@ -547,6 +549,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 
 	file-&gt;private_data = tun;
 	tun-&gt;attached = 1;
+	get_net(dev_net(tun-&gt;dev));
 
 	strcpy(ifr-&gt;ifr_name, tun-&gt;dev-&gt;name);
 	return 0;
@@ -762,6 +765,7 @@ static int tun_chr_close(struct inode *...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:07 am

Remove the static tun_dev_list and replace its occurrences in
driver with per-net one.

It is used in two places - in tun_set_iff and tun_cleanup. In 
the first case it's legal to use current net_ns. In the cleanup
call - move the loop, that unregisters all devices in net exit
hook.

This shows how to use the generic pointer.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 drivers/net/tun.c |   37 +++++++++++++++++++------------------
 1 files changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 9bfba02..74263a4 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -62,6 +62,7 @@
 #include &lt;linux/if_ether.h&gt;
 #include &lt;linux/if_tun.h&gt;
 #include &lt;linux/crc32.h&gt;
+#include &lt;linux/nsproxy.h&gt;
 #include &lt;net/net_namespace.h&gt;
 #include &lt;net/netns/generic.h&gt;
 
@@ -79,7 +80,6 @@ struct tun_net {
 	struct list_head dev_list;
 };
 
-static LIST_HEAD(tun_dev_list);
 static const struct ethtool_ops tun_ethtool_ops;
 
 /* Net device open. */
@@ -443,12 +443,12 @@ static void tun_setup(struct net_device *dev)
 	dev-&gt;destructor = free_netdev;
 }
 
-static struct tun_struct *tun_get_by_name(const char *name)
+static struct tun_struct *tun_get_by_name(struct tun_net *tn, const char *name)
 {
 	struct tun_struct *tun;
 
 	ASSERT_RTNL();
-	list_for_each_entry(tun, &amp;tun_dev_list, list) {
+	list_for_each_entry(tun, &amp;tn-&gt;dev_list, list) {
 		if (!strncmp(tun-&gt;dev-&gt;name, name, IFNAMSIZ))
 		    return tun;
 	}
@@ -456,13 +456,15 @@ static struct tun_struct *tun_get_by_name(const char *name)
 	return NULL;
 }
 
-static int tun_set_iff(struct file *file, struct ifreq *ifr)
+static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
 {
+	struct tun_net *tn;
 	struct tun_struct *tun;
 	struct net_device *dev;
 	int err;
 
-	tun = tun_get_by_name(ifr-&gt;ifr_name);
+	tn = net_generic(net, tun_net_id);
+	tun = tun_get_by_name(tn, ifr-&gt;i...
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:06 am

This is the first step in making tuntap devices work in net 
namespaces. The structure mentioned is pointed by generic
net pointer with tun_net_id id, and tun driver fills one on 
its load. It will contain only the tun devices list.

So declare this structure and introduce net init and exit hooks.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 drivers/net/tun.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 52 insertions(+), 1 deletions(-)

diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index 7b816a0..9bfba02 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -63,6 +63,7 @@
 #include &lt;linux/if_tun.h&gt;
 #include &lt;linux/crc32.h&gt;
 #include &lt;net/net_namespace.h&gt;
+#include &lt;net/netns/generic.h&gt;
 
 #include &lt;asm/system.h&gt;
 #include &lt;asm/uaccess.h&gt;
@@ -73,6 +74,11 @@ static int debug;
 
 /* Network device part of the driver */
 
+static unsigned int tun_net_id;
+struct tun_net {
+	struct list_head dev_list;
+};
+
 static LIST_HEAD(tun_dev_list);
 static const struct ethtool_ops tun_ethtool_ops;
 
@@ -873,6 +879,37 @@ static const struct ethtool_ops tun_ethtool_ops = {
 	.set_rx_csum	= tun_set_rx_csum
 };
 
+static int tun_init_net(struct net *net)
+{
+	struct tun_net *tn;
+
+	tn = kmalloc(sizeof(*tn), GFP_KERNEL);
+	if (tn == NULL)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&amp;tn-&gt;dev_list);
+
+	if (net_assign_generic(net, tun_net_id, tn)) {
+		kfree(tn);
+		return -ENOMEM;
+	}
+
+	return 0;
+}
+
+static void tun_exit_net(struct net *net)
+{
+	struct tun_net *tn;
+
+	tn = net_generic(net, tun_net_id);
+	kfree(tn);
+}
+
+static struct pernet_operations tun_net_ops = {
+	.init = tun_init_net,
+	.exit = tun_exit_net,
+};
+
 static int __init tun_init(void)
 {
 	int ret = 0;
@@ -880,9 +917,22 @@ static int __init tun_init(void)
 	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
 	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
 
+	ret = reg...
To: <xemul@...>
Cc: <netdev@...>, <dlezcano@...>, <den@...>, <containers@...>, <benjamin.thery@...>
Date: Tuesday, April 15, 2008 - 3:44 am

Pavel, please respin these patches since I applied the updated
version of patches 1 and 2 which added the generic netns bits.

Thanks!
--
To: David Miller <davem@...>
Cc: <netdev@...>, <dlezcano@...>, <den@...>, <containers@...>, <benjamin.thery@...>
Date: Tuesday, April 15, 2008 - 6:31 am

Thank you, David! I will do it today.

Are you willing to look at vlans and ip tunnels (ipip, gre, sit) as 

--
To: <xemul@...>
Cc: <netdev@...>, <dlezcano@...>, <den@...>, <containers@...>, <benjamin.thery@...>
Date: Tuesday, April 15, 2008 - 6:06 am

From: Pavel Emelyanov &lt;xemul@openvz.org&gt;

Sure.
--
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 9:01 pm

OK, I have to ask...  What prevents someone else from invoking
net_generic() concurrently with a call to tun_exit_net(), potentially
obtaining a pointer to the structure that tun_exit_net() is about
to kfree()?

--
To: <paulmck@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 3:55 am

It's the same as if the tun_net was directly pointed by the struct 
net. Nobody can grant, that the pointer got by you from the struct
net is not going to become free, unless you provide this security
by yourself.

But if you call net_generic to get some pointer other than tun_net,
then you're fine (due to RCU), providing you play the same rules with
the pointer you're getting.

Maybe I'm missing something in your question, can you provide some

--
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 11:04 am

So tun_net acquires some lock before calling net_generic(), and that
same lock is held when calling tun_exit_net()?  Or is there but a
single tun_net task, so that it will never call tun_net_exit()

Agreed, RCU protects the net_generic structure, but not the structures

Just trying to understand what prevents one task from calling
net_generic() to pick up the tun_net pointer at the same time some other
task calls tun_net_exit().

--
To: <paulmck@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 11:45 am

tun_net_exit is called only when a struct net is no longer referenced
and is going to be kfree-ed itself, so it's impossible (or BUGy by its
own) that someone still has a pointer on this net.

Providing the struct net is alive (!), the net-&gt;gen array is alive (or
is scheduled for kfree after RCU grace period). Thus, if your code 
holds the net and uses the net_generic() call, then it will get alive 
net-&gt;gen array and alive tun_net pointer.

Next, what happens after net_generic() completes and leaves the RCU-read 
section? Simple - the struct net is (should be) still referenced, so the
tun_net_exit cannot yet be called and thus the tun_net pointer obtained
earlier is alive. Unlike the (possibly) former instance of the net_generic
array, but nobody references this one in my code (and should not do so,


If this task dereferences a "held" struct net, then should be OK. If 
this task does not, this will OOPs in any case.

Consider the struct net to look like

struct net {
	...
	void *ptrs[N];
}

and the net_generic to be just

static inline void net_generic(struct net *net, int id)
{
	BUG_ON(id &gt;= N);
	return net-&gt;ptrs[id - 1];
}

That's the same to what I propose, except for the ptrs array is on the

Thanks,
Pavel
--
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 12:27 pm

So RCU is protecting -only- the net_generic structure that net_generic()
is traversing, and the structure returned by net_generic() is protected
by a reference counter in the upper-level struct net.

If this is the approach, I am happy.  ;-)

							Thanx, Paul
--
To: <paulmck@...>
Cc: Linux Netdev List <netdev@...>, Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Saturday, April 12, 2008 - 4:44 am

--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:04 am

Add the elastic array of void * pointer to the struct net.
The access rules are simple:

 1. register the ops with register_pernet_gen_device to get
    the id of your private pointer
 2. call net_assign_generic() to put the private data on the
    struct net (most preferably this should be done in the
    -&gt;init callback of the ops registered)
 3. do not change this pointer while the net is alive;
 4. use the net_generic() to get the pointer.

When adding a new pointer, I copy the old array, replace it
with a new one and schedule the old for kfree after an RCU
grace period.

Since the net_generic explores the net-&gt;gen array inside rcu
read section and once set the net-&gt;gen-&gt;ptr[x] pointer never 
changes, this grants us a safe access to generic pointers.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 include/net/net_namespace.h |    2 +
 include/net/netns/generic.h |   49 ++++++++++++++++++++++++++++++++++
 net/core/net_namespace.c    |   62 +++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 113 insertions(+), 0 deletions(-)
 create mode 100644 include/net/netns/generic.h

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 6971fdb..e3d4eb4 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -19,6 +19,7 @@ struct proc_dir_entry;
 struct net_device;
 struct sock;
 struct ctl_table_header;
+struct net_generic;
 
 struct net {
 	atomic_t		count;		/* To decided when the network
@@ -57,6 +58,7 @@ struct net {
 #ifdef CONFIG_NETFILTER
 	struct netns_xt		xt;
 #endif
+	struct net_generic	*gen;
 };
 
 
diff --git a/include/net/netns/generic.h b/include/net/netns/generic.h
new file mode 100644
index 0000000..e8a6d27
--- /dev/null
+++ b/include/net/netns/generic.h
@@ -0,0 +1,49 @@
+/*
+ * generic net pointers
+ */
+
+#ifndef __NET_GENERIC_H__
+#define __NET_GENERIC_H__
+
+#include &lt;linux/rcupdate.h&gt;
+
+/*
+ * Generic net pointers are to be used by modules
+ * to put...
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 9:43 am

--
To: Daniel Lezcano <dlezcano@...>
Cc: Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 10:29 am

That's just an optimization to avoid many reallocations in the
nearest future. I planned to make similar in net_assign_generic
(allocate a bit more that required), but decided to do it later
to keep net_assign_generic simpler.

Currently I have only 5 users of generic pointers (tun and vlan
you see and I have patches for ipip, ipgre and sit tunnels), so
that's enough for the first time.


Nope - nobody can race with us and change this pointer, so it's
safe to get one without rcu_dereference.

Thanks,
Pavel
--
To: Linux Netdev List <netdev@...>
Cc: Daniel Lezcano <dlezcano@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 11:01 am

To make some per-net generic pointers, we need some way to
address them, i.e. - IDs. This is simple IDA-based IDs
generator for pernet subsystems. They will be used in the
next patches.

Since it will be used by devices only (tun and vlan), I make
it resemble the register_pernet_device functionality.

The new ids is stored in the *id pointer _before_ calling the
init callback to make this id available in this callback.

Signed-off-by: Pavel Emelyanov &lt;xemul@openvz.org&gt;

---
 include/net/net_namespace.h |    2 ++
 net/core/net_namespace.c    |   36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 38 insertions(+), 0 deletions(-)

diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 0ab62ed..6971fdb 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -181,6 +181,8 @@ extern int register_pernet_subsys(struct pernet_operations *);
 extern void unregister_pernet_subsys(struct pernet_operations *);
 extern int register_pernet_device(struct pernet_operations *);
 extern void unregister_pernet_device(struct pernet_operations *);
+extern int register_pernet_gen_device(int *id, struct pernet_operations *);
+extern void unregister_pernet_gen_device(int id, struct pernet_operations *);
 
 struct ctl_path;
 struct ctl_table;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 7b66083..7ef3bac 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -5,6 +5,7 @@
 #include &lt;linux/list.h&gt;
 #include &lt;linux/delay.h&gt;
 #include &lt;linux/sched.h&gt;
+#include &lt;linux/idr.h&gt;
 #include &lt;net/net_namespace.h&gt;
 
 /*
@@ -253,6 +254,8 @@ static void unregister_pernet_operations(struct pernet_operations *ops)
 }
 #endif
 
+static DEFINE_IDA(net_generic_ids);
+
 /**
  *      register_pernet_subsys - register a network namespace subsystem
  *	@ops:  pernet operations structure for the subsystem
@@ -330,6 +333,28 @@ int register_pernet_device(struct pernet_operations *ops)
 ...
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 4:52 pm

-- 






















































Sauf indication contraire ci-dessus:
Compagnie IBM France
Siège Social : Tour Descartes, 2, avenue Gambetta, La Défense 5, 92400
Courbevoie
RCS Nanterre 552 118 465
Forme Sociale : S.A.S.
Capital Social : 542.737.118 ?
SIREN/SIRET : 552 118 465 02430
--
To: Daniel Lezcano <dlezcano@...>
Cc: Paul Menage <menage@...>, Linux Netdev List <netdev@...>, Denis Lunev <den@...>, Linux Containers <containers@...>, Benjamin Thery <benjamin.thery@...>
Date: Friday, April 11, 2008 - 3:56 am

Oops! Thank, will fix.
--
To: Pavel Emelyanov <xemul@...>
Cc: Linux Netdev List <netdev@...>, Linux Containers <containers@...>, Denis Lunev <den@...>, Benjamin Thery <benjamin.thery@...>
Date: Thursday, April 10, 2008 - 1:37 pm

Shouldn't you handle non-EAGAIN errors here?

Paul
--
Previous thread: [PATCH]: net/bonding: Enable to change device type before enslaving by Moni Shoua on Thursday, April 10, 2008 - 11:09 am. (5 messages)

Next thread: [PATCH] [NET] [ISDN]: Do not validate ISDN net device address prior to interface-up by Paul Bolle on Thursday, April 10, 2008 - 11:00 am. (13 messages)
speck-geostationary