Skip to content

Commit

Permalink
bonding: fix set_multicast_list locking
Browse files Browse the repository at this point in the history
	This patch eliminates a problem (reported by lockdep) in the
bond_set_multicast_list function.  It first reduces the locking on
bond->lock to a simple read_lock, and second, adds netif_tx locking
around the bonding mc_list manipulations that occur outside of the
set_multicast_list function.

	The original problem was related to IPv6 addrconf activity.

Signed-off-by: Jay Vosburgh <fubar@us.ibm.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Jay Vosburgh authored and David S. Miller committed Feb 3, 2008
1 parent a42e534 commit 80ee5ad
Showing 1 changed file with 11 additions and 3 deletions.
14 changes: 11 additions & 3 deletions drivers/net/bonding/bond_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1464,10 +1464,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
dev_set_allmulti(slave_dev, 1);
}

netif_tx_lock_bh(bond_dev);
/* upload master's mc_list to new slave */
for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) {
dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0);
}
netif_tx_unlock_bh(bond_dev);
}

if (bond->params.mode == BOND_MODE_8023AD) {
Expand Down Expand Up @@ -1821,7 +1823,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev)
}

/* flush master's mc_list from slave */
netif_tx_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
netif_tx_unlock_bh(bond_dev);
}

netdev_set_master(slave_dev, NULL);
Expand Down Expand Up @@ -1942,7 +1946,9 @@ static int bond_release_all(struct net_device *bond_dev)
}

/* flush master's mc_list from slave */
netif_tx_lock_bh(bond_dev);
bond_mc_list_flush(bond_dev, slave_dev);
netif_tx_unlock_bh(bond_dev);
}

netdev_set_master(slave_dev, NULL);
Expand Down Expand Up @@ -3937,8 +3943,6 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
struct bonding *bond = bond_dev->priv;
struct dev_mc_list *dmi;

write_lock_bh(&bond->lock);

/*
* Do promisc before checking multicast_mode
*/
Expand All @@ -3959,6 +3963,8 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
bond_set_allmulti(bond, -1);
}

read_lock(&bond->lock);

bond->flags = bond_dev->flags;

/* looking for addresses to add to slaves' mc list */
Expand All @@ -3979,7 +3985,7 @@ static void bond_set_multicast_list(struct net_device *bond_dev)
bond_mc_list_destroy(bond);
bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC);

write_unlock_bh(&bond->lock);
read_unlock(&bond->lock);
}

/*
Expand Down Expand Up @@ -4526,7 +4532,9 @@ static void bond_free_all(void)
struct net_device *bond_dev = bond->dev;

bond_work_cancel_all(bond);
netif_tx_lock_bh(bond_dev);
bond_mc_list_destroy(bond);
netif_tx_unlock_bh(bond_dev);
/* Release the bonded slaves */
bond_release_all(bond_dev);
bond_deinit(bond_dev);
Expand Down

0 comments on commit 80ee5ad

Please sign in to comment.