diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-10-28 01:21:38 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-29 04:13:49 -0400 |
commit | d17fa6fa81d9be6d2dc69aedfabecf904210cbf4 (patch) | |
tree | 36513dfe8637c6ef87d2837948c7f64ad2b96d8f /net/ipv4/ipmr.c | |
parent | cf4432f550a0fe4e08e7cd522568cfbae754582c (diff) |
ipmr: Optimize multiple unregistration
Speedup module unloading by factorizing synchronize_rcu() calls
Signed-off-by: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/ipmr.c')
-rw-r--r-- | net/ipv4/ipmr.c | 15 |
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 694974502ea6..ef4ee45b928f 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -275,7 +275,8 @@ failure: | |||
275 | * @notify: Set to 1, if the caller is a notifier_call | 275 | * @notify: Set to 1, if the caller is a notifier_call |
276 | */ | 276 | */ |
277 | 277 | ||
278 | static int vif_delete(struct net *net, int vifi, int notify) | 278 | static int vif_delete(struct net *net, int vifi, int notify, |
279 | struct list_head *head) | ||
279 | { | 280 | { |
280 | struct vif_device *v; | 281 | struct vif_device *v; |
281 | struct net_device *dev; | 282 | struct net_device *dev; |
@@ -319,7 +320,7 @@ static int vif_delete(struct net *net, int vifi, int notify) | |||
319 | } | 320 | } |
320 | 321 | ||
321 | if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify) | 322 | if (v->flags&(VIFF_TUNNEL|VIFF_REGISTER) && !notify) |
322 | unregister_netdevice(dev); | 323 | unregister_netdevice_queue(dev, head); |
323 | 324 | ||
324 | dev_put(dev); | 325 | dev_put(dev); |
325 | return 0; | 326 | return 0; |
@@ -870,14 +871,16 @@ static int ipmr_mfc_add(struct net *net, struct mfcctl *mfc, int mrtsock) | |||
870 | static void mroute_clean_tables(struct net *net) | 871 | static void mroute_clean_tables(struct net *net) |
871 | { | 872 | { |
872 | int i; | 873 | int i; |
874 | LIST_HEAD(list); | ||
873 | 875 | ||
874 | /* | 876 | /* |
875 | * Shut down all active vif entries | 877 | * Shut down all active vif entries |
876 | */ | 878 | */ |
877 | for (i = 0; i < net->ipv4.maxvif; i++) { | 879 | for (i = 0; i < net->ipv4.maxvif; i++) { |
878 | if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) | 880 | if (!(net->ipv4.vif_table[i].flags&VIFF_STATIC)) |
879 | vif_delete(net, i, 0); | 881 | vif_delete(net, i, 0, &list); |
880 | } | 882 | } |
883 | unregister_netdevice_many(&list); | ||
881 | 884 | ||
882 | /* | 885 | /* |
883 | * Wipe the cache | 886 | * Wipe the cache |
@@ -993,7 +996,7 @@ int ip_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, unsi | |||
993 | if (optname == MRT_ADD_VIF) { | 996 | if (optname == MRT_ADD_VIF) { |
994 | ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); | 997 | ret = vif_add(net, &vif, sk == net->ipv4.mroute_sk); |
995 | } else { | 998 | } else { |
996 | ret = vif_delete(net, vif.vifc_vifi, 0); | 999 | ret = vif_delete(net, vif.vifc_vifi, 0, NULL); |
997 | } | 1000 | } |
998 | rtnl_unlock(); | 1001 | rtnl_unlock(); |
999 | return ret; | 1002 | return ret; |
@@ -1156,6 +1159,7 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1156 | struct net *net = dev_net(dev); | 1159 | struct net *net = dev_net(dev); |
1157 | struct vif_device *v; | 1160 | struct vif_device *v; |
1158 | int ct; | 1161 | int ct; |
1162 | LIST_HEAD(list); | ||
1159 | 1163 | ||
1160 | if (!net_eq(dev_net(dev), net)) | 1164 | if (!net_eq(dev_net(dev), net)) |
1161 | return NOTIFY_DONE; | 1165 | return NOTIFY_DONE; |
@@ -1165,8 +1169,9 @@ static int ipmr_device_event(struct notifier_block *this, unsigned long event, v | |||
1165 | v = &net->ipv4.vif_table[0]; | 1169 | v = &net->ipv4.vif_table[0]; |
1166 | for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { | 1170 | for (ct = 0; ct < net->ipv4.maxvif; ct++, v++) { |
1167 | if (v->dev == dev) | 1171 | if (v->dev == dev) |
1168 | vif_delete(net, ct, 1); | 1172 | vif_delete(net, ct, 1, &list); |
1169 | } | 1173 | } |
1174 | unregister_netdevice_many(&list); | ||
1170 | return NOTIFY_DONE; | 1175 | return NOTIFY_DONE; |
1171 | } | 1176 | } |
1172 | 1177 | ||