diff options
| author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-02-03 15:33:25 -0500 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2015-02-04 23:34:53 -0500 |
| commit | 9a7766288274ef765245ed65e6176a2727b96706 (patch) | |
| tree | 2095e94d014d0c0a195b487086c336de86269f92 | |
| parent | 56d28b1e921b57b918a0ae6b13a1671115fe788d (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.c | 53 |
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; | ||
| 154 | cont: | 170 | cont: |
| 155 | iter->count++; | 171 | iter->count++; |
| 156 | } | ||
| 157 | } | 172 | } |
| 173 | |||
| 174 | out: | ||
| 175 | rhashtable_walk_stop(&hti); | ||
| 176 | rhashtable_walk_exit(&hti); | ||
| 158 | } | 177 | } |
| 159 | 178 | ||
| 160 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) | 179 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) |
