diff options
-rw-r--r-- | include/linux/notifier.h | 2 | ||||
-rw-r--r-- | include/net/route.h | 1 | ||||
-rw-r--r-- | net/core/dev.c | 36 | ||||
-rw-r--r-- | net/ipv4/fib_frontend.c | 4 | ||||
-rw-r--r-- | net/ipv4/route.c | 6 |
5 files changed, 20 insertions, 29 deletions
diff --git a/include/linux/notifier.h b/include/linux/notifier.h index b0c3671d463c..fee6c2f68075 100644 --- a/include/linux/notifier.h +++ b/include/linux/notifier.h | |||
@@ -202,7 +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 | #define NETDEV_UNREGISTER_BATCH 0x0011 |
206 | 206 | ||
207 | #define SYS_DOWN 0x0001 /* Notify of system down */ | 207 | #define SYS_DOWN 0x0001 /* Notify of system down */ |
208 | #define SYS_RESTART SYS_DOWN | 208 | #define SYS_RESTART SYS_DOWN |
diff --git a/include/net/route.h b/include/net/route.h index cfb4c071a136..bce6dd68d27b 100644 --- a/include/net/route.h +++ b/include/net/route.h | |||
@@ -108,6 +108,7 @@ extern int ip_rt_init(void); | |||
108 | extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, | 108 | extern void ip_rt_redirect(__be32 old_gw, __be32 dst, __be32 new_gw, |
109 | __be32 src, struct net_device *dev); | 109 | __be32 src, struct net_device *dev); |
110 | extern void rt_cache_flush(struct net *net, int how); | 110 | extern void rt_cache_flush(struct net *net, int how); |
111 | extern void rt_cache_flush_batch(void); | ||
111 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); | 112 | extern int __ip_route_output_key(struct net *, struct rtable **, const struct flowi *flp); |
112 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); | 113 | extern int ip_route_output_key(struct net *, struct rtable **, struct flowi *flp); |
113 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); | 114 | extern int ip_route_output_flow(struct net *, struct rtable **rp, struct flowi *flp, struct sock *sk, int flags); |
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 | ||
4772 | static void rollback_registered_many(struct list_head *head) | 4772 | static 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 | ||
4853 | static void rollback_registered(struct net_device *dev) | 4840 | static 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 | */ |
5451 | void unregister_netdevice_many(struct list_head *head) | 5433 | void 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 |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 6c1e56aef1f4..3b373a8b0473 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -959,9 +959,11 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
959 | break; | 959 | break; |
960 | case NETDEV_CHANGEMTU: | 960 | case NETDEV_CHANGEMTU: |
961 | case NETDEV_CHANGE: | 961 | case NETDEV_CHANGE: |
962 | case NETDEV_UNREGISTER_PERNET: | ||
963 | rt_cache_flush(dev_net(dev), 0); | 962 | rt_cache_flush(dev_net(dev), 0); |
964 | break; | 963 | break; |
964 | case NETDEV_UNREGISTER_BATCH: | ||
965 | rt_cache_flush_batch(); | ||
966 | break; | ||
965 | } | 967 | } |
966 | return NOTIFY_DONE; | 968 | return NOTIFY_DONE; |
967 | } | 969 | } |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 9889fbd96487..90cdcfc32937 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -900,6 +900,12 @@ void rt_cache_flush(struct net *net, int delay) | |||
900 | rt_do_flush(!in_softirq()); | 900 | rt_do_flush(!in_softirq()); |
901 | } | 901 | } |
902 | 902 | ||
903 | /* Flush previous cache invalidated entries from the cache */ | ||
904 | void rt_cache_flush_batch(void) | ||
905 | { | ||
906 | rt_do_flush(!in_softirq()); | ||
907 | } | ||
908 | |||
903 | /* | 909 | /* |
904 | * We change rt_genid and let gc do the cleanup | 910 | * We change rt_genid and let gc do the cleanup |
905 | */ | 911 | */ |