aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2015-02-03 15:33:25 -0500
committerDavid S. Miller <davem@davemloft.net>2015-02-04 23:34:53 -0500
commit9a7766288274ef765245ed65e6176a2727b96706 (patch)
tree2095e94d014d0c0a195b487086c336de86269f92
parent56d28b1e921b57b918a0ae6b13a1671115fe788d (diff)
netfilter: Use rhashtable walk iterator
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>
-rw-r--r--net/netfilter/nft_hash.c53
1 files changed, 36 insertions, 17 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c
index 75887d7d2c6a..61e6c407476a 100644
--- a/net/netfilter/nft_hash.c
+++ b/net/netfilter/nft_hash.c
@@ -130,31 +130,50 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set,
130 struct nft_set_iter *iter) 130 struct nft_set_iter *iter)
131{ 131{
132 struct rhashtable *priv = nft_set_priv(set); 132 struct rhashtable *priv = nft_set_priv(set);
133 const struct bucket_table *tbl;
134 const struct nft_hash_elem *he; 133 const struct nft_hash_elem *he;
134 struct rhashtable_iter hti;
135 struct nft_set_elem elem; 135 struct nft_set_elem elem;
136 unsigned int i; 136 int err;
137 137
138 tbl = rht_dereference_rcu(priv->tbl, priv); 138 err = rhashtable_walk_init(priv, &hti);
139 for (i = 0; i < tbl->size; i++) { 139 iter->err = err;
140 struct rhash_head *pos; 140 if (err)
141 return;
142
143 err = rhashtable_walk_start(&hti);
144 if (err && err != -EAGAIN) {
145 iter->err = err;
146 goto out;
147 }
141 148
142 rht_for_each_entry_rcu(he, pos, tbl, i, node) { 149 while ((he = rhashtable_walk_next(&hti))) {
143 if (iter->count < iter->skip) 150 if (IS_ERR(he)) {
144 goto cont; 151 err = PTR_ERR(he);
152 if (err != -EAGAIN) {
153 iter->err = err;
154 goto out;
155 }
156 }
157
158 if (iter->count < iter->skip)
159 goto cont;
160
161 memcpy(&elem.key, &he->key, sizeof(elem.key));
162 if (set->flags & NFT_SET_MAP)
163 memcpy(&elem.data, he->data, sizeof(elem.data));
164 elem.flags = 0;
145 165
146 memcpy(&elem.key, &he->key, sizeof(elem.key)); 166 iter->err = iter->fn(ctx, set, iter, &elem);
147 if (set->flags & NFT_SET_MAP) 167 if (iter->err < 0)
148 memcpy(&elem.data, he->data, sizeof(elem.data)); 168 goto out;
149 elem.flags = 0;
150 169
151 iter->err = iter->fn(ctx, set, iter, &elem);
152 if (iter->err < 0)
153 return;
154cont: 170cont:
155 iter->count++; 171 iter->count++;
156 }
157 } 172 }
173
174out:
175 rhashtable_walk_stop(&hti);
176 rhashtable_walk_exit(&hti);
158} 177}
159 178
160static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) 179static unsigned int nft_hash_privsize(const struct nlattr * const nla[])