diff options
author | David S. Miller <davem@davemloft.net> | 2013-10-01 17:06:14 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-10-01 17:06:14 -0400 |
commit | 4fbef95af4e62d4aada6c1728e04d3b1c828abe0 (patch) | |
tree | 19cb25e39583119c98dee7114aada6a3b57d18a9 /net/core/dev.c | |
parent | 5229432f15e6f1b1e34e519e51d07917dee8790e (diff) | |
parent | c31eeaced22ce8bd61268a3c595d542bb38c0a4f (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.c | 49 |
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 */ |
5430 | static LIST_HEAD(net_todo_list); | 5430 | static LIST_HEAD(net_todo_list); |
5431 | static DECLARE_WAIT_QUEUE_HEAD(netdev_unregistering_wq); | ||
5431 | 5432 | ||
5432 | static void net_set_todo(struct net_device *dev) | 5433 | static 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 | ||
5437 | static void rollback_registered_many(struct list_head *head) | 5439 | static 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 | ||
6797 | static 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 | |||
6789 | static void __net_exit default_device_exit_batch(struct list_head *net_list) | 6825 | static 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) |