aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
authorEric Dumazet <eric.dumazet@gmail.com>2009-10-28 00:48:11 -0400
committerDavid S. Miller <davem@davemloft.net>2009-10-29 04:13:53 -0400
commitc871e664ea39363c2a1011ec2dc4bc172dc396a0 (patch)
tree90a83827b99c690e5380d6f2668d224c5a2bc534 /net/ipv6
parent62808f91237181dbac74c2b5be4fa92adfbbbe40 (diff)
ip6mr: 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/ipv6')
-rw-r--r--net/ipv6/ip6mr.c15
1 files changed, 10 insertions, 5 deletions
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 85849b4f5a36..52e0f74fdfe0 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -477,7 +477,7 @@ failure:
477 * Delete a VIF entry 477 * Delete a VIF entry
478 */ 478 */
479 479
480static int mif6_delete(struct net *net, int vifi) 480static int mif6_delete(struct net *net, int vifi, struct list_head *head)
481{ 481{
482 struct mif_device *v; 482 struct mif_device *v;
483 struct net_device *dev; 483 struct net_device *dev;
@@ -519,7 +519,7 @@ static int mif6_delete(struct net *net, int vifi)
519 in6_dev->cnf.mc_forwarding--; 519 in6_dev->cnf.mc_forwarding--;
520 520
521 if (v->flags & MIFF_REGISTER) 521 if (v->flags & MIFF_REGISTER)
522 unregister_netdevice(dev); 522 unregister_netdevice_queue(dev, head);
523 523
524 dev_put(dev); 524 dev_put(dev);
525 return 0; 525 return 0;
@@ -976,6 +976,7 @@ static int ip6mr_device_event(struct notifier_block *this,
976 struct net *net = dev_net(dev); 976 struct net *net = dev_net(dev);
977 struct mif_device *v; 977 struct mif_device *v;
978 int ct; 978 int ct;
979 LIST_HEAD(list);
979 980
980 if (event != NETDEV_UNREGISTER) 981 if (event != NETDEV_UNREGISTER)
981 return NOTIFY_DONE; 982 return NOTIFY_DONE;
@@ -983,8 +984,10 @@ static int ip6mr_device_event(struct notifier_block *this,
983 v = &net->ipv6.vif6_table[0]; 984 v = &net->ipv6.vif6_table[0];
984 for (ct = 0; ct < net->ipv6.maxvif; ct++, v++) { 985 for (ct = 0; ct < net->ipv6.maxvif; ct++, v++) {
985 if (v->dev == dev) 986 if (v->dev == dev)
986 mif6_delete(net, ct); 987 mif6_delete(net, ct, &list);
987 } 988 }
989 unregister_netdevice_many(&list);
990
988 return NOTIFY_DONE; 991 return NOTIFY_DONE;
989} 992}
990 993
@@ -1188,14 +1191,16 @@ static int ip6mr_mfc_add(struct net *net, struct mf6cctl *mfc, int mrtsock)
1188static void mroute_clean_tables(struct net *net) 1191static void mroute_clean_tables(struct net *net)
1189{ 1192{
1190 int i; 1193 int i;
1194 LIST_HEAD(list);
1191 1195
1192 /* 1196 /*
1193 * Shut down all active vif entries 1197 * Shut down all active vif entries
1194 */ 1198 */
1195 for (i = 0; i < net->ipv6.maxvif; i++) { 1199 for (i = 0; i < net->ipv6.maxvif; i++) {
1196 if (!(net->ipv6.vif6_table[i].flags & VIFF_STATIC)) 1200 if (!(net->ipv6.vif6_table[i].flags & VIFF_STATIC))
1197 mif6_delete(net, i); 1201 mif6_delete(net, i, &list);
1198 } 1202 }
1203 unregister_netdevice_many(&list);
1199 1204
1200 /* 1205 /*
1201 * Wipe the cache 1206 * Wipe the cache
@@ -1325,7 +1330,7 @@ int ip6_mroute_setsockopt(struct sock *sk, int optname, char __user *optval, uns
1325 if (copy_from_user(&mifi, optval, sizeof(mifi_t))) 1330 if (copy_from_user(&mifi, optval, sizeof(mifi_t)))
1326 return -EFAULT; 1331 return -EFAULT;
1327 rtnl_lock(); 1332 rtnl_lock();
1328 ret = mif6_delete(net, mifi); 1333 ret = mif6_delete(net, mifi, NULL);
1329 rtnl_unlock(); 1334 rtnl_unlock();
1330 return ret; 1335 return ret;
1331 1336