diff options
author | Veaceslav Falico <vfalico@redhat.com> | 2014-01-10 05:59:45 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-01-14 01:22:27 -0500 |
commit | 49b7624eda6867d2803bcc5bbf6f25936184304a (patch) | |
tree | 8cf62ce9ae669d5587bbc7b9dc8ee504eecaed56 | |
parent | 768b954922e69a92a363bd4041cb93040ae4e9cf (diff) |
bonding: fix __get_active_agg() RCU logic
Currently, the implementation is meaningless - once again, we take the
slave structure and use it after we've exited RCU critical section.
Fix this by removing the rcu_read_lock() from __get_active_agg(), and
ensuring that all its callers are holding RCU.
Fixes: be79bd048 ("bonding: add RCU for bond_3ad_state_machine_handler()")
CC: dingtianhong@huawei.com
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>
-rw-r--r-- | drivers/net/bonding/bond_3ad.c | 10 |
1 files changed, 4 insertions, 6 deletions
diff --git a/drivers/net/bonding/bond_3ad.c b/drivers/net/bonding/bond_3ad.c index b49f421346a7..cce1f1bf90b4 100644 --- a/drivers/net/bonding/bond_3ad.c +++ b/drivers/net/bonding/bond_3ad.c | |||
@@ -678,6 +678,8 @@ static u32 __get_agg_bandwidth(struct aggregator *aggregator) | |||
678 | /** | 678 | /** |
679 | * __get_active_agg - get the current active aggregator | 679 | * __get_active_agg - get the current active aggregator |
680 | * @aggregator: the aggregator we're looking at | 680 | * @aggregator: the aggregator we're looking at |
681 | * | ||
682 | * Caller must hold RCU lock. | ||
681 | */ | 683 | */ |
682 | static struct aggregator *__get_active_agg(struct aggregator *aggregator) | 684 | static struct aggregator *__get_active_agg(struct aggregator *aggregator) |
683 | { | 685 | { |
@@ -685,13 +687,9 @@ static struct aggregator *__get_active_agg(struct aggregator *aggregator) | |||
685 | struct list_head *iter; | 687 | struct list_head *iter; |
686 | struct slave *slave; | 688 | struct slave *slave; |
687 | 689 | ||
688 | rcu_read_lock(); | ||
689 | bond_for_each_slave_rcu(bond, slave, iter) | 690 | bond_for_each_slave_rcu(bond, slave, iter) |
690 | if (SLAVE_AD_INFO(slave).aggregator.is_active) { | 691 | if (SLAVE_AD_INFO(slave).aggregator.is_active) |
691 | rcu_read_unlock(); | ||
692 | return &(SLAVE_AD_INFO(slave).aggregator); | 692 | return &(SLAVE_AD_INFO(slave).aggregator); |
693 | } | ||
694 | rcu_read_unlock(); | ||
695 | 693 | ||
696 | return NULL; | 694 | return NULL; |
697 | } | 695 | } |
@@ -1499,11 +1497,11 @@ static void ad_agg_selection_logic(struct aggregator *agg) | |||
1499 | struct slave *slave; | 1497 | struct slave *slave; |
1500 | struct port *port; | 1498 | struct port *port; |
1501 | 1499 | ||
1500 | rcu_read_lock(); | ||
1502 | origin = agg; | 1501 | origin = agg; |
1503 | active = __get_active_agg(agg); | 1502 | active = __get_active_agg(agg); |
1504 | best = (active && agg_device_up(active)) ? active : NULL; | 1503 | best = (active && agg_device_up(active)) ? active : NULL; |
1505 | 1504 | ||
1506 | rcu_read_lock(); | ||
1507 | bond_for_each_slave_rcu(bond, slave, iter) { | 1505 | bond_for_each_slave_rcu(bond, slave, iter) { |
1508 | agg = &(SLAVE_AD_INFO(slave).aggregator); | 1506 | agg = &(SLAVE_AD_INFO(slave).aggregator); |
1509 | 1507 | ||