aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bonding
diff options
context:
space:
mode:
authordingtianhong <dingtianhong@huawei.com>2014-02-11 23:06:40 -0500
committerDavid S. Miller <davem@davemloft.net>2014-02-13 17:08:29 -0500
commitf80889a5b79cae0b84465a90c21b1273a03b7973 (patch)
treeebafceda4aeb7c2e10ded3667b9bf47c2c0c79e3 /drivers/net/bonding
parent455016e5dc623cb784dbaa4f197054ab87d84c76 (diff)
bonding: Fix deadlock in bonding driver when using netpoll
The bonding driver take write locks and spin locks that are shared by the tx path in enslave processing and notification processing, If the netconsole is in use, the bonding can call printk which puts us in the netpoll tx path, if the netconsole is attached to the bonding driver, result in deadlock. So add protection for these place, by checking the netpoll_block_tx state, 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. Cc: Jay Vosburgh <fubar@us.ibm.com> Cc: Veaceslav Falico <vfalico@redhat.com> Cc: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Ding Tianhong <dingtianhong@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding')
-rw-r--r--drivers/net/bonding/bond_main.c7
1 files changed, 7 insertions, 0 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 71ba18efa15b..867664918715 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
1543 bond_set_carrier(bond); 1543 bond_set_carrier(bond);
1544 1544
1545 if (USES_PRIMARY(bond->params.mode)) { 1545 if (USES_PRIMARY(bond->params.mode)) {
1546 block_netpoll_tx();
1546 write_lock_bh(&bond->curr_slave_lock); 1547 write_lock_bh(&bond->curr_slave_lock);
1547 bond_select_active_slave(bond); 1548 bond_select_active_slave(bond);
1548 write_unlock_bh(&bond->curr_slave_lock); 1549 write_unlock_bh(&bond->curr_slave_lock);
1550 unblock_netpoll_tx();
1549 } 1551 }
1550 1552
1551 pr_info("%s: enslaving %s as a%s interface with a%s link.\n", 1553 pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
@@ -1571,10 +1573,12 @@ err_detach:
1571 if (bond->primary_slave == new_slave) 1573 if (bond->primary_slave == new_slave)
1572 bond->primary_slave = NULL; 1574 bond->primary_slave = NULL;
1573 if (bond->curr_active_slave == new_slave) { 1575 if (bond->curr_active_slave == new_slave) {
1576 block_netpoll_tx();
1574 write_lock_bh(&bond->curr_slave_lock); 1577 write_lock_bh(&bond->curr_slave_lock);
1575 bond_change_active_slave(bond, NULL); 1578 bond_change_active_slave(bond, NULL);
1576 bond_select_active_slave(bond); 1579 bond_select_active_slave(bond);
1577 write_unlock_bh(&bond->curr_slave_lock); 1580 write_unlock_bh(&bond->curr_slave_lock);
1581 unblock_netpoll_tx();
1578 } 1582 }
1579 slave_disable_netpoll(new_slave); 1583 slave_disable_netpoll(new_slave);
1580 1584
@@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event,
2864 pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", 2868 pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
2865 bond->dev->name, bond->primary_slave ? slave_dev->name : 2869 bond->dev->name, bond->primary_slave ? slave_dev->name :
2866 "none"); 2870 "none");
2871
2872 block_netpoll_tx();
2867 write_lock_bh(&bond->curr_slave_lock); 2873 write_lock_bh(&bond->curr_slave_lock);
2868 bond_select_active_slave(bond); 2874 bond_select_active_slave(bond);
2869 write_unlock_bh(&bond->curr_slave_lock); 2875 write_unlock_bh(&bond->curr_slave_lock);
2876 unblock_netpoll_tx();
2870 break; 2877 break;
2871 case NETDEV_FEAT_CHANGE: 2878 case NETDEV_FEAT_CHANGE:
2872 bond_compute_features(bond); 2879 bond_compute_features(bond);