aboutsummaryrefslogtreecommitdiff
path: root/datapath/table.c
diff options
context:
space:
mode:
authorJesse Gross <jesse@nicira.com>2010-12-06 11:27:07 -0800
committerJesse Gross <jesse@nicira.com>2010-12-09 17:43:37 -0800
commiteb0e14ed3f3a719b3cd5bef8cb3112e683e2a9dd (patch)
tree9bcd4ecbf7080bcf70b7768be13d56afe285adcf /datapath/table.c
parent79863c64f9085114759fb1125e35f377301441fb (diff)
datapath: RCU dereference correct pointer in table.
Our hash table implementation consists of two levels of buckets and then arrays of pointers. The bucket arrays are fixed by the size of the table, which is therefore protected by the RCU dereference of the table pointer. The arrays change when items are inserted or deleted. However, in tbl_insert/remove we need to look at the old values and we do an rcu_dereference() on the second level array instead of the bucket itself. Other places that access the table for lookup do the pointer dereference in the correct order. Found by sparse. Signed-off-by: Jesse Gross <jesse@nicira.com> Acked-by: Ben Pfaff <blp@nicira.com>
Diffstat (limited to 'datapath/table.c')
-rw-r--r--datapath/table.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/datapath/table.c b/datapath/table.c
index cfe7b2b9..c6614e13 100644
--- a/datapath/table.c
+++ b/datapath/table.c
@@ -319,7 +319,7 @@ static void free_bucket_rcu(struct rcu_head *rcu)
int tbl_insert(struct tbl *table, struct tbl_node *target, u32 hash)
{
struct tbl_bucket **oldp = find_bucket(table, hash);
- struct tbl_bucket *old = *rcu_dereference(oldp);
+ struct tbl_bucket *old = rcu_dereference(*oldp);
unsigned int n = old ? old->n_objs : 0;
struct tbl_bucket *new = bucket_alloc(n + 1);
@@ -357,7 +357,7 @@ int tbl_insert(struct tbl *table, struct tbl_node *target, u32 hash)
int tbl_remove(struct tbl *table, struct tbl_node *target)
{
struct tbl_bucket **oldp = find_bucket(table, target->hash);
- struct tbl_bucket *old = *rcu_dereference(oldp);
+ struct tbl_bucket *old = rcu_dereference(*oldp);
unsigned int n = old->n_objs;
struct tbl_bucket *new;