tcp: batch tcp_net_metrics_exit
authorEric Dumazet <edumazet@google.com>
Tue, 19 Sep 2017 23:27:07 +0000 (16:27 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 19 Sep 2017 23:32:23 +0000 (16:32 -0700)
When dealing with a list of dismantling netns, we can scan
tcp_metrics once, saving cpu cycles.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv4/tcp_metrics.c

index 102b2c90bb807d3a88d31b59324baf72cf901cdf..0ab78abc811bef0388089befed672e3d4ee9d881 100644 (file)
@@ -892,10 +892,14 @@ static void tcp_metrics_flush_all(struct net *net)
 
        for (row = 0; row < max_rows; row++, hb++) {
                struct tcp_metrics_block __rcu **pp;
+               bool match;
+
                spin_lock_bh(&tcp_metrics_lock);
                pp = &hb->chain;
                for (tm = deref_locked(*pp); tm; tm = deref_locked(*pp)) {
-                       if (net_eq(tm_net(tm), net)) {
+                       match = net ? net_eq(tm_net(tm), net) :
+                               !atomic_read(&tm_net(tm)->count);
+                       if (match) {
                                *pp = tm->tcpm_next;
                                kfree_rcu(tm, rcu_head);
                        } else {
@@ -1018,14 +1022,14 @@ static int __net_init tcp_net_metrics_init(struct net *net)
        return 0;
 }
 
-static void __net_exit tcp_net_metrics_exit(struct net *net)
+static void __net_exit tcp_net_metrics_exit_batch(struct list_head *net_exit_list)
 {
-       tcp_metrics_flush_all(net);
+       tcp_metrics_flush_all(NULL);
 }
 
 static __net_initdata struct pernet_operations tcp_net_metrics_ops = {
-       .init   =       tcp_net_metrics_init,
-       .exit   =       tcp_net_metrics_exit,
+       .init           =       tcp_net_metrics_init,
+       .exit_batch     =       tcp_net_metrics_exit_batch,
 };
 
 void __init tcp_metrics_init(void)