diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2013-09-25 09:20:17 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-09-26 16:02:05 -0400 |
commit | 6475ae4ceea2f430db1daabf6460a9f36bc97438 (patch) | |
tree | d62241c4ded183e28bc77b25a22c921f7cf402be /drivers/net/bonding/bond_alb.c | |
parent | c33d78874eeb6c28909158719043fa2a5fd18f0a (diff) | |
download | linux-6475ae4ceea2f430db1daabf6460a9f36bc97438.tar.gz linux-6475ae4ceea2f430db1daabf6460a9f36bc97438.tar.bz2 linux-6475ae4ceea2f430db1daabf6460a9f36bc97438.zip |
bonding: rework rlb_next_rx_slave() to use bond_for_each_slave()
Currently, we're using bond_for_each_slave_from(), which is really hard to
implement under RCU and/or neighbour list.
Remove it and use bond_for_each_slave() instead, taking care of the last
used slave.
Also, rename next_rx_slave to rx_slave and store the current (last)
rx_slave.
CC: Jay Vosburgh <fubar@us.ibm.com>
CC: Andy Gospodarek <andy@greyhouse.net>
Signed-off-by: Veaceslav Falico <vfalico@redhat.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bonding/bond_alb.c')
-rw-r--r-- | drivers/net/bonding/bond_alb.c | 41 |
1 files changed, 21 insertions, 20 deletions
diff --git a/drivers/net/bonding/bond_alb.c b/drivers/net/bonding/bond_alb.c index f4929cee21a6..c5b85ad5554d 100644 --- a/drivers/net/bonding/bond_alb.c +++ b/drivers/net/bonding/bond_alb.c @@ -383,30 +383,31 @@ out: static struct slave *rlb_next_rx_slave(struct bonding *bond) { struct alb_bond_info *bond_info = &(BOND_ALB_INFO(bond)); - struct slave *rx_slave, *slave, *start_at; - int i = 0; - - if (bond_info->next_rx_slave) - start_at = bond_info->next_rx_slave; - else - start_at = bond_first_slave(bond); - - rx_slave = NULL; + struct slave *before = NULL, *rx_slave = NULL, *slave; + struct list_head *iter; + bool found = false; - bond_for_each_slave_from(bond, slave, i, start_at) { - if (SLAVE_IS_OK(slave)) { - if (!rx_slave) { - rx_slave = slave; - } else if (slave->speed > rx_slave->speed) { + bond_for_each_slave(bond, slave, iter) { + if (!SLAVE_IS_OK(slave)) + continue; + if (!found) { + if (!before || before->speed < slave->speed) + before = slave; + } else { + if (!rx_slave || rx_slave->speed < slave->speed) rx_slave = slave; - } } + if (slave == bond_info->rx_slave) + found = true; } + /* we didn't find anything after the current or we have something + * better before and up to the current slave + */ + if (!rx_slave || (before && rx_slave->speed < before->speed)) + rx_slave = before; - if (rx_slave) { - slave = bond_next_slave(bond, rx_slave); - bond_info->next_rx_slave = slave; - } + if (rx_slave) + bond_info->rx_slave = rx_slave; return rx_slave; } @@ -1611,7 +1612,7 @@ void bond_alb_deinit_slave(struct bonding *bond, struct slave *slave) tlb_clear_slave(bond, slave, 0); if (bond->alb_info.rlb_enabled) { - bond->alb_info.next_rx_slave = NULL; + bond->alb_info.rx_slave = NULL; rlb_clear_slave(bond, slave); } } |