netfilter: Use rhashtable walk iterator
authorHerbert Xu <herbert@gondor.apana.org.au>
Tue, 3 Feb 2015 20:33:25 +0000 (07:33 +1100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 5 Feb 2015 04:34:53 +0000 (20:34 -0800)
This patch gets rid of the manual rhashtable walk in nft_hash
which touches rhashtable internals that should not be exposed.
It does so by using the rhashtable iterator primitives.

Note that I'm leaving nft_hash_destroy alone since it's only
invoked on shutdown and it shouldn't be affected by changes
to rhashtable internals (or at least not what I'm planning to
change).

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

index 75887d7d2c6a756b7863aca289f2e0f31d81bfc4..61e6c407476a618df386c2f14839033398aae14b 100644 (file)
@@ -130,31 +130,50 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
                          struct nft_set_iter *iter)
 {
        struct rhashtable *priv = nft_set_priv(set);
-       const struct bucket_table *tbl;
        const struct nft_hash_elem *he;
+       struct rhashtable_iter hti;
        struct nft_set_elem elem;
-       unsigned int i;
+       int err;
 
-       tbl = rht_dereference_rcu(priv->tbl, priv);
-       for (i = 0; i < tbl->size; i++) {
-               struct rhash_head *pos;
+       err = rhashtable_walk_init(priv, &hti);
+       iter->err = err;
+       if (err)
+               return;
+
+       err = rhashtable_walk_start(&hti);
+       if (err && err != -EAGAIN) {
+               iter->err = err;
+               goto out;
+       }
 
-               rht_for_each_entry_rcu(he, pos, tbl, i, node) {
-                       if (iter->count < iter->skip)
-                               goto cont;
+       while ((he = rhashtable_walk_next(&hti))) {
+               if (IS_ERR(he)) {
+                       err = PTR_ERR(he);
+                       if (err != -EAGAIN) {
+                               iter->err = err;
+                               goto out;
+                       }
+               }
+
+               if (iter->count < iter->skip)
+                       goto cont;
+
+               memcpy(&elem.key, &he->key, sizeof(elem.key));
+               if (set->flags & NFT_SET_MAP)
+                       memcpy(&elem.data, he->data, sizeof(elem.data));
+               elem.flags = 0;
 
-                       memcpy(&elem.key, &he->key, sizeof(elem.key));
-                       if (set->flags & NFT_SET_MAP)
-                               memcpy(&elem.data, he->data, sizeof(elem.data));
-                       elem.flags = 0;
+               iter->err = iter->fn(ctx, set, iter, &elem);
+               if (iter->err < 0)
+                       goto out;
 
-                       iter->err = iter->fn(ctx, set, iter, &elem);
-                       if (iter->err < 0)
-                               return;
 cont:
-                       iter->count++;
-               }
+               iter->count++;
        }
+
+out:
+       rhashtable_walk_stop(&hti);
+       rhashtable_walk_exit(&hti);
 }
 
 static unsigned int nft_hash_privsize(const struct nlattr * const nla[])