aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@maxwell.aristanetworks.com>2008-11-08 01:54:20 -0500
committerDavid S. Miller <davem@davemloft.net>2008-11-08 01:54:20 -0500
commit505d4f73dda9e20d59da05008f1f5eb432613e71 (patch)
treea30032d6474ce1d8dea1853c1907f4c3bdd8a19c
parent5d6d480908300a0c0b3be8b58567dfcef62c83a5 (diff)
net: Guaranetee the proper ordering of the loopback device. v2
I was recently hunting a bug that occurred in network namespace cleanup. In looking at the code it became apparrent that we have and will continue to have cases where if we have anything going on in a network namespace there will be assumptions that the loopback device is present. Things like sending igmp unsubscribe messages when we bring down network devices invokes the routing code which assumes that at least the loopback driver is present. Therefore to avoid magic initcall ordering hackery that is hard to follow and hard to get right insert a call to register the loopback device directly from net_dev_init(). This guarantes that the loopback device is the first device registered and the last network device to go away. But do it carefully so we register the loopback device after we clear dev_boot_phase. Signed-off-by: Eric W. Biederman <ebiederm@maxwell.aristanetworks.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/loopback.c13
-rw-r--r--include/linux/netdevice.h1
-rw-r--r--net/core/dev.c22
3 files changed, 20 insertions, 16 deletions
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 91d08585a6d8..c4516b580ba5 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -204,17 +204,8 @@ static __net_exit void loopback_net_exit(struct net *net)
204 unregister_netdev(dev); 204 unregister_netdev(dev);
205} 205}
206 206
207static struct pernet_operations __net_initdata loopback_net_ops = { 207/* Registered in net/core/dev.c */
208struct pernet_operations __net_initdata loopback_net_ops = {
208 .init = loopback_net_init, 209 .init = loopback_net_init,
209 .exit = loopback_net_exit, 210 .exit = loopback_net_exit,
210}; 211};
211
212static int __init loopback_init(void)
213{
214 return register_pernet_device(&loopback_net_ops);
215}
216
217/* Loopback is special. It should be initialized before any other network
218 * device and network subsystem.
219 */
220fs_initcall(loopback_init);
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index f1b0dbe58464..12d7f4469dc9 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -1766,6 +1766,7 @@ static inline int skb_bond_should_drop(struct sk_buff *skb)
1766 return 0; 1766 return 0;
1767} 1767}
1768 1768
1769extern struct pernet_operations __net_initdata loopback_net_ops;
1769#endif /* __KERNEL__ */ 1770#endif /* __KERNEL__ */
1770 1771
1771#endif /* _LINUX_DEV_H */ 1772#endif /* _LINUX_DEV_H */
diff --git a/net/core/dev.c b/net/core/dev.c
index 2306d56fbb5e..31568b2068ac 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -4909,9 +4909,6 @@ static int __init net_dev_init(void)
4909 if (register_pernet_subsys(&netdev_net_ops)) 4909 if (register_pernet_subsys(&netdev_net_ops))
4910 goto out; 4910 goto out;
4911 4911
4912 if (register_pernet_device(&default_device_ops))
4913 goto out;
4914
4915 /* 4912 /*
4916 * Initialise the packet receive queues. 4913 * Initialise the packet receive queues.
4917 */ 4914 */
@@ -4928,10 +4925,25 @@ static int __init net_dev_init(void)
4928 queue->backlog.weight = weight_p; 4925 queue->backlog.weight = weight_p;
4929 } 4926 }
4930 4927
4931 netdev_dma_register();
4932
4933 dev_boot_phase = 0; 4928 dev_boot_phase = 0;
4934 4929
4930 /* The loopback device is special if any other network devices
4931 * is present in a network namespace the loopback device must
4932 * be present. Since we now dynamically allocate and free the
4933 * loopback device ensure this invariant is maintained by
4934 * keeping the loopback device as the first device on the
4935 * list of network devices. Ensuring the loopback devices
4936 * is the first device that appears and the last network device
4937 * that disappears.
4938 */
4939 if (register_pernet_device(&loopback_net_ops))
4940 goto out;
4941
4942 if (register_pernet_device(&default_device_ops))
4943 goto out;
4944
4945 netdev_dma_register();
4946
4935 open_softirq(NET_TX_SOFTIRQ, net_tx_action); 4947 open_softirq(NET_TX_SOFTIRQ, net_tx_action);
4936 open_softirq(NET_RX_SOFTIRQ, net_rx_action); 4948 open_softirq(NET_RX_SOFTIRQ, net_rx_action);
4937 4949