aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding/bond_sysfs.c
diff options
context:
space:
mode:
authorNeil Horman <nhorman@tuxdriver.com>2010-10-13 12:01:50 -0400
committerDavid S. Miller <davem@davemloft.net>2010-10-18 11:32:07 -0400
commite843fa50887582c867d8b7995f81fe9c1a076806 (patch)
tree5a8e34f5afaeeed539d519b0e91b7a4c92268b11 /drivers/net/bonding/bond_sysfs.c
parentc2355e1ab910278a94d487b78590ee3c8eecd08a (diff)
bonding: Fix deadlock in bonding driver resulting from internal locking when using netpoll
The monitoring paths in the bonding driver take write locks that are shared by the tx path. If netconsole is in use, these paths can call printk which puts us in the netpoll tx path, which, if netconsole is attached to the bonding driver, result in deadlock (the xmit_lock guards are useless in netpoll_send_skb, as the monitor paths in the bonding driver don't claim the xmit_lock, nor should they). The solution is to use a per cpu flag internal to the driver to indicate when a cpu is holding the lock in a path that might recusrse into the tx path for the driver via netconsole. By checking this flag on transmit, we can defer the sending of the netconsole frames until a later time using the retransmit feature of netpoll_send_skb that is triggered on the return code NETDEV_TX_BUSY. I've tested this and am able to transmit via netconsole while causing failover conditions on the bond slave links. Signed-off-by: Neil Horman <nhorman@tuxdriver.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_sysfs.c')
-rw-r--r--drivers/net/bonding/bond_sysfs.c8
1 files changed, 8 insertions, 0 deletions
diff --git a/drivers/net/bonding/bond_sysfs.c b/drivers/net/bonding/bond_sysfs.c
index 01b4c3f5d9e7..8fd0174c5380 100644
--- a/drivers/net/bonding/bond_sysfs.c
+++ b/drivers/net/bonding/bond_sysfs.c
@@ -1066,6 +1066,7 @@ static ssize_t bonding_store_primary(struct device *d,
1066 1066
1067 if (!rtnl_trylock()) 1067 if (!rtnl_trylock())
1068 return restart_syscall(); 1068 return restart_syscall();
1069 block_netpoll_tx();
1069 read_lock(&bond->lock); 1070 read_lock(&bond->lock);
1070 write_lock_bh(&bond->curr_slave_lock); 1071 write_lock_bh(&bond->curr_slave_lock);
1071 1072
@@ -1101,6 +1102,7 @@ static ssize_t bonding_store_primary(struct device *d,
1101out: 1102out:
1102 write_unlock_bh(&bond->curr_slave_lock); 1103 write_unlock_bh(&bond->curr_slave_lock);
1103 read_unlock(&bond->lock); 1104 read_unlock(&bond->lock);
1105 unblock_netpoll_tx();
1104 rtnl_unlock(); 1106 rtnl_unlock();
1105 1107
1106 return count; 1108 return count;
@@ -1146,11 +1148,13 @@ static ssize_t bonding_store_primary_reselect(struct device *d,
1146 bond->dev->name, pri_reselect_tbl[new_value].modename, 1148 bond->dev->name, pri_reselect_tbl[new_value].modename,
1147 new_value); 1149 new_value);
1148 1150
1151 block_netpoll_tx();
1149 read_lock(&bond->lock); 1152 read_lock(&bond->lock);
1150 write_lock_bh(&bond->curr_slave_lock); 1153 write_lock_bh(&bond->curr_slave_lock);
1151 bond_select_active_slave(bond); 1154 bond_select_active_slave(bond);
1152 write_unlock_bh(&bond->curr_slave_lock); 1155 write_unlock_bh(&bond->curr_slave_lock);
1153 read_unlock(&bond->lock); 1156 read_unlock(&bond->lock);
1157 unblock_netpoll_tx();
1154out: 1158out:
1155 rtnl_unlock(); 1159 rtnl_unlock();
1156 return ret; 1160 return ret;
@@ -1232,6 +1236,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
1232 1236
1233 if (!rtnl_trylock()) 1237 if (!rtnl_trylock())
1234 return restart_syscall(); 1238 return restart_syscall();
1239
1240 block_netpoll_tx();
1235 read_lock(&bond->lock); 1241 read_lock(&bond->lock);
1236 write_lock_bh(&bond->curr_slave_lock); 1242 write_lock_bh(&bond->curr_slave_lock);
1237 1243
@@ -1288,6 +1294,8 @@ static ssize_t bonding_store_active_slave(struct device *d,
1288 out: 1294 out:
1289 write_unlock_bh(&bond->curr_slave_lock); 1295 write_unlock_bh(&bond->curr_slave_lock);
1290 read_unlock(&bond->lock); 1296 read_unlock(&bond->lock);
1297 unblock_netpoll_tx();
1298
1291 rtnl_unlock(); 1299 rtnl_unlock();
1292 1300
1293 return count; 1301 return count;