diff options
| -rw-r--r-- | include/linux/notifier.h | 1 | ||||
| -rw-r--r-- | net/core/dev.c | 29 |
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 | ||
| 4722 | static void rollback_registered_many(struct list_head *head) | 4723 | static 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 | ||
| 4786 | static void rollback_registered(struct net_device *dev) | 4804 | static 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 | */ |
| 5389 | void unregister_netdevice_many(struct list_head *head) | 5413 | void 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 |
