]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
bonding: avoid NETDEV_CHANGEMTU event when unregistering slave
authorWANG Cong <xiyou.wangcong@gmail.com>
Fri, 14 Jul 2017 20:58:52 +0000 (16:58 -0400)
committerKleber Sacilotto de Souza <kleber.souza@canonical.com>
Wed, 9 Aug 2017 14:23:32 +0000 (16:23 +0200)
BugLink: http://bugs.launchpad.net/bugs/1704102
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>
(cherry picked from commit f51048c3e07b68c90b21a77541fc4b208f9244d7)
Signed-off-by: Joseph Salisbury <joseph.salisbury@canonical.com>
Acked-by: Stefan Bader <stefan.bader@canonical.com>
Acked-by: Seth Forshee <seth.forshee@canonical.com>
Signed-off-by: Thadeu Lima de Souza Cascardo <cascardo@canonical.com>
drivers/net/bonding/bond_main.c
include/linux/netdevice.h
net/core/dev.c

index 644d2bf0c4513b4320536e2b07dc3699f368bfbc..335662553f801fac6ef61e190c7c4dd848485379 100644 (file)
@@ -1814,7 +1814,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;
@@ -1958,7 +1958,10 @@ static int __bond_release_one(struct net_device *bond_dev,
                dev_set_mac_address(slave_dev, &addr);
        }
 
-       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;
 
@@ -1970,7 +1973,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.
@@ -1982,7 +1985,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",
@@ -3033,7 +3036,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:
@@ -4234,7 +4237,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);
index bdef8b7d4305f27a5f34509d0f4ef0a865f8e14c..3f653bc53aebb34ca9115ad56705c6368004a0ef 100644 (file)
@@ -3245,6 +3245,7 @@ void __dev_notify_flags(struct net_device *, unsigned int old_flags,
 int dev_change_name(struct net_device *, const char *);
 int dev_set_alias(struct net_device *, const char *, size_t);
 int dev_change_net_namespace(struct net_device *, struct net *, const char *);
+int __dev_set_mtu(struct net_device *, int);
 int dev_set_mtu(struct net_device *, int);
 void dev_set_group(struct net_device *, int);
 int dev_set_mac_address(struct net_device *, struct sockaddr *);
index 54f8c162ded8a32524d4729cbc41be54b0470f50..7c8959936169120b63653d9c6d571dc21a3e5f63 100644 (file)
@@ -6602,7 +6602,7 @@ int dev_change_flags(struct net_device *dev, unsigned int flags)
 }
 EXPORT_SYMBOL(dev_change_flags);
 
-static int __dev_set_mtu(struct net_device *dev, int new_mtu)
+int __dev_set_mtu(struct net_device *dev, int new_mtu)
 {
        const struct net_device_ops *ops = dev->netdev_ops;
 
@@ -6612,6 +6612,7 @@ static int __dev_set_mtu(struct net_device *dev, int new_mtu)
        dev->mtu = new_mtu;
        return 0;
 }
+EXPORT_SYMBOL(__dev_set_mtu);
 
 /**
  *     dev_set_mtu - Change maximum transfer unit