diff options
author | Jay Vosburgh <fubar@us.ibm.com> | 2008-01-29 21:07:44 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-03 07:28:12 -0500 |
commit | 80ee5ad23150f1f3fe8d35728e860850ccea44da (patch) | |
tree | 4bab44a6762a87c59ba22ab688326f1a6fe075a1 | |
parent | a42e534f1b6be7f2f68f83d29588c3f2736b4d25 (diff) |
bonding: fix set_multicast_list locking
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>
-rw-r--r-- | drivers/net/bonding/bond_main.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 2766855a5aee..65c7ebafaacd 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1464,10 +1464,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1464 | dev_set_allmulti(slave_dev, 1); | 1464 | dev_set_allmulti(slave_dev, 1); |
1465 | } | 1465 | } |
1466 | 1466 | ||
1467 | netif_tx_lock_bh(bond_dev); | ||
1467 | /* upload master's mc_list to new slave */ | 1468 | /* upload master's mc_list to new slave */ |
1468 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { | 1469 | for (dmi = bond_dev->mc_list; dmi; dmi = dmi->next) { |
1469 | dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); | 1470 | dev_mc_add (slave_dev, dmi->dmi_addr, dmi->dmi_addrlen, 0); |
1470 | } | 1471 | } |
1472 | netif_tx_unlock_bh(bond_dev); | ||
1471 | } | 1473 | } |
1472 | 1474 | ||
1473 | if (bond->params.mode == BOND_MODE_8023AD) { | 1475 | if (bond->params.mode == BOND_MODE_8023AD) { |
@@ -1821,7 +1823,9 @@ int bond_release(struct net_device *bond_dev, struct net_device *slave_dev) | |||
1821 | } | 1823 | } |
1822 | 1824 | ||
1823 | /* flush master's mc_list from slave */ | 1825 | /* flush master's mc_list from slave */ |
1826 | netif_tx_lock_bh(bond_dev); | ||
1824 | bond_mc_list_flush(bond_dev, slave_dev); | 1827 | bond_mc_list_flush(bond_dev, slave_dev); |
1828 | netif_tx_unlock_bh(bond_dev); | ||
1825 | } | 1829 | } |
1826 | 1830 | ||
1827 | netdev_set_master(slave_dev, NULL); | 1831 | netdev_set_master(slave_dev, NULL); |
@@ -1942,7 +1946,9 @@ static int bond_release_all(struct net_device *bond_dev) | |||
1942 | } | 1946 | } |
1943 | 1947 | ||
1944 | /* flush master's mc_list from slave */ | 1948 | /* flush master's mc_list from slave */ |
1949 | netif_tx_lock_bh(bond_dev); | ||
1945 | bond_mc_list_flush(bond_dev, slave_dev); | 1950 | bond_mc_list_flush(bond_dev, slave_dev); |
1951 | netif_tx_unlock_bh(bond_dev); | ||
1946 | } | 1952 | } |
1947 | 1953 | ||
1948 | netdev_set_master(slave_dev, NULL); | 1954 | netdev_set_master(slave_dev, NULL); |
@@ -3937,8 +3943,6 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3937 | struct bonding *bond = bond_dev->priv; | 3943 | struct bonding *bond = bond_dev->priv; |
3938 | struct dev_mc_list *dmi; | 3944 | struct dev_mc_list *dmi; |
3939 | 3945 | ||
3940 | write_lock_bh(&bond->lock); | ||
3941 | |||
3942 | /* | 3946 | /* |
3943 | * Do promisc before checking multicast_mode | 3947 | * Do promisc before checking multicast_mode |
3944 | */ | 3948 | */ |
@@ -3959,6 +3963,8 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3959 | bond_set_allmulti(bond, -1); | 3963 | bond_set_allmulti(bond, -1); |
3960 | } | 3964 | } |
3961 | 3965 | ||
3966 | read_lock(&bond->lock); | ||
3967 | |||
3962 | bond->flags = bond_dev->flags; | 3968 | bond->flags = bond_dev->flags; |
3963 | 3969 | ||
3964 | /* looking for addresses to add to slaves' mc list */ | 3970 | /* looking for addresses to add to slaves' mc list */ |
@@ -3979,7 +3985,7 @@ static void bond_set_multicast_list(struct net_device *bond_dev) | |||
3979 | bond_mc_list_destroy(bond); | 3985 | bond_mc_list_destroy(bond); |
3980 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); | 3986 | bond_mc_list_copy(bond_dev->mc_list, bond, GFP_ATOMIC); |
3981 | 3987 | ||
3982 | write_unlock_bh(&bond->lock); | 3988 | read_unlock(&bond->lock); |
3983 | } | 3989 | } |
3984 | 3990 | ||
3985 | /* | 3991 | /* |
@@ -4526,7 +4532,9 @@ static void bond_free_all(void) | |||
4526 | struct net_device *bond_dev = bond->dev; | 4532 | struct net_device *bond_dev = bond->dev; |
4527 | 4533 | ||
4528 | bond_work_cancel_all(bond); | 4534 | bond_work_cancel_all(bond); |
4535 | netif_tx_lock_bh(bond_dev); | ||
4529 | bond_mc_list_destroy(bond); | 4536 | bond_mc_list_destroy(bond); |
4537 | netif_tx_unlock_bh(bond_dev); | ||
4530 | /* Release the bonded slaves */ | 4538 | /* Release the bonded slaves */ |
4531 | bond_release_all(bond_dev); | 4539 | bond_release_all(bond_dev); |
4532 | bond_deinit(bond_dev); | 4540 | bond_deinit(bond_dev); |