rhashtable: Fix reader/rehash race
authorHerbert Xu <herbert@gondor.apana.org.au>
Thu, 12 Mar 2015 11:07:49 +0000 (22:07 +1100)
committerDavid S. Miller <davem@davemloft.net>
Fri, 13 Mar 2015 03:02:30 +0000 (23:02 -0400)
There is a potential race condition between readers and the rehasher.
In particular, the rehasher could have started a rehash while the
reader finishes a scan of the old table but fails to see the new
table pointer.

This patch closes this window by adding smp_wmb/smp_rmb.

Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: David S. Miller <davem@davemloft.net>
lib/rhashtable.c

index 6ffc793..68210cc 100644 (file)
@@ -271,6 +271,9 @@ static void rhashtable_rehash(struct rhashtable *ht,
         */
        rcu_assign_pointer(ht->future_tbl, new_tbl);
 
+       /* Ensure the new table is visible to readers. */
+       smp_wmb();
+
        for (old_hash = 0; old_hash < old_tbl->size; old_hash++)
                rhashtable_rehash_chain(ht, old_hash);
 
@@ -618,6 +621,9 @@ restart:
                return rht_obj(ht, he);
        }
 
+       /* Ensure we see any new tables. */
+       smp_rmb();
+
        old_tbl = tbl;
        tbl = rht_dereference_rcu(ht->future_tbl, ht);
        if (unlikely(tbl != old_tbl))