diff options
author | dingtianhong <dingtianhong@huawei.com> | 2013-07-23 03:25:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-07-24 20:45:23 -0400 |
commit | c4cdef9b7183159c23c7302aaf270d64c549f557 (patch) | |
tree | 8e2f3c51ee4b7bfdf91b85e1b1760189e61eb649 /drivers/net/bonding | |
parent | f13bbc2f9aba00c7a37b499d23060616b9a4ef9e (diff) |
bonding: don't call slave_xxx_netpoll under spinlocks
The slave_xxx_netpoll will call synchronize_rcu_bh(),
so the function may schedule and sleep, it should't be
called under spinlocks.
bond_netpoll_setup() and bond_netpoll_cleanup() are always
protected by rtnl lock, it is no need to take the read lock,
as the slave list couldn't be changed outside rtnl lock.
Signed-off-by: Ding Tianhong <dingtianhong@huawei.com>
Cc: Jay Vosburgh <fubar@us.ibm.com>
Cc: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r-- | drivers/net/bonding/bond_main.c | 15 |
1 files changed, 3 insertions, 12 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index ae9864c9fa38..5cd8e0acf160 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c | |||
@@ -1219,8 +1219,9 @@ static void bond_poll_controller(struct net_device *bond_dev) | |||
1219 | { | 1219 | { |
1220 | } | 1220 | } |
1221 | 1221 | ||
1222 | static void __bond_netpoll_cleanup(struct bonding *bond) | 1222 | static void bond_netpoll_cleanup(struct net_device *bond_dev) |
1223 | { | 1223 | { |
1224 | struct bonding *bond = netdev_priv(bond_dev); | ||
1224 | struct slave *slave; | 1225 | struct slave *slave; |
1225 | int i; | 1226 | int i; |
1226 | 1227 | ||
@@ -1228,14 +1229,6 @@ static void __bond_netpoll_cleanup(struct bonding *bond) | |||
1228 | if (IS_UP(slave->dev)) | 1229 | if (IS_UP(slave->dev)) |
1229 | slave_disable_netpoll(slave); | 1230 | slave_disable_netpoll(slave); |
1230 | } | 1231 | } |
1231 | static void bond_netpoll_cleanup(struct net_device *bond_dev) | ||
1232 | { | ||
1233 | struct bonding *bond = netdev_priv(bond_dev); | ||
1234 | |||
1235 | read_lock(&bond->lock); | ||
1236 | __bond_netpoll_cleanup(bond); | ||
1237 | read_unlock(&bond->lock); | ||
1238 | } | ||
1239 | 1232 | ||
1240 | static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) | 1233 | static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, gfp_t gfp) |
1241 | { | 1234 | { |
@@ -1243,15 +1236,13 @@ static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, g | |||
1243 | struct slave *slave; | 1236 | struct slave *slave; |
1244 | int i, err = 0; | 1237 | int i, err = 0; |
1245 | 1238 | ||
1246 | read_lock(&bond->lock); | ||
1247 | bond_for_each_slave(bond, slave, i) { | 1239 | bond_for_each_slave(bond, slave, i) { |
1248 | err = slave_enable_netpoll(slave); | 1240 | err = slave_enable_netpoll(slave); |
1249 | if (err) { | 1241 | if (err) { |
1250 | __bond_netpoll_cleanup(bond); | 1242 | bond_netpoll_cleanup(dev); |
1251 | break; | 1243 | break; |
1252 | } | 1244 | } |
1253 | } | 1245 | } |
1254 | read_unlock(&bond->lock); | ||
1255 | return err; | 1246 | return err; |
1256 | } | 1247 | } |
1257 | 1248 | ||