aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/notifier.h1
-rw-r--r--net/core/dev.c29
2 files changed, 28 insertions, 2 deletions
diff --git a/include/linux/notifier.h b/include/linux/notifier.h
index 29714b8441b1..b0c3671d463c 100644
--- a/include/linux/notifier.h
+++ b/include/linux/notifier.h
@@ -202,6 +202,7 @@ static inline int notifier_to_errno(int ret)
202#define NETDEV_BONDING_OLDTYPE 0x000E 202#define NETDEV_BONDING_OLDTYPE 0x000E
203#define NETDEV_BONDING_NEWTYPE 0x000F 203#define NETDEV_BONDING_NEWTYPE 0x000F
204#define NETDEV_POST_INIT 0x0010 204#define NETDEV_POST_INIT 0x0010
205#define NETDEV_UNREGISTER_PERNET 0x0011
205 206
206#define SYS_DOWN 0x0001 /* Notify of system down */ 207#define SYS_DOWN 0x0001 /* Notify of system down */
207#define SYS_RESTART SYS_DOWN 208#define SYS_RESTART SYS_DOWN
diff --git a/net/core/dev.c b/net/core/dev.c
index c3e0578d29d1..e25fe5d9343b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -1344,6 +1344,7 @@ rollback:
1344 nb->notifier_call(nb, NETDEV_DOWN, dev); 1344 nb->notifier_call(nb, NETDEV_DOWN, dev);
1345 } 1345 }
1346 nb->notifier_call(nb, NETDEV_UNREGISTER, dev); 1346 nb->notifier_call(nb, NETDEV_UNREGISTER, dev);
1347 nb->notifier_call(nb, NETDEV_UNREGISTER_PERNET, dev);
1347 } 1348 }
1348 } 1349 }
1349 1350
@@ -4721,7 +4722,8 @@ static void net_set_todo(struct net_device *dev)
4721 4722
4722static void rollback_registered_many(struct list_head *head) 4723static void rollback_registered_many(struct list_head *head)
4723{ 4724{
4724 struct net_device *dev; 4725 struct net_device *dev, *aux, *fdev;
4726 LIST_HEAD(pernet_list);
4725 4727
4726 BUG_ON(dev_boot_phase); 4728 BUG_ON(dev_boot_phase);
4727 ASSERT_RTNL(); 4729 ASSERT_RTNL();
@@ -4779,8 +4781,24 @@ static void rollback_registered_many(struct list_head *head)
4779 4781
4780 synchronize_net(); 4782 synchronize_net();
4781 4783
4782 list_for_each_entry(dev, head, unreg_list) 4784 list_for_each_entry_safe(dev, aux, head, unreg_list) {
4785 int new_net = 1;
4786 list_for_each_entry(fdev, &pernet_list, unreg_list) {
4787 if (dev_net(dev) == dev_net(fdev)) {
4788 new_net = 0;
4789 dev_put(dev);
4790 break;
4791 }
4792 }
4793 if (new_net)
4794 list_move(&dev->unreg_list, &pernet_list);
4795 }
4796
4797 list_for_each_entry_safe(dev, aux, &pernet_list, unreg_list) {
4798 call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev);
4799 list_move(&dev->unreg_list, head);
4783 dev_put(dev); 4800 dev_put(dev);
4801 }
4784} 4802}
4785 4803
4786static void rollback_registered(struct net_device *dev) 4804static void rollback_registered(struct net_device *dev)
@@ -5074,6 +5092,8 @@ static void netdev_wait_allrefs(struct net_device *dev)
5074 5092
5075 /* Rebroadcast unregister notification */ 5093 /* Rebroadcast unregister notification */
5076 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 5094 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
5095 /* don't resend NETDEV_UNREGISTER_PERNET, _PERNET users
5096 * should have already handle it the first time */
5077 5097
5078 if (test_bit(__LINK_STATE_LINKWATCH_PENDING, 5098 if (test_bit(__LINK_STATE_LINKWATCH_PENDING,
5079 &dev->state)) { 5099 &dev->state)) {
@@ -5385,6 +5405,10 @@ EXPORT_SYMBOL(unregister_netdevice_queue);
5385 * unregister_netdevice_many - unregister many devices 5405 * unregister_netdevice_many - unregister many devices
5386 * @head: list of devices 5406 * @head: list of devices
5387 * 5407 *
5408 * WARNING: Calling this modifies the given list
5409 * (in rollback_registered_many). It may change the order of the elements
5410 * in the list. However, you can assume it does not add or delete elements
5411 * to/from the list.
5388 */ 5412 */
5389void unregister_netdevice_many(struct list_head *head) 5413void unregister_netdevice_many(struct list_head *head)
5390{ 5414{
@@ -5504,6 +5528,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char
5504 this device. They should clean all the things. 5528 this device. They should clean all the things.
5505 */ 5529 */
5506 call_netdevice_notifiers(NETDEV_UNREGISTER, dev); 5530 call_netdevice_notifiers(NETDEV_UNREGISTER, dev);
5531 call_netdevice_notifiers(NETDEV_UNREGISTER_PERNET, dev);
5507 5532
5508 /* 5533 /*
5509 * Flush the unicast and multicast chains 5534 * Flush the unicast and multicast chains