Commit cf5f9044 authored by Jay Vosburgh's avatar Jay Vosburgh Committed by Jeff Garzik

bonding: Convert balance-rr transmit to new locking

	Change locking in balance-rr transmit processing to use a free
running counter to determine which slave to transmit on.  Instead, a
free-running counter is maintained, and modulo arithmetic used to select
a slave for transmit.

	This removes lock operations from the TX path, and eliminates
a deadlock introduced by the conversion to work queues.
Signed-off-by: default avatarAndy Gospodarek <andy@greyhouse.net>
Signed-off-by: default avatarJay Vosburgh <fubar@us.ibm.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 1b76b316
...@@ -4057,8 +4057,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev ...@@ -4057,8 +4057,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
{ {
struct bonding *bond = bond_dev->priv; struct bonding *bond = bond_dev->priv;
struct slave *slave, *start_at; struct slave *slave, *start_at;
int i; int i, slave_no, res = 1;
int res = 1;
read_lock(&bond->lock); read_lock(&bond->lock);
...@@ -4066,29 +4065,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev ...@@ -4066,29 +4065,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
goto out; goto out;
} }
read_lock(&bond->curr_slave_lock); /*
slave = start_at = bond->curr_active_slave; * Concurrent TX may collide on rr_tx_counter; we accept that
read_unlock(&bond->curr_slave_lock); * as being rare enough not to justify using an atomic op here
*/
slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
if (!slave) { bond_for_each_slave(bond, slave, i) {
goto out; slave_no--;
if (slave_no < 0) {
break;
}
} }
start_at = slave;
bond_for_each_slave_from(bond, slave, i, start_at) { bond_for_each_slave_from(bond, slave, i, start_at) {
if (IS_UP(slave->dev) && if (IS_UP(slave->dev) &&
(slave->link == BOND_LINK_UP) && (slave->link == BOND_LINK_UP) &&
(slave->state == BOND_STATE_ACTIVE)) { (slave->state == BOND_STATE_ACTIVE)) {
res = bond_dev_queue_xmit(bond, skb, slave->dev); res = bond_dev_queue_xmit(bond, skb, slave->dev);
write_lock(&bond->curr_slave_lock);
bond->curr_active_slave = slave->next;
write_unlock(&bond->curr_slave_lock);
break; break;
} }
} }
out: out:
if (res) { if (res) {
/* no suitable interface, frame not sent */ /* no suitable interface, frame not sent */
......
...@@ -197,6 +197,7 @@ struct bonding { ...@@ -197,6 +197,7 @@ struct bonding {
int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int); int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
__be32 master_ip; __be32 master_ip;
u16 flags; u16 flags;
u16 rr_tx_counter;
struct ad_bond_info ad_info; struct ad_bond_info ad_info;
struct alb_bond_info alb_info; struct alb_bond_info alb_info;
struct bond_params params; struct bond_params params;
......
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