diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-10-28 08:35:35 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-29 11:13:48 +0300 |
commit | 8c56ba0530af3d5eee6445dce9dc9296f1f74ed5 (patch) | |
tree | b7c82f62e266ba732e0a80f9c22a91d47cddafe3 | |
parent | 59fd5d87a4243a992f3a3e69f3627cf4c509608e (diff) | |
download | linux-8c56ba0530af3d5eee6445dce9dc9296f1f74ed5.tar.xz |
bridge: 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/bridge/br_if.c | 19 |
1 files changed, 9 insertions, 10 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index b1b3b0fbf41c..2117e5ba24c8 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c @@ -154,7 +154,7 @@ static void del_nbp(struct net_bridge_port *p) } /* called with RTNL */ -static void del_br(struct net_bridge *br) +static void del_br(struct net_bridge *br, struct list_head *head) { struct net_bridge_port *p, *n; @@ -165,7 +165,7 @@ static void del_br(struct net_bridge *br) del_timer_sync(&br->gc_timer); br_sysfs_delbr(br->dev); - unregister_netdevice(br->dev); + unregister_netdevice_queue(br->dev, head); } static struct net_device *new_bridge_dev(struct net *net, const char *name) @@ -323,7 +323,7 @@ int br_del_bridge(struct net *net, const char *name) } else - del_br(netdev_priv(dev)); + del_br(netdev_priv(dev), NULL); rtnl_unlock(); return ret; @@ -462,15 +462,14 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) void br_net_exit(struct net *net) { struct net_device *dev; + LIST_HEAD(list); rtnl_lock(); -restart: - for_each_netdev(net, dev) { - if (dev->priv_flags & IFF_EBRIDGE) { - del_br(netdev_priv(dev)); - goto restart; - } - } + for_each_netdev(net, dev) + if (dev->priv_flags & IFF_EBRIDGE) + del_br(netdev_priv(dev), &list); + + unregister_netdevice_many(&list); rtnl_unlock(); } |