diff options
author | Jiri Pirko <jiri@resnulli.us> | 2014-09-05 09:51:28 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-09-09 14:29:54 -0400 |
commit | 0f49579a39533bf839b2af807b094fc652f9e49b (patch) | |
tree | 2f3e7d978d92767ec7f3894f52f714ce7f8ab92f /net/bridge | |
parent | 49a601589caaf0e93194c0cc9b4ecddbe75dd2d5 (diff) |
bridge: switch order of rx_handler reg and upper dev link
The thing is that netdev_master_upper_dev_link calls
call_netdevice_notifiers(NETDEV_CHANGEUPPER, dev). That generates rtnl
link message and during that, rtnl_link_ops->fill_slave_info is called.
But with current ordering, rx_handler and IFF_BRIDGE_PORT are not set
yet so there would have to be check for that in fill_slave_info callback.
Resolve this by reordering to similar what bonding and team does to
avoid the check.
Also add removal of IFF_BRIDGE_PORT flag into error path.
Signed-off-by: Jiri Pirko <jiri@resnulli.us>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/bridge')
-rw-r--r-- | net/bridge/br_if.c | 15 |
1 files changed, 8 insertions, 7 deletions
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 078d336a1f37..a9f54a9b6690 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -252,12 +252,12 @@ static void del_nbp(struct net_bridge_port *p) | |||
252 | br_fdb_delete_by_port(br, p, 1); | 252 | br_fdb_delete_by_port(br, p, 1); |
253 | nbp_update_port_count(br); | 253 | nbp_update_port_count(br); |
254 | 254 | ||
255 | netdev_upper_dev_unlink(dev, br->dev); | ||
256 | |||
255 | dev->priv_flags &= ~IFF_BRIDGE_PORT; | 257 | dev->priv_flags &= ~IFF_BRIDGE_PORT; |
256 | 258 | ||
257 | netdev_rx_handler_unregister(dev); | 259 | netdev_rx_handler_unregister(dev); |
258 | 260 | ||
259 | netdev_upper_dev_unlink(dev, br->dev); | ||
260 | |||
261 | br_multicast_del_port(p); | 261 | br_multicast_del_port(p); |
262 | 262 | ||
263 | kobject_uevent(&p->kobj, KOBJ_REMOVE); | 263 | kobject_uevent(&p->kobj, KOBJ_REMOVE); |
@@ -476,16 +476,16 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
476 | if (err) | 476 | if (err) |
477 | goto err3; | 477 | goto err3; |
478 | 478 | ||
479 | err = netdev_master_upper_dev_link(dev, br->dev); | 479 | err = netdev_rx_handler_register(dev, br_handle_frame, p); |
480 | if (err) | 480 | if (err) |
481 | goto err4; | 481 | goto err4; |
482 | 482 | ||
483 | err = netdev_rx_handler_register(dev, br_handle_frame, p); | 483 | dev->priv_flags |= IFF_BRIDGE_PORT; |
484 | |||
485 | err = netdev_master_upper_dev_link(dev, br->dev); | ||
484 | if (err) | 486 | if (err) |
485 | goto err5; | 487 | goto err5; |
486 | 488 | ||
487 | dev->priv_flags |= IFF_BRIDGE_PORT; | ||
488 | |||
489 | dev_disable_lro(dev); | 489 | dev_disable_lro(dev); |
490 | 490 | ||
491 | list_add_rcu(&p->list, &br->port_list); | 491 | list_add_rcu(&p->list, &br->port_list); |
@@ -520,7 +520,8 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
520 | return 0; | 520 | return 0; |
521 | 521 | ||
522 | err5: | 522 | err5: |
523 | netdev_upper_dev_unlink(dev, br->dev); | 523 | dev->priv_flags &= ~IFF_BRIDGE_PORT; |
524 | netdev_rx_handler_unregister(dev); | ||
524 | err4: | 525 | err4: |
525 | br_netpoll_disable(p); | 526 | br_netpoll_disable(p); |
526 | err3: | 527 | err3: |