datapath: RCU dereference correct pointer in table.
authorJesse Gross <jesse@nicira.com>
Mon, 6 Dec 2010 19:27:07 +0000 (11:27 -0800)
committerJesse Gross <jesse@nicira.com>
Fri, 10 Dec 2010 01:43:37 +0000 (17:43 -0800)
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>
datapath/table.c

index cfe7b2b95976fb65de054b5ce9d1f1759935db8b..c6614e13e5c23a3872f7f531115736e5b62c27e3 100644 (file)
@@ -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;