diff options
author | WANG Cong <xiyou.wangcong@gmail.com> | 2017-07-07 01:01:57 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-07-08 13:23:29 +0300 |
commit | f51048c3e07b68c90b21a77541fc4b208f9244d7 (patch) | |
tree | c8f485825b7b9ac43cdde73c4d174474b1498794 /drivers/net | |
parent | 5dc314f8ded18e2b0ffce55a5f253c8aa759d51a (diff) | |
download | linux-f51048c3e07b68c90b21a77541fc4b208f9244d7.tar.xz |
bonding: avoid NETDEV_CHANGEMTU event when unregistering slave
As Hongjun/Nicolas summarized in their original patch:
"
When a device changes from one netns to another, it's first unregistered,
then the netns reference is updated and the dev is registered in the new
netns. Thus, when a slave moves to another netns, it is first
unregistered. This triggers a NETDEV_UNREGISTER event which is caught by
the bonding driver. The driver calls bond_release(), which calls
dev_set_mtu() and thus triggers NETDEV_CHANGEMTU (the device is still in
the old netns).
"
This is a very special case, because the device is being unregistered
no one should still care about the NETDEV_CHANGEMTU event triggered
at this point, we can avoid broadcasting this event on this path,
and avoid touching inetdev_event()/addrconf_notify() path.
It requires to export __dev_set_mtu() to bonding driver.
Reported-by: Hongjun Li <hongjun.li@6wind.com>
Reported-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Jay Vosburgh <j.vosburgh@gmail.com>
Cc: Veaceslav Falico <vfalico@gmail.com>
Cc: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2865f31c6076..14ff622190a5 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -1820,7 +1820,7 @@ err_undo_flags: */ static int __bond_release_one(struct net_device *bond_dev, struct net_device *slave_dev, - bool all) + bool all, bool unregister) { struct bonding *bond = netdev_priv(bond_dev); struct slave *slave, *oldcurrent; @@ -1965,7 +1965,10 @@ static int __bond_release_one(struct net_device *bond_dev, dev_set_mac_address(slave_dev, (struct sockaddr *)&ss); } - dev_set_mtu(slave_dev, slave->original_mtu); + if (unregister) + __dev_set_mtu(slave_dev, slave->original_mtu); + else + dev_set_mtu(slave_dev, slave->original_mtu); slave_dev->priv_flags &= ~IFF_BONDING; @@ -1977,7 +1980,7 @@ static int __bond_release_one(struct net_device *bond_dev, /* A wrapper used because of ndo_del_link */ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) { - return __bond_release_one(bond_dev, slave_dev, false); + return __bond_release_one(bond_dev, slave_dev, false, false); } /* First release a slave and then destroy the bond if no more slaves are left. @@ -1989,7 +1992,7 @@ static int bond_release_and_destroy(struct net_device *bond_dev, struct bonding *bond = netdev_priv(bond_dev); int ret; - ret = bond_release(bond_dev, slave_dev); + ret = __bond_release_one(bond_dev, slave_dev, false, true); if (ret == 0 && !bond_has_slaves(bond)) { bond_dev->priv_flags |= IFF_DISABLE_NETPOLL; netdev_info(bond_dev, "Destroying bond %s\n", @@ -3060,7 +3063,7 @@ static int bond_slave_netdev_event(unsigned long event, if (bond_dev->type != ARPHRD_ETHER) bond_release_and_destroy(bond_dev, slave_dev); else - bond_release(bond_dev, slave_dev); + __bond_release_one(bond_dev, slave_dev, false, true); break; case NETDEV_UP: case NETDEV_CHANGE: @@ -4252,7 +4255,7 @@ static void bond_uninit(struct net_device *bond_dev) /* Release the bonded slaves */ bond_for_each_slave(bond, slave, iter) - __bond_release_one(bond_dev, slave->dev, true); + __bond_release_one(bond_dev, slave->dev, true, true); netdev_info(bond_dev, "Released all slaves\n"); arr = rtnl_dereference(bond->slave_arr); |