aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-10-28 01:21:38 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-29 04:13:49 -0400
commitd17fa6fa81d9be6d2dc69aedfabecf904210cbf4 (patch)
tree36513dfe8637c6ef87d2837948c7f64ad2b96d8f
parentcf4432f550a0fe4e08e7cd522568cfbae754582c (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>
-rw-r--r--net/ipv4/ipmr.c15
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
278static int vif_delete(struct net *net, int vifi, int notify) 278static 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)
870static void mroute_clean_tables(struct net *net) 871static 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