From: Jesse Gross Date: Mon, 6 Dec 2010 19:27:07 +0000 (-0800) Subject: datapath: RCU dereference correct pointer in table. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=eb0e14ed3f3a719b3cd5bef8cb3112e683e2a9dd;p=openvswitch 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 Acked-by: Ben Pfaff --- 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;