Commit f80889a5 authored by dingtianhong's avatar dingtianhong Committed by David S. Miller

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: default avatarDing Tianhong <dingtianhong@huawei.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 455016e5
...@@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1543,9 +1543,11 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
bond_set_carrier(bond); bond_set_carrier(bond);
if (USES_PRIMARY(bond->params.mode)) { if (USES_PRIMARY(bond->params.mode)) {
block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock); write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond); bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock); write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
} }
pr_info("%s: enslaving %s as a%s interface with a%s link.\n", pr_info("%s: enslaving %s as a%s interface with a%s link.\n",
...@@ -1571,10 +1573,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev) ...@@ -1571,10 +1573,12 @@ int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
if (bond->primary_slave == new_slave) if (bond->primary_slave == new_slave)
bond->primary_slave = NULL; bond->primary_slave = NULL;
if (bond->curr_active_slave == new_slave) { if (bond->curr_active_slave == new_slave) {
block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock); write_lock_bh(&bond->curr_slave_lock);
bond_change_active_slave(bond, NULL); bond_change_active_slave(bond, NULL);
bond_select_active_slave(bond); bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock); write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
} }
slave_disable_netpoll(new_slave); slave_disable_netpoll(new_slave);
...@@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event, ...@@ -2864,9 +2868,12 @@ static int bond_slave_netdev_event(unsigned long event,
pr_info("%s: Primary slave changed to %s, reselecting active slave.\n", pr_info("%s: Primary slave changed to %s, reselecting active slave.\n",
bond->dev->name, bond->primary_slave ? slave_dev->name : bond->dev->name, bond->primary_slave ? slave_dev->name :
"none"); "none");
block_netpoll_tx();
write_lock_bh(&bond->curr_slave_lock); write_lock_bh(&bond->curr_slave_lock);
bond_select_active_slave(bond); bond_select_active_slave(bond);
write_unlock_bh(&bond->curr_slave_lock); write_unlock_bh(&bond->curr_slave_lock);
unblock_netpoll_tx();
break; break;
case NETDEV_FEAT_CHANGE: case NETDEV_FEAT_CHANGE:
bond_compute_features(bond); bond_compute_features(bond);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment