bonding: Convert balance-rr transmit to new locking
authorJay Vosburgh <fubar@us.ibm.com>
Thu, 18 Oct 2007 00:37:47 +0000 (17:37 -0700)
committerJeff Garzik <jeff@garzik.org>
Wed, 24 Oct 2007 00:32:00 +0000 (20:32 -0400)
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>
drivers/net/bonding/bond_main.c
drivers/net/bonding/bonding.h

index ed361d62d702b27895377179ff8d379d0660a71c..862ed8ece14e6a627e485aa0727244c34246283a 100644 (file)
@@ -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 slave *slave, *start_at;
-       int i;
-       int res = 1;
+       int i, slave_no, res = 1;
 
        read_lock(&bond->lock);
 
@@ -4066,29 +4065,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 */
index a8f2384f550d0045632e645e42d9a00a11988f6b..d1ed14bf1ccba358d4e1e8b9a6044d16f1056f2f 100644 (file)
@@ -197,6 +197,7 @@ struct bonding {
        int      (*xmit_hash_policy)(struct sk_buff *, struct net_device *, int);
        __be32   master_ip;
        u16      flags;
+       u16      rr_tx_counter;
        struct   ad_bond_info ad_info;
        struct   alb_bond_info alb_info;
        struct   bond_params params;