diff options
author | Eric Dumazet <eric.dumazet@gmail.com> | 2009-10-28 01:35:35 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-29 04:13:48 -0400 |
commit | 8c56ba0530af3d5eee6445dce9dc9296f1f74ed5 (patch) | |
tree | b7c82f62e266ba732e0a80f9c22a91d47cddafe3 /net/bridge/br_if.c | |
parent | 59fd5d87a4243a992f3a3e69f3627cf4c509608e (diff) |
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>
Diffstat (limited to 'net/bridge/br_if.c')
-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) | |||
154 | } | 154 | } |
155 | 155 | ||
156 | /* called with RTNL */ | 156 | /* called with RTNL */ |
157 | static void del_br(struct net_bridge *br) | 157 | static void del_br(struct net_bridge *br, struct list_head *head) |
158 | { | 158 | { |
159 | struct net_bridge_port *p, *n; | 159 | struct net_bridge_port *p, *n; |
160 | 160 | ||
@@ -165,7 +165,7 @@ static void del_br(struct net_bridge *br) | |||
165 | del_timer_sync(&br->gc_timer); | 165 | del_timer_sync(&br->gc_timer); |
166 | 166 | ||
167 | br_sysfs_delbr(br->dev); | 167 | br_sysfs_delbr(br->dev); |
168 | unregister_netdevice(br->dev); | 168 | unregister_netdevice_queue(br->dev, head); |
169 | } | 169 | } |
170 | 170 | ||
171 | static struct net_device *new_bridge_dev(struct net *net, const char *name) | 171 | 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) | |||
323 | } | 323 | } |
324 | 324 | ||
325 | else | 325 | else |
326 | del_br(netdev_priv(dev)); | 326 | del_br(netdev_priv(dev), NULL); |
327 | 327 | ||
328 | rtnl_unlock(); | 328 | rtnl_unlock(); |
329 | return ret; | 329 | return ret; |
@@ -462,15 +462,14 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
462 | void br_net_exit(struct net *net) | 462 | void br_net_exit(struct net *net) |
463 | { | 463 | { |
464 | struct net_device *dev; | 464 | struct net_device *dev; |
465 | LIST_HEAD(list); | ||
465 | 466 | ||
466 | rtnl_lock(); | 467 | rtnl_lock(); |
467 | restart: | 468 | for_each_netdev(net, dev) |
468 | for_each_netdev(net, dev) { | 469 | if (dev->priv_flags & IFF_EBRIDGE) |
469 | if (dev->priv_flags & IFF_EBRIDGE) { | 470 | del_br(netdev_priv(dev), &list); |
470 | del_br(netdev_priv(dev)); | 471 | |
471 | goto restart; | 472 | unregister_netdevice_many(&list); |
472 | } | ||
473 | } | ||
474 | rtnl_unlock(); | 473 | rtnl_unlock(); |
475 | 474 | ||
476 | } | 475 | } |