aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJay Vosburgh <fubar@us.ibm.com>2007-10-17 20:37:47 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-23 20:32:00 -0400
commitcf5f9044934658dd3ffc628a60cd37c70f8168b1 (patch)
tree406baa95870c3e86858fd9ff98bc145c53dfa6ac
parent1b76b31693d4a6088dec104ff6a6ead54081a3c2 (diff)
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: Andy Gospodarek <andy@greyhouse.net> Signed-off-by: Jay Vosburgh <fubar@us.ibm.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
-rw-r--r--drivers/net/bonding/bond_main.c25
-rw-r--r--drivers/net/bonding/bonding.h1
2 files changed, 13 insertions, 13 deletions
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index ed361d62d702..862ed8ece14e 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -4057,8 +4057,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
4057{ 4057{
4058 struct bonding *bond = bond_dev->priv; 4058 struct bonding *bond = bond_dev->priv;
4059 struct slave *slave, *start_at; 4059 struct slave *slave, *start_at;
4060 int i; 4060 int i, slave_no, res = 1;
4061 int res = 1;
4062 4061
4063 read_lock(&bond->lock); 4062 read_lock(&bond->lock);
4064 4063
@@ -4066,29 +4065,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev
4066 goto out; 4065 goto out;
4067 } 4066 }
4068 4067
4069 read_lock(&bond->curr_slave_lock); 4068 /*
4070 slave = start_at = bond->curr_active_slave; 4069 * Concurrent TX may collide on rr_tx_counter; we accept that
4071 read_unlock(&bond->curr_slave_lock); 4070 * as being rare enough not to justify using an atomic op here
4071 */
4072 slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
4072 4073
4073 if (!slave) { 4074 bond_for_each_slave(bond, slave, i) {
4074 goto out; 4075 slave_no--;
4076 if (slave_no < 0) {
4077 break;
4078 }
4075 } 4079 }
4076 4080
4081 start_at = slave;
4077 bond_for_each_slave_from(bond, slave, i, start_at) { 4082 bond_for_each_slave_from(bond, slave, i, start_at) {
4078 if (IS_UP(slave->dev) && 4083 if (IS_UP(slave->dev) &&
4079 (slave->link == BOND_LINK_UP) && 4084 (slave->link == BOND_LINK_UP) &&
4080 (slave->state == BOND_STATE_ACTIVE)) { 4085 (slave->state == BOND_STATE_ACTIVE)) {
4081 res = bond_dev_queue_xmit(bond, skb, slave->dev); 4086 res = bond_dev_queue_xmit(bond, skb, slave->dev);
4082
4083 write_lock(&bond->curr_slave_lock);
4084 bond->curr_active_slave = slave->next;
4085 write_unlock(&bond->curr_slave_lock);
4086
4087 break; 4087 break;
4088 } 4088 }
4089 } 4089 }
4090 4090
4091
4092out: 4091out:
4093 if (res) { 4092 if (res) {
4094 /* no suitable interface, frame not sent */ 4093 /* no suitable interface, frame not sent */
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index a8f2384f550d..d1ed14bf1ccb 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -197,6 +197,7 @@ struct bonding {
197 int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int); 197 int (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
198 __be32 master_ip; 198 __be32 master_ip;
199 u16 flags; 199 u16 flags;
200 u16 rr_tx_counter;
200 struct ad_bond_info ad_info; 201 struct ad_bond_info ad_info;
201 struct alb_bond_info alb_info; 202 struct alb_bond_info alb_info;
202 struct bond_params params; 203 struct bond_params params;