aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authornikolay@redhat.com <nikolay@redhat.com>2013-02-18 09:09:42 -0500
committerDavid S. Miller <davem@davemloft.net>2013-02-19 00:51:09 -0500
commit0896341a44bf04bf6149d9307fe4686006f3eee1 (patch)
treeea26f8337c05dadb0b93107a440ad4e95257a178 /drivers/net/bonding
parent7341a73c12b6133aaf3dade95942041043b11ba3 (diff)
bonding: fix bond_release_all inconsistencies
This patch fixes the following inconsistencies in bond_release_all: - IFF_BONDING flag is not stripped from slaves - MTU is not restored - no netdev notifiers are sent Instead of trying to keep bond_release and bond_release_all in sync I think we can re-use bond_release as the environment for calling it is correct (RTNL is held). I have been running tests for the past week and they came out successful. The only way for bond_release to fail is for the slave to be attached in a different bond or to not be a slave but that cannot happen as RTNL is held and no slave manipulations can be achieved. V2: As suggested bond_release is renamed to __bond_release_one with a new parameter "all" introduced so to avoid calling unnecessary code while destroying a bond, and a wrapper for it called bond_release is created because of ndo_del_link. bond_release_all() is removed. Signed-off-by: Nikolay Aleksandrov <nikolay@redhat.com> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c135
1 files changed, 18 insertions, 117 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 94c1534dd578..e242dd12e5a3 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1937,7 +1937,8 @@ err_undo_flags:
1937/* 1937/*
1938 * Try to release the slave device <slave> from the bond device <master> 1938 * Try to release the slave device <slave> from the bond device <master>
1939 * It is legal to access curr_active_slave without a lock because all the function 1939 * It is legal to access curr_active_slave without a lock because all the function
1940 * is write-locked. 1940 * is write-locked. If "all" is true it means that the function is being called
1941 * while destroying a bond interface and all slaves are being released.
1941 * 1942 *
1942 * The rules for slave state should be: 1943 * The rules for slave state should be:
1943 * for Active/Backup: 1944 * for Active/Backup:
@@ -1945,7 +1946,9 @@ err_undo_flags:
1945 * for Bonded connections: 1946 * for Bonded connections:
1946 * The first up interface should be left on and all others downed. 1947 * The first up interface should be left on and all others downed.
1947 */ 1948 */
1948int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) 1949static int __bond_release_one(struct net_device *bond_dev,
1950 struct net_device *slave_dev,
1951 bool all)
1949{ 1952{
1950 struct bonding *bond = netdev_priv(bond_dev); 1953 struct bonding *bond = netdev_priv(bond_dev);
1951 struct slave *slave, *oldcurrent; 1954 struct slave *slave, *oldcurrent;
@@ -1982,7 +1985,7 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
1982 synchronize_net(); 1985 synchronize_net();
1983 write_lock_bh(&bond->lock); 1986 write_lock_bh(&bond->lock);
1984 1987
1985 if (!bond->params.fail_over_mac) { 1988 if (!all && !bond->params.fail_over_mac) {
1986 if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) && 1989 if (ether_addr_equal(bond_dev->dev_addr, slave->perm_hwaddr) &&
1987 bond->slave_cnt > 1) 1990 bond->slave_cnt > 1)
1988 pr_warning("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n", 1991 pr_warning("%s: Warning: the permanent HWaddr of %s - %pM - is still in use by %s. Set the HWaddr of %s to a different address to avoid conflicts.\n",
@@ -2028,7 +2031,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
2028 write_lock_bh(&bond->lock); 2031 write_lock_bh(&bond->lock);
2029 } 2032 }
2030 2033
2031 if (oldcurrent == slave) { 2034 if (all) {
2035 bond->curr_active_slave = NULL;
2036 } else if (oldcurrent == slave) {
2032 /* 2037 /*
2033 * Note that we hold RTNL over this sequence, so there 2038 * Note that we hold RTNL over this sequence, so there
2034 * is no concern that another slave add/remove event 2039 * is no concern that another slave add/remove event
@@ -2117,6 +2122,12 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
2117 return 0; /* deletion OK */ 2122 return 0; /* deletion OK */
2118} 2123}
2119 2124
2125/* A wrapper used because of ndo_del_link */
2126int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
2127{
2128 return __bond_release_one(bond_dev, slave_dev, false);
2129}
2130
2120/* 2131/*
2121* First release a slave and then destroy the bond if no more slaves are left. 2132* First release a slave and then destroy the bond if no more slaves are left.
2122* Must be under rtnl_lock when this function is called. 2133* Must be under rtnl_lock when this function is called.
@@ -2138,118 +2149,6 @@ static int bond_release_and_destroy(struct net_device *bond_dev,
2138} 2149}
2139 2150
2140/* 2151/*
2141 * This function releases all slaves.
2142 */
2143static int bond_release_all(struct net_device *bond_dev)
2144{
2145 struct bonding *bond = netdev_priv(bond_dev);
2146 struct slave *slave;
2147 struct net_device *slave_dev;
2148 struct sockaddr addr;
2149
2150 write_lock_bh(&bond->lock);
2151
2152 netif_carrier_off(bond_dev);
2153
2154 if (bond->slave_cnt == 0)
2155 goto out;
2156
2157 bond->current_arp_slave = NULL;
2158 bond->primary_slave = NULL;
2159 bond_change_active_slave(bond, NULL);
2160
2161 while ((slave = bond->first_slave) != NULL) {
2162 /* Inform AD package of unbinding of slave
2163 * before slave is detached from the list.
2164 */
2165 if (bond->params.mode == BOND_MODE_8023AD)
2166 bond_3ad_unbind_slave(slave);
2167
2168 slave_dev = slave->dev;
2169 bond_detach_slave(bond, slave);
2170
2171 /* now that the slave is detached, unlock and perform
2172 * all the undo steps that should not be called from
2173 * within a lock.
2174 */
2175 write_unlock_bh(&bond->lock);
2176
2177 /* unregister rx_handler early so bond_handle_frame wouldn't
2178 * be called for this slave anymore.
2179 */
2180 netdev_rx_handler_unregister(slave_dev);
2181 synchronize_net();
2182
2183 if (bond_is_lb(bond)) {
2184 /* must be called only after the slave
2185 * has been detached from the list
2186 */
2187 bond_alb_deinit_slave(bond, slave);
2188 }
2189
2190 bond_destroy_slave_symlinks(bond_dev, slave_dev);
2191 bond_del_vlans_from_slave(bond, slave_dev);
2192
2193 /* If the mode USES_PRIMARY, then we should only remove its
2194 * promisc and mc settings if it was the curr_active_slave, but that was
2195 * already taken care of above when we detached the slave
2196 */
2197 if (!USES_PRIMARY(bond->params.mode)) {
2198 /* unset promiscuity level from slave */
2199 if (bond_dev->flags & IFF_PROMISC)
2200 dev_set_promiscuity(slave_dev, -1);
2201
2202 /* unset allmulti level from slave */
2203 if (bond_dev->flags & IFF_ALLMULTI)
2204 dev_set_allmulti(slave_dev, -1);
2205
2206 /* flush master's mc_list from slave */
2207 netif_addr_lock_bh(bond_dev);
2208 bond_mc_list_flush(bond_dev, slave_dev);
2209 netif_addr_unlock_bh(bond_dev);
2210 }
2211
2212 bond_upper_dev_unlink(bond_dev, slave_dev);
2213
2214 slave_disable_netpoll(slave);
2215
2216 /* close slave before restoring its mac address */
2217 dev_close(slave_dev);
2218
2219 if (!bond->params.fail_over_mac) {
2220 /* restore original ("permanent") mac address*/
2221 memcpy(addr.sa_data, slave->perm_hwaddr, ETH_ALEN);
2222 addr.sa_family = slave_dev->type;
2223 dev_set_mac_address(slave_dev, &addr);
2224 }
2225
2226 kfree(slave);
2227
2228 /* re-acquire the lock before getting the next slave */
2229 write_lock_bh(&bond->lock);
2230 }
2231
2232 eth_hw_addr_random(bond_dev);
2233 bond->dev_addr_from_first = true;
2234
2235 if (bond_vlan_used(bond)) {
2236 pr_warning("%s: Warning: clearing HW address of %s while it still has VLANs.\n",
2237 bond_dev->name, bond_dev->name);
2238 pr_warning("%s: When re-adding slaves, make sure the bond's HW address matches its VLANs'.\n",
2239 bond_dev->name);
2240 }
2241
2242 pr_info("%s: released all slaves\n", bond_dev->name);
2243
2244out:
2245 write_unlock_bh(&bond->lock);
2246
2247 bond_compute_features(bond);
2248
2249 return 0;
2250}
2251
2252/*
2253 * This function changes the active slave to slave <slave_dev>. 2152 * This function changes the active slave to slave <slave_dev>.
2254 * It returns -EINVAL in the following cases. 2153 * It returns -EINVAL in the following cases.
2255 * - <slave_dev> is not found in the list. 2154 * - <slave_dev> is not found in the list.
@@ -4440,7 +4339,9 @@ static void bond_uninit(struct net_device *bond_dev)
4440 bond_netpoll_cleanup(bond_dev); 4339 bond_netpoll_cleanup(bond_dev);
4441 4340
4442 /* Release the bonded slaves */ 4341 /* Release the bonded slaves */
4443 bond_release_all(bond_dev); 4342 while (bond->first_slave != NULL)
4343 __bond_release_one(bond_dev, bond->first_slave->dev, true);
4344 pr_info("%s: released all slaves\n", bond_dev->name);
4444 4345
4445 list_del(&bond->bond_list); 4346 list_del(&bond->bond_list);
4446 4347