gre: Optimize multiple unregistration
authorEric Dumazet <eric.dumazet@gmail.com>
Tue, 27 Oct 2009 07:07:16 +0000 (07:07 +0000)
committerDavid S. Miller <davem@davemloft.net>
Wed, 28 Oct 2009 09:22:09 +0000 (02:22 -0700)
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>
net/ipv4/ip_gre.c

index 40f0439..a77807d 100644 (file)
@@ -1290,16 +1290,19 @@ static const struct net_protocol ipgre_protocol = {
        .netns_ok       =       1,
 };
 
-static void ipgre_destroy_tunnels(struct ipgre_net *ign)
+static void ipgre_destroy_tunnels(struct ipgre_net *ign, struct list_head *head)
 {
        int prio;
 
        for (prio = 0; prio < 4; prio++) {
                int h;
                for (h = 0; h < HASH_SIZE; h++) {
-                       struct ip_tunnel *t;
-                       while ((t = ign->tunnels[prio][h]) != NULL)
-                               unregister_netdevice(t->dev);
+                       struct ip_tunnel *t = ign->tunnels[prio][h];
+
+                       while (t != NULL) {
+                               unregister_netdevice_queue(t->dev, head);
+                               t = t->next;
+                       }
                }
        }
 }
@@ -1347,10 +1350,12 @@ err_alloc:
 static void ipgre_exit_net(struct net *net)
 {
        struct ipgre_net *ign;
+       LIST_HEAD(list);
 
        ign = net_generic(net, ipgre_net_id);
        rtnl_lock();
-       ipgre_destroy_tunnels(ign);
+       ipgre_destroy_tunnels(ign, &list);
+       unregister_netdevice_many(&list);
        rtnl_unlock();
        kfree(ign);
 }