bonding: restructure and add rcu for bond_for_each_slave_next()
Subsystems (3)
PATCH v2 5/6 bonding: restructure and add rcu for bond_for_each_slave_next()
Remove the wordy int and add bond_for_each_slave_next_rcu() for future use.
--- drivers/net/bonding/bond_alb.c | 3 +-- drivers/net/bonding/bond_main.c | 6 ++---- drivers/net/bonding/bonding.h | 30 ++++++++++++++++++++++++++---- 3 files changed, 29 insertions(+), 10 deletions(-)
drivers/net/bonding/bond_alb.c +1 -2
@@ -383,7 +383,6 @@ 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;
@@ -392,7 +391,7 @@ static struct slave *rlb_next_rx_slave(struct bonding *bond) rx_slave =NULL ; -bond_for_each_slave_from (bond, slave, i, start_at) { +bond_for_each_slave_from (bond, slave, start_at) {if (SLAVE_IS_OK (slave)) {if (!rx_slave) { rx_slave = slave;
drivers/net/bonding/bond_main.c +2 -4
@@ -782,7 +782,6 @@ static struct slave *bond_find_best_slave(struct bonding *bond)struct slave *new_active, *old_active;struct slave *bestslave =NULL ;int mintime = bond->params.updelay; -int i; new_active = bond->curr_active_slave;
@@ -801,7 +800,7 @@ static struct slave *bond_find_best_slave(struct bonding *bond)/* remember where to stop iterating over the slaves */ old_active = new_active; -bond_for_each_slave_from (bond, new_active, i, old_active) { +bond_for_each_slave_from (bond, new_active, old_active) {if (new_active->link ==BOND_LINK_UP ) {return new_active; } else if (new_active->link == BOND_LINK_BACK &&
@@ -2756,7 +2755,6 @@ do_failover:static void bond_ab_arp_probe (struct bonding *bond) {struct slave *slave, *next_slave; -int i;read_lock (&bond->curr_slave_lock);
@@ -2788,7 +2786,7 @@ static void bond_ab_arp_probe(struct bonding *bond)/* search for next candidate */ next_slave =bond_next_slave (bond, bond->current_arp_slave); -bond_for_each_slave_from (bond, slave, i, next_slave) { +bond_for_each_slave_from (bond, slave, next_slave) {if (IS_UP (slave->dev)) { slave->link =BOND_LINK_BACK ;bond_set_slave_active_flags (slave);
drivers/net/bonding/bonding.h +26 -4
@@ -115,18 +115,40 @@ (bond_is_first_slave (bond, pos) ?bond_last_slave_rcu (bond) : \bond_to_slave_rcu ((pos)->list.prev)) +/* Check whether the slave is the only one in bond */ +#define bond_is_only_slave (bond, pos) \ + (((pos)->list.prev == &(bond)->slave_list) && \ + ((pos)->list.next == &(bond)->slave_list)) +/** * bond_for_each_slave_from - iterate the slaves list from a starting point * @bond: the bond holding this list. * @pos: current slave. -* @cnt: counter for max number of moves * @start: starting point. * * Caller must hold bond->lock */ -#define bond_for_each_slave_from (bond, pos, cnt, start) \ - for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \ - cnt++, pos = bond_next_slave(bond, pos)) +#define bond_for_each_slave_from (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave(bond, pos))) + +/** +* bond_for_each_slave_from_rcu - iterate the slaves list from a starting point +* @bond: the bond holding this list. +* @pos: current slave. +* @start: starting point. +* +* Caller must hold rcu_read_lock +*/ +#define bond_for_each_slave_from_rcu (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry_rcu(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave_rcu(bond, pos)))/** * bond_for_each_slave - iterate over all slaves
Signature · 1 line
1.8.2.1
On Wed, Sep 04, 2013 at 05:44:15PM +0800, Ding Tianhong wrote:
...snip...
drivers/net/bonding/bonding.h line 121
Quoted 4 lines
drivers/net/bonding/bonding.h +4
-0+/* Check whether the slave is the only one in bond */ +#define bond_is_only_slave (bond, pos) \ + (((pos)->list.prev == &(bond)->slave_list) && \ + ((pos)->list.next == &(bond)->slave_list))
Could be done without pos at all -
!list_empty(&(bond)->slave_list) && \
&(bond)->slave_list.next == &(bond)->slave_list.prev
If we have only one slave and pos is NOT our slave then... well.. we have big troubles.
Quoted 10 lines
+
/**
*bond_for_each_slave_from- iterate the slaves list from a starting point
* @bond: the bond holding this list.
* @pos: current slave.
- * @cnt: counter for max number of moves
* @start: starting point.
*
* Caller must holdbond->lock
*/
drivers/net/bonding/bonding.h line 136
Quoted 9 lines
drivers/net/bonding/bonding.h +6
-3-#define bond_for_each_slave_from (bond, pos, cnt, start) \ - for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \ - cnt++, pos = bond_next_slave(bond, pos)) +#define bond_for_each_slave_from (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave(bond, pos)))
Did you check that?
pos = slave1 (bond has more than one slave);
pos && &pos->list != &slave1->list - false.
We won't ever enter this loop if we have >1 slaves.
I don't understand this at all.
Quoted 5 lines
drivers/net/bonding/bonding.h +5
-0+ +/** +* bond_for_each_slave_from_rcu - iterate the slaves list from a starting point +* @bond: the bond holding this list. +* @pos: current slave.
drivers/net/bonding/bonding.h line 151
Quoted 10 lines
drivers/net/bonding/bonding.h +10
-0+* @start: starting point. +* +* Caller must hold rcu_read_lock +*/ +#define bond_for_each_slave_from_rcu (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry_rcu(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave_rcu(bond, pos)))
Ditto as bond_for_each_slave_from() and, also, see my comment about RCU from patch 1.
Quoted 8 lines
/**
*bond_for_each_slave- iterate over all slavesSignature · 1 line
1.8.2.1
Quoted 9 lines · Veaceslav Falico
On Wed, Sep 04, 2013 at 05:44:15PM +0800, Ding Tianhong wrote:
...snip...drivers/net/bonding/bonding.h line 121
Quoted 4 lines
drivers/net/bonding/bonding.h +4
-0+/* Check whether the slave is the only one in bond */ +#define bond_is_only_slave (bond, pos) \ + (((pos)->list.prev == &(bond)->slave_list) && \ + ((pos)->list.next == &(bond)->slave_list))Could be done without pos at all -
Quoted 6 lines
!list_empty(&(bond)->slave_list) && \
&(bond)->slave_list.next == &(bond)->slave_list.prevIf we have only one slave and pos is NOT our slave then... well.. we have big troubles.
yes, more simple more beautiful, thanks.
but if the pos is not our slave, it is the mistake, not bug. :)
Quoted 22 lines
Quoted 10 lines
+
/**
*bond_for_each_slave_from- iterate the slaves list from a starting point
* @bond: the bond holding this list.
* @pos: current slave.
- * @cnt: counter for max number of moves
* @start: starting point.
*
* Caller must holdbond->lock
*/drivers/net/bonding/bonding.h line 136
Quoted 9 lines
drivers/net/bonding/bonding.h +6
-3-#define bond_for_each_slave_from (bond, pos, cnt, start) \ - for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \ - cnt++, pos = bond_next_slave(bond, pos)) +#define bond_for_each_slave_from (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave(bond, pos)))Did you check that?
Quoted 7 lines
pos = slave1 (bond has more than one slave);
pos &&&pos->list!=&slave1->list- false.We won't ever enter this loop if we have >1 slaves.
I don't understand this at all.
ok, the logic is : if slaves == 1, run once for the slave.
if slaves > 1, run loops until reach the end list.
I could not get a better way to simplify the function, I think it is a suitable scheme.
by the way, I test the function and works well. :)
Quoted 33 lines
Quoted 8 lines
drivers/net/bonding/bonding.h +3
-0+ +/** +* bond_for_each_slave_from_rcu - iterate the slaves list from a starting point
+ * @bond: the bond holding this list.
+ * @pos: current slave.
+ * @start: starting point.
+ *Quoted 8 lines
+ * Caller must hold
rcu_read_lock
+ */
+#definebond_for_each_slave_from_rcu(bond, pos, start)\
+ for (pos = start; pos && (bond_is_only_slave(bond, start)? \
+&pos->list!=&bond->slave_list: \
+&pos->list!=&start->list);bond_is_only_slave(bond, start)? \
+ (pos =list_entry_rcu(pos->list.next, typeof(*pos), list)) : \
+ (pos =bond_next_slave_rcu(bond, pos)))Ditto as
bond_for_each_slave_from()and, also, see my comment about RCU from patch 1.Quoted 8 lines
/**
*bond_for_each_slave- iterate over all slavesSignature · 1 line
1.8.2.1Signature · 3 lines
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
Quoted 45 lines · Ding Tianhong
Quoted 9 lines · Veaceslav Falico
On Wed, Sep 04, 2013 at 05:44:15PM +0800, Ding Tianhong wrote:
...snip...drivers/net/bonding/bonding.h line 121
Quoted 4 lines
drivers/net/bonding/bonding.h +4
-0+/* Check whether the slave is the only one in bond */ +#define bond_is_only_slave (bond, pos) \ + (((pos)->list.prev == &(bond)->slave_list) && \ + ((pos)->list.next == &(bond)->slave_list))Could be done without pos at all -
Quoted 6 lines
!list_empty(&(bond)->slave_list) && \
&(bond)->slave_list.next == &(bond)->slave_list.prevIf we have only one slave and pos is NOT our slave then... well.. we have big troubles.
yes, more simple more beautiful, thanks.
but if the pos is not our slave, it is the mistake, not bug. :)
Quoted 25 lines
Quoted 10 lines
+
/**
*bond_for_each_slave_from- iterate the slaves list from a starting point
* @bond: the bond holding this list.
* @pos: current slave.
- * @cnt: counter for max number of moves
* @start: starting point.
*
* Caller must holdbond->lock
*/drivers/net/bonding/bonding.h line 136
Quoted 9 lines
drivers/net/bonding/bonding.h +6
-3-#define bond_for_each_slave_from (bond, pos, cnt, start) \ - for (cnt = 0, pos = start; pos && cnt < (bond)->slave_cnt; \ - cnt++, pos = bond_next_slave(bond, pos)) +#define bond_for_each_slave_from (bond, pos, start) \ + for (pos = start; pos && (bond_is_only_slave(bond, start) ? \ + &pos->list != &bond->slave_list : \ + &pos->list != &start->list); bond_is_only_slave(bond, start) ? \ + (pos = list_entry(pos->list.next, typeof(*pos), list)) : \ + (pos = bond_next_slave(bond, pos)))Did you check that?
pos = slave1 (bond has more than one slave);
pos &&&pos->list!=&slave1->list- false.
Quoted 6 lines
Quoted 4 lines
We won't ever enter this loop if we have >1 slaves.
I don't understand this at all.
ok, the logic is : if slaves == 1, run once for the slave.
your code, actually, says differently:
(bond_is_only_slave(bond, start) ? &pos->list != &bond->slave_list :
which means that if bond_is_only_slave(bond, start) == true then we check &pos->list != &bond->slave_list, so we run till the end of the list.
Ternary operator works like that
expression ? what_to_do_if_true : what_to_do_if_false
http://en.wikipedia.org/wiki/?:#C
Quoted 1 line
if slaves > 1, run loops until reach the end list.
Here we test for &pos->list != &start->list, which is false cause pos == start.
Quoted 1 line
I could not get a better way to simplify the function, I think it is a suitable scheme.
Nope. bond_for_each_slave_from() is supposed to loop through slaves from a starting slave and till that starting slave, not included.
Your loop... I don't understand what it does. But clearly not what it was doing (and supposed to do).
Quoted 37 lines
by the way, I test the function and works well. :)
Quoted 33 lines
Quoted 8 lines
drivers/net/bonding/bonding.h +3
-0+ +/** +* bond_for_each_slave_from_rcu - iterate the slaves list from a starting point
+ * @bond: the bond holding this list.
+ * @pos: current slave.
+ * @start: starting point.
+ *Quoted 8 lines
+ * Caller must hold
rcu_read_lock
+ */
+#definebond_for_each_slave_from_rcu(bond, pos, start)\
+ for (pos = start; pos && (bond_is_only_slave(bond, start)? \
+&pos->list!=&bond->slave_list: \
+&pos->list!=&start->list);bond_is_only_slave(bond, start)? \
+ (pos =list_entry_rcu(pos->list.next, typeof(*pos), list)) : \
+ (pos =bond_next_slave_rcu(bond, pos)))Ditto as
bond_for_each_slave_from()and, also, see my comment about RCU from patch 1.Quoted 8 lines
/**
*bond_for_each_slave- iterate over all slavesSignature · 1 line
1.8.2.1Signature · 3 lines
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