bridge: switch br_net_exit to batch mode
authorEric Dumazet <edumazet@google.com>
Fri, 18 Feb 2022 07:01:50 +0000 (23:01 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sat, 19 Feb 2022 16:20:12 +0000 (16:20 +0000)
cleanup_net() is competing with other rtnl users.

Instead of calling br_net_exit() for each netns,
call br_net_exit_batch() once.

This gives cleanup_net() ability to group more devices
and call unregister_netdevice_many() only once for all bridge devices.

Signed-off-by: Eric Dumazet <edumazet@google.com>
Cc: Roopa Prabhu <roopa@nvidia.com>
Cc: Nikolay Aleksandrov <razor@blackwall.org>
Acked-by: Nikolay Aleksandrov <razor@blackwall.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/bridge/br.c

index 1fac72c..b1dea3f 100644 (file)
@@ -342,23 +342,26 @@ void br_opt_toggle(struct net_bridge *br, enum net_bridge_opts opt, bool on)
                clear_bit(opt, &br->options);
 }
 
-static void __net_exit br_net_exit(struct net *net)
+static void __net_exit br_net_exit_batch(struct list_head *net_list)
 {
        struct net_device *dev;
+       struct net *net;
        LIST_HEAD(list);
 
        rtnl_lock();
-       for_each_netdev(net, dev)
-               if (netif_is_bridge_master(dev))
-                       br_dev_delete(dev, &list);
+
+       list_for_each_entry(net, net_list, exit_list)
+               for_each_netdev(net, dev)
+                       if (netif_is_bridge_master(dev))
+                               br_dev_delete(dev, &list);
 
        unregister_netdevice_many(&list);
-       rtnl_unlock();
 
+       rtnl_unlock();
 }
 
 static struct pernet_operations br_net_ops = {
-       .exit   = br_net_exit,
+       .exit_batch     = br_net_exit_batch,
 };
 
 static const struct stp_proto br_stp_proto = {