aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2013-10-01 17:06:14 -0400
committerDavid S. Miller <davem@davemloft.net>2013-10-01 17:06:14 -0400
commit4fbef95af4e62d4aada6c1728e04d3b1c828abe0 (patch)
tree19cb25e39583119c98dee7114aada6a3b57d18a9 /net/core/dev.c
parent5229432f15e6f1b1e34e519e51d07917dee8790e (diff)
parentc31eeaced22ce8bd61268a3c595d542bb38c0a4f (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
Conflicts: drivers/net/ethernet/emulex/benet/be.h drivers/net/usb/qmi_wwan.c drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h include/net/netfilter/nf_conntrack_synproxy.h include/net/secure_seq.h The conflicts are of two varieties: 1) Conflicts with Joe Perches's 'extern' removal from header file function declarations. Usually it's an argument signature change or a function being added/removed. The resolutions are trivial. 2) Some overlapping changes in qmi_wwan.c and be.h, one commit adds a new value, another changes an existing value. That sort of thing. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c49
1 files changed, 48 insertions, 1 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 81340ed7f0f4..c25db20a4246 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -5428,10 +5428,12 @@ static int dev_new_index(struct net *net)
5428 5428
5429/* Delayed registration/unregisteration */ 5429/* Delayed registration/unregisteration */
5430static LIST_HEAD(net_todo_list); 5430static LIST_HEAD(net_todo_list);
5431static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq);
5431 5432
5432static void net_set_todo(struct net_device *dev) 5433static void net_set_todo(struct net_device *dev)
5433{ 5434{
5434 list_add_tail(&dev->todo_list, &net_todo_list); 5435 list_add_tail(&dev->todo_list, &net_todo_list);
5436 dev_net(dev)->dev_unreg_count++;
5435} 5437}
5436 5438
5437static void rollback_registered_many(struct list_head *head) 5439static void rollback_registered_many(struct list_head *head)
@@ -6099,6 +6101,12 @@ void netdev_run_todo(void)
6099 if (dev->destructor) 6101 if (dev->destructor)
6100 dev->destructor(dev); 6102 dev->destructor(dev);
6101 6103
6104 /* Report a network device has been unregistered */
6105 rtnl_lock();
6106 dev_net(dev)->dev_unreg_count--;
6107 __rtnl_unlock();
6108 wake_up(&netdev_unregistering_wq);
6109
6102 /* Free network device */ 6110 /* Free network device */
6103 kobject_put(&dev->dev.kobj); 6111 kobject_put(&dev->dev.kobj);
6104 } 6112 }
@@ -6786,6 +6794,34 @@ static void __net_exit default_device_exit(struct net *net)
6786 rtnl_unlock(); 6794 rtnl_unlock();
6787} 6795}
6788 6796
6797static void __net_exit rtnl_lock_unregistering(struct list_head *net_list)
6798{
6799 /* Return with the rtnl_lock held when there are no network
6800 * devices unregistering in any network namespace in net_list.
6801 */
6802 struct net *net;
6803 bool unregistering;
6804 DEFINE_WAIT(wait);
6805
6806 for (;;) {
6807 prepare_to_wait(&netdev_unregistering_wq, &wait,
6808 TASK_UNINTERRUPTIBLE);
6809 unregistering = false;
6810 rtnl_lock();
6811 list_for_each_entry(net, net_list, exit_list) {
6812 if (net->dev_unreg_count > 0) {
6813 unregistering = true;
6814 break;
6815 }
6816 }
6817 if (!unregistering)
6818 break;
6819 __rtnl_unlock();
6820 schedule();
6821 }
6822 finish_wait(&netdev_unregistering_wq, &wait);
6823}
6824
6789static void __net_exit default_device_exit_batch(struct list_head *net_list) 6825static void __net_exit default_device_exit_batch(struct list_head *net_list)
6790{ 6826{
6791 /* At exit all network devices most be removed from a network 6827 /* At exit all network devices most be removed from a network
@@ -6797,7 +6833,18 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list)
6797 struct net *net; 6833 struct net *net;
6798 LIST_HEAD(dev_kill_list); 6834 LIST_HEAD(dev_kill_list);
6799 6835
6800 rtnl_lock(); 6836 /* To prevent network device cleanup code from dereferencing
6837 * loopback devices or network devices that have been freed
6838 * wait here for all pending unregistrations to complete,
6839 * before unregistring the loopback device and allowing the
6840 * network namespace be freed.
6841 *
6842 * The netdev todo list containing all network devices
6843 * unregistrations that happen in default_device_exit_batch
6844 * will run in the rtnl_unlock() at the end of
6845 * default_device_exit_batch.
6846 */
6847 rtnl_lock_unregistering(net_list);
6801 list_for_each_entry(net, net_list, exit_list) { 6848 list_for_each_entry(net, net_list, exit_list) {
6802 for_each_netdev_reverse(net, dev) { 6849 for_each_netdev_reverse(net, dev) {
6803 if (dev->rtnl_link_ops) 6850 if (dev->rtnl_link_ops)