diff options
author | Herbert Xu <herbert@gondor.apana.org.au> | 2015-03-20 06:57:02 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2015-03-20 16:16:24 -0400 |
commit | fa3773211eb61f2a08ffc399a98af53594ba1509 (patch) | |
tree | 091bc12c3e98e72cd7c6284eac1beeffe0dae9d4 | |
parent | c428ecd1a21f1457ca3beb4df71b8a079c410e41 (diff) |
netfilter: Convert nft_hash to inlined rhashtable
This patch converts nft_hash to the inlined rhashtable interface.
This patch also replaces the call to rhashtable_lookup_compare with
a straight rhashtable_lookup_fast because it's simply doing a memcmp
(in fact nft_hash_lookup already uses memcmp instead of nft_data_cmp).
Furthermore, the compare function is only meant to compare, it is not
supposed to have side-effects. The current side-effect code can
simply be moved into the nft_hash_get.
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 | 70 |
1 files changed, 29 insertions, 41 deletions
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index c82df0a48fcd..4585c5724391 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -29,6 +29,8 @@ struct nft_hash_elem { | |||
29 | struct nft_data data[]; | 29 | struct nft_data data[]; |
30 | }; | 30 | }; |
31 | 31 | ||
32 | static const struct rhashtable_params nft_hash_params; | ||
33 | |||
32 | static bool nft_hash_lookup(const struct nft_set *set, | 34 | static bool nft_hash_lookup(const struct nft_set *set, |
33 | const struct nft_data *key, | 35 | const struct nft_data *key, |
34 | struct nft_data *data) | 36 | struct nft_data *data) |
@@ -36,7 +38,7 @@ static bool nft_hash_lookup(const struct nft_set *set, | |||
36 | struct rhashtable *priv = nft_set_priv(set); | 38 | struct rhashtable *priv = nft_set_priv(set); |
37 | const struct nft_hash_elem *he; | 39 | const struct nft_hash_elem *he; |
38 | 40 | ||
39 | he = rhashtable_lookup(priv, key); | 41 | he = rhashtable_lookup_fast(priv, key, nft_hash_params); |
40 | if (he && set->flags & NFT_SET_MAP) | 42 | if (he && set->flags & NFT_SET_MAP) |
41 | nft_data_copy(data, he->data); | 43 | nft_data_copy(data, he->data); |
42 | 44 | ||
@@ -49,6 +51,7 @@ static int nft_hash_insert(const struct nft_set *set, | |||
49 | struct rhashtable *priv = nft_set_priv(set); | 51 | struct rhashtable *priv = nft_set_priv(set); |
50 | struct nft_hash_elem *he; | 52 | struct nft_hash_elem *he; |
51 | unsigned int size; | 53 | unsigned int size; |
54 | int err; | ||
52 | 55 | ||
53 | if (elem->flags != 0) | 56 | if (elem->flags != 0) |
54 | return -EINVAL; | 57 | return -EINVAL; |
@@ -65,9 +68,11 @@ static int nft_hash_insert(const struct nft_set *set, | |||
65 | if (set->flags & NFT_SET_MAP) | 68 | if (set->flags & NFT_SET_MAP) |
66 | nft_data_copy(he->data, &elem->data); | 69 | nft_data_copy(he->data, &elem->data); |
67 | 70 | ||
68 | rhashtable_insert(priv, &he->node); | 71 | err = rhashtable_insert_fast(priv, &he->node, nft_hash_params); |
72 | if (err) | ||
73 | kfree(he); | ||
69 | 74 | ||
70 | return 0; | 75 | return err; |
71 | } | 76 | } |
72 | 77 | ||
73 | static void nft_hash_elem_destroy(const struct nft_set *set, | 78 | static void nft_hash_elem_destroy(const struct nft_set *set, |
@@ -84,46 +89,26 @@ static void nft_hash_remove(const struct nft_set *set, | |||
84 | { | 89 | { |
85 | struct rhashtable *priv = nft_set_priv(set); | 90 | struct rhashtable *priv = nft_set_priv(set); |
86 | 91 | ||
87 | rhashtable_remove(priv, elem->cookie); | 92 | rhashtable_remove_fast(priv, elem->cookie, nft_hash_params); |
88 | synchronize_rcu(); | 93 | synchronize_rcu(); |
89 | kfree(elem->cookie); | 94 | kfree(elem->cookie); |
90 | } | 95 | } |
91 | 96 | ||
92 | struct nft_compare_arg { | ||
93 | const struct nft_set *set; | ||
94 | struct nft_set_elem *elem; | ||
95 | }; | ||
96 | |||
97 | static bool nft_hash_compare(void *ptr, void *arg) | ||
98 | { | ||
99 | struct nft_hash_elem *he = ptr; | ||
100 | struct nft_compare_arg *x = arg; | ||
101 | |||
102 | if (!nft_data_cmp(&he->key, &x->elem->key, x->set->klen)) { | ||
103 | x->elem->cookie = he; | ||
104 | x->elem->flags = 0; | ||
105 | if (x->set->flags & NFT_SET_MAP) | ||
106 | nft_data_copy(&x->elem->data, he->data); | ||
107 | |||
108 | return true; | ||
109 | } | ||
110 | |||
111 | return false; | ||
112 | } | ||
113 | |||
114 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | 97 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) |
115 | { | 98 | { |
116 | struct rhashtable *priv = nft_set_priv(set); | 99 | struct rhashtable *priv = nft_set_priv(set); |
117 | struct nft_compare_arg arg = { | 100 | struct nft_hash_elem *he; |
118 | .set = set, | 101 | |
119 | .elem = elem, | 102 | he = rhashtable_lookup_fast(priv, &elem->key, nft_hash_params); |
120 | }; | 103 | if (!he) |
104 | return -ENOENT; | ||
121 | 105 | ||
122 | if (rhashtable_lookup_compare(priv, &elem->key, | 106 | elem->cookie = he; |
123 | &nft_hash_compare, &arg)) | 107 | elem->flags = 0; |
124 | return 0; | 108 | if (set->flags & NFT_SET_MAP) |
109 | nft_data_copy(&elem->data, he->data); | ||
125 | 110 | ||
126 | return -ENOENT; | 111 | return 0; |
127 | } | 112 | } |
128 | 113 | ||
129 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | 114 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, |
@@ -181,18 +166,21 @@ static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) | |||
181 | return sizeof(struct rhashtable); | 166 | return sizeof(struct rhashtable); |
182 | } | 167 | } |
183 | 168 | ||
169 | static const struct rhashtable_params nft_hash_params = { | ||
170 | .head_offset = offsetof(struct nft_hash_elem, node), | ||
171 | .key_offset = offsetof(struct nft_hash_elem, key), | ||
172 | .hashfn = jhash, | ||
173 | }; | ||
174 | |||
184 | static int nft_hash_init(const struct nft_set *set, | 175 | static int nft_hash_init(const struct nft_set *set, |
185 | const struct nft_set_desc *desc, | 176 | const struct nft_set_desc *desc, |
186 | const struct nlattr * const tb[]) | 177 | const struct nlattr * const tb[]) |
187 | { | 178 | { |
188 | struct rhashtable *priv = nft_set_priv(set); | 179 | struct rhashtable *priv = nft_set_priv(set); |
189 | struct rhashtable_params params = { | 180 | struct rhashtable_params params = nft_hash_params; |
190 | .nelem_hint = desc->size ? : NFT_HASH_ELEMENT_HINT, | 181 | |
191 | .head_offset = offsetof(struct nft_hash_elem, node), | 182 | params.nelem_hint = desc->size ?: NFT_HASH_ELEMENT_HINT; |
192 | .key_offset = offsetof(struct nft_hash_elem, key), | 183 | params.key_len = set->klen; |
193 | .key_len = set->klen, | ||
194 | .hashfn = jhash, | ||
195 | }; | ||
196 | 184 | ||
197 | return rhashtable_init(priv, ¶ms); | 185 | return rhashtable_init(priv, ¶ms); |
198 | } | 186 | } |