aboutsummaryrefslogtreecommitdiffstats
path: root/net/core/dev.c
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2009-11-29 10:45:58 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-01 19:15:50 -0500
commita5ee155136b4a8f4ab0e4c9c064b661da475e298 (patch)
tree10c113756ff0dcc860735d96ed141701bffa3476 /net/core/dev.c
parent5a5b6f6f62ac684a5856121d8cffd3c3253dc890 (diff)
net: NETDEV_UNREGISTER_PERNET -> NETDEV_UNREGISTER_BATCH
The motivation for an additional notifier in batched netdevice notification (rt_do_flush) only needs to be called once per batch not once per namespace. For further batching improvements I need a guarantee that the netdevices are unregistered in order allowing me to unregister an all of the network devices in a network namespace at the same time with the guarantee that the loopback device is really and truly unregistered last. Additionally it appears that we moved the route cache flush after the final synchronize_net, which seems wrong and there was no explanation. So I have restored the original location of the final synchronize_net. Cc: Octavian Purdila <opurdila@ixiacom.com> Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core/dev.c')
-rw-r--r--net/core/dev.c36
1 files changed, 9 insertions, 27 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 5d131c2f84cc..bb37ee1e0901 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1353,7 +1353,7 @@ rollback:
1353 nb->notifier_call(nb, NETDEV_DOWN, dev); 1353 nb->notifier_call(nb, NETDEV_DOWN, dev);
1354 } 1354 }
1355 nb->notifier_call(nb, NETDEV_UNREGISTER, dev); 1355 nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
1356 nb->notifier_call(nb, NETDEV_UNREGISTER_PERNET, dev); 1356 nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev);
1357 } 1357 }
1358 } 1358 }
1359 1359
@@ -4771,8 +4771,7 @@ static void net_set_todo(struct net_device *dev)
4771 4771
4772static void rollback_registered_many(struct list_head *head) 4772static void rollback_registered_many(struct list_head *head)
4773{ 4773{
4774 struct net_device *dev, *aux, *fdev; 4774 struct net_device *dev;
4775 LIST_HEAD(pernet_list);
4776 4775
4777 BUG_ON(dev_boot_phase); 4776 BUG_ON(dev_boot_phase);
4778 ASSERT_RTNL(); 4777 ASSERT_RTNL();
@@ -4828,26 +4827,14 @@ static void rollback_registered_many(struct list_head *head)
4828 netdev_unregister_kobject(dev); 4827 netdev_unregister_kobject(dev);
4829 } 4828 }
4830 4829
4831 synchronize_net(); 4830 /* Process any work delayed until the end of the batch */
4831 dev = list_entry(head->next, struct net_device, unreg_list);
4832 call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
4832 4833
4833 list_for_each_entry_safe(dev, aux, head, unreg_list) { 4834 synchronize_net();
4834 int new_net = 1;
4835 list_for_each_entry(fdev, &pernet_list, unreg_list) {
4836 if (net_eq(dev_net(dev), dev_net(fdev))) {
4837 new_net = 0;
4838 dev_put(dev);
4839 break;
4840 }
4841 }
4842 if (new_net)
4843 list_move(&dev->unreg_list, &pernet_list);
4844 }
4845 4835
4846 list_for_each_entry_safe(dev, aux, &pernet_list, unreg_list) { 4836 list_for_each_entry(dev, head, unreg_list)
4847 call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev);
4848 list_move(&dev->unreg_list, head);
4849 dev_put(dev); 4837 dev_put(dev);
4850 }
4851} 4838}
4852 4839
4853static void rollback_registered(struct net_device *dev) 4840static void rollback_registered(struct net_device *dev)
@@ -5129,7 +5116,7 @@ static void netdev_wait_allrefs(struct net_device *dev)
5129 5116
5130 /* Rebroadcast unregister notification */ 5117 /* Rebroadcast unregister notification */
5131 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 5118 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
5132 /* don't resend NETDEV_UNREGISTER_PERNET, _PERNET users 5119 /* don't resend NETDEV_UNREGISTER_BATCH, _BATCH users
5133 * should have already handle it the first time */ 5120 * should have already handle it the first time */
5134 5121
5135 if (test_bit(__LINK_STATE_LINKWATCH_PENDING, 5122 if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
@@ -5442,11 +5429,6 @@ EXPORT_SYMBOL(unregister_netdevice_queue);
5442/** 5429/**
5443 * unregister_netdevice_many - unregister many devices 5430 * unregister_netdevice_many - unregister many devices
5444 * @head: list of devices 5431 * @head: list of devices
5445 *
5446 * WARNING: Calling this modifies the given list
5447 * (in rollback_registered_many). It may change the order of the elements
5448 * in the list. However, you can assume it does not add or delete elements
5449 * to/from the list.
5450 */ 5432 */
5451void unregister_netdevice_many(struct list_head *head) 5433void unregister_netdevice_many(struct list_head *head)
5452{ 5434{
@@ -5555,7 +5537,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
5555 this device. They should clean all the things. 5537 this device. They should clean all the things.
5556 */ 5538 */
5557 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 5539 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
5558 call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev); 5540 call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev);
5559 5541
5560 /* 5542 /*
5561 * Flush the unicast and multicast chains 5543 * Flush the unicast and multicast chains