diff options
Diffstat (limited to 'net/bridge/br_if.c')
-rw-r--r-- | net/bridge/br_if.c | 23 |
1 files changed, 16 insertions, 7 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 1bacca4cb67..1d420f64ff2 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -161,9 +161,10 @@ static void del_nbp(struct net_bridge_port *p) | |||
161 | call_rcu(&p->rcu, destroy_nbp_rcu); | 161 | call_rcu(&p->rcu, destroy_nbp_rcu); |
162 | } | 162 | } |
163 | 163 | ||
164 | /* called with RTNL */ | 164 | /* Delete bridge device */ |
165 | static void del_br(struct net_bridge *br, struct list_head *head) | 165 | void br_dev_delete(struct net_device *dev, struct list_head *head) |
166 | { | 166 | { |
167 | struct net_bridge *br = netdev_priv(dev); | ||
167 | struct net_bridge_port *p, *n; | 168 | struct net_bridge_port *p, *n; |
168 | 169 | ||
169 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 170 | list_for_each_entry_safe(p, n, &br->port_list, list) { |
@@ -231,6 +232,7 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
231 | int br_add_bridge(struct net *net, const char *name) | 232 | int br_add_bridge(struct net *net, const char *name) |
232 | { | 233 | { |
233 | struct net_device *dev; | 234 | struct net_device *dev; |
235 | int res; | ||
234 | 236 | ||
235 | dev = alloc_netdev(sizeof(struct net_bridge), name, | 237 | dev = alloc_netdev(sizeof(struct net_bridge), name, |
236 | br_dev_setup); | 238 | br_dev_setup); |
@@ -240,7 +242,10 @@ int br_add_bridge(struct net *net, const char *name) | |||
240 | 242 | ||
241 | dev_net_set(dev, net); | 243 | dev_net_set(dev, net); |
242 | 244 | ||
243 | return register_netdev(dev); | 245 | res = register_netdev(dev); |
246 | if (res) | ||
247 | free_netdev(dev); | ||
248 | return res; | ||
244 | } | 249 | } |
245 | 250 | ||
246 | int br_del_bridge(struct net *net, const char *name) | 251 | int br_del_bridge(struct net *net, const char *name) |
@@ -264,7 +269,7 @@ int br_del_bridge(struct net *net, const char *name) | |||
264 | } | 269 | } |
265 | 270 | ||
266 | else | 271 | else |
267 | del_br(netdev_priv(dev), NULL); | 272 | br_dev_delete(dev, NULL); |
268 | 273 | ||
269 | rtnl_unlock(); | 274 | rtnl_unlock(); |
270 | return ret; | 275 | return ret; |
@@ -388,7 +393,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
388 | br_ifinfo_notify(RTM_NEWLINK, p); | 393 | br_ifinfo_notify(RTM_NEWLINK, p); |
389 | 394 | ||
390 | if (changed_addr) | 395 | if (changed_addr) |
391 | call_netdevice_notifiers(NETDEV_CHANGEADDR, dev); | 396 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); |
392 | 397 | ||
393 | dev_set_mtu(br->dev, br_min_mtu(br)); | 398 | dev_set_mtu(br->dev, br_min_mtu(br)); |
394 | 399 | ||
@@ -417,6 +422,7 @@ put_back: | |||
417 | int br_del_if(struct net_bridge *br, struct net_device *dev) | 422 | int br_del_if(struct net_bridge *br, struct net_device *dev) |
418 | { | 423 | { |
419 | struct net_bridge_port *p; | 424 | struct net_bridge_port *p; |
425 | bool changed_addr; | ||
420 | 426 | ||
421 | p = br_port_get_rtnl(dev); | 427 | p = br_port_get_rtnl(dev); |
422 | if (!p || p->br != br) | 428 | if (!p || p->br != br) |
@@ -425,9 +431,12 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
425 | del_nbp(p); | 431 | del_nbp(p); |
426 | 432 | ||
427 | spin_lock_bh(&br->lock); | 433 | spin_lock_bh(&br->lock); |
428 | br_stp_recalculate_bridge_id(br); | 434 | changed_addr = br_stp_recalculate_bridge_id(br); |
429 | spin_unlock_bh(&br->lock); | 435 | spin_unlock_bh(&br->lock); |
430 | 436 | ||
437 | if (changed_addr) | ||
438 | call_netdevice_notifiers(NETDEV_CHANGEADDR, br->dev); | ||
439 | |||
431 | netdev_update_features(br->dev); | 440 | netdev_update_features(br->dev); |
432 | 441 | ||
433 | return 0; | 442 | return 0; |
@@ -441,7 +450,7 @@ void __net_exit br_net_exit(struct net *net) | |||
441 | rtnl_lock(); | 450 | rtnl_lock(); |
442 | for_each_netdev(net, dev) | 451 | for_each_netdev(net, dev) |
443 | if (dev->priv_flags & IFF_EBRIDGE) | 452 | if (dev->priv_flags & IFF_EBRIDGE) |
444 | del_br(netdev_priv(dev), &list); | 453 | br_dev_delete(dev, &list); |
445 | 454 | ||
446 | unregister_netdevice_many(&list); | 455 | unregister_netdevice_many(&list); |
447 | rtnl_unlock(); | 456 | rtnl_unlock(); |