diff mbox

[4/7] initdev:kernel:Await network init device discovery, v3

Message ID 20090606023409.GA5721@cuplxvomd02.corp.sa.net
State Not Applicable, archived
Delegated to: David Miller
Headers show

Commit Message

David VomLehn June 6, 2009, 2:34 a.m. UTC
Delay IP autoconfiguration until network boot devices have been initialized.
This depends on the boot device discovery code and on the asynchronous
function call infrastructure.

History
v3	Ignore return value from async_schedule call to ip_auto_config_async.
	Change BOOTDEV_* to INITDEV_*.
v2	Change bootdev_* to initdev_*
v1	Initial release

Signed-off-by: David VomLehn <dvomlehn@cisco.com>
---
 net/core/dev.c      |    2 +
 net/ipv4/ipconfig.c |   55 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 56 insertions(+), 1 deletions(-)

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/core/dev.c b/net/core/dev.c
index 308a7d0..2796764 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -93,6 +93,7 @@ 
 #include <linux/ethtool.h>
 #include <linux/notifier.h>
 #include <linux/skbuff.h>
+#include <linux/device.h>
 #include <net/net_namespace.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
@@ -4497,6 +4498,7 @@  int register_netdevice(struct net_device *dev)
 		dev->reg_state = NETREG_UNREGISTERED;
 	}
 
+	initdev_registered(INITDEV_NETDEV_TYPE);
 out:
 	return ret;
 
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c
index 90d22ae..3b1a381 100644
--- a/net/ipv4/ipconfig.c
+++ b/net/ipv4/ipconfig.c
@@ -53,6 +53,7 @@ 
 #include <linux/root_dev.h>
 #include <linux/delay.h>
 #include <linux/nfs_fs.h>
+#include <linux/async.h>
 #include <net/net_namespace.h>
 #include <net/arp.h>
 #include <net/ip.h>
@@ -182,12 +183,48 @@  struct ic_device {
 static struct ic_device *ic_first_dev __initdata = NULL;/* List of open device */
 static struct net_device *ic_dev __initdata = NULL;	/* Selected device */
 
+/*
+ * Wait for required network devices to come up
+ * If the networking device name was specified on the kernel command line
+ * and that device is now registered, we have the device we want to configure
+ * and we return true. Otherwise, we return false. So, if no device was
+ * specified on the command line, we wait for all possible network devices to
+ * be initialized.
+ */
+static bool have_all_netdevs(void)
+{
+	struct net_device *dev;
+	bool	result = false;
+
+	rtnl_lock();
+
+	for_each_netdev(&init_net, dev) {
+		if (dev->flags & IFF_LOOPBACK)
+			continue;
+
+		/* If a specific device name was specified and that name is
+		 * registered, we have the device we need. */
+		if (user_dev_name[0] && !strcmp(dev->name, user_dev_name)) {
+			result = true;
+			break;
+		}
+	}
+
+	rtnl_unlock();
+
+	return result;
+
+}
+
 static int __init ic_open_devs(void)
 {
 	struct ic_device *d, **last;
 	struct net_device *dev;
 	unsigned short oflags;
 
+	/* Wait for networking devices */
+	initdev_wait(INITDEV_NETDEV_TYPE, have_all_netdevs);
+
 	last = &ic_first_dev;
 	rtnl_lock();
 
@@ -1263,6 +1300,7 @@  __be32 __init root_nfs_parse_addr(char *name)
 
 /*
  *	IP Autoconfig dispatcher.
+ *	Return zero on success, negative one on failure
  */
 
 static int __init ip_auto_config(void)
@@ -1397,7 +1435,22 @@  static int __init ip_auto_config(void)
 	return 0;
 }
 
-late_initcall(ip_auto_config);
+static void __init ip_auto_config_async(void *data, async_cookie_t cookie)
+{
+	ip_auto_config();
+}
+
+/*
+ * Start a thread to do IP autoconfiguration
+ */
+static int __init ip_auto_configurator(void)
+{
+	async_schedule(ip_auto_config_async, NULL);
+
+	return 0;
+}
+
+late_initcall(ip_auto_configurator);
 
 
 /*