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 <[EMAIL PROTECTED]>
Signed-off-by: Jay Vosburgh <[EMAIL PROTECTED]>
---
 drivers/net/bonding/bond_main.c |   25 ++++++++++++-------------
 drivers/net/bonding/bonding.h   |    1 +
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 28ae961..4541a1b 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -3928,8 +3928,7 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, 
struct net_device *bond_dev
 {
        struct bonding *bond = bond_dev->priv;
        struct slave *slave, *start_at;
-       int i;
-       int res = 1;
+       int i, slave_no, res = 1;
 
        read_lock(&bond->lock);
 
@@ -3937,29 +3936,29 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, 
struct net_device *bond_dev
                goto out;
        }
 
-       read_lock(&bond->curr_slave_lock);
-       slave = start_at = bond->curr_active_slave;
-       read_unlock(&bond->curr_slave_lock);
+       /*
+        * Concurrent TX may collide on rr_tx_counter; we accept that
+        * as being rare enough not to justify using an atomic op here
+        */
+       slave_no = bond->rr_tx_counter++ % bond->slave_cnt;
 
-       if (!slave) {
-               goto out;
+       bond_for_each_slave(bond, slave, i) {
+               slave_no--;
+               if (slave_no < 0) {
+                       break;
+               }
        }
 
+       start_at = slave;
        bond_for_each_slave_from(bond, slave, i, start_at) {
                if (IS_UP(slave->dev) &&
                    (slave->link == BOND_LINK_UP) &&
                    (slave->state == BOND_STATE_ACTIVE)) {
                        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;
                }
        }
 
-
 out:
        if (res) {
                /* no suitable interface, frame not sent */
diff --git a/drivers/net/bonding/bonding.h b/drivers/net/bonding/bonding.h
index 4986d0f..e7c3671 100644
--- a/drivers/net/bonding/bonding.h
+++ b/drivers/net/bonding/bonding.h
@@ -183,6 +183,7 @@ struct bonding {
        rwlock_t lock;
        rwlock_t curr_slave_lock;
        s8       kill_timers;
+       u16      rr_tx_counter;
        struct   net_device_stats stats;
 #ifdef CONFIG_PROC_FS
        struct   proc_dir_entry *proc_entry;
-- 
1.5.3.1

-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to