diff options
author | Patrick McHardy <kaber@trash.net> | 2007-07-08 01:34:07 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-07-11 01:18:00 -0400 |
commit | 5d08ad440feae11b8d6e7599147a8a20ac60f99a (patch) | |
tree | 41043588598c7dae1b1edecaac3764924f0cf3bf /net/ipv4 | |
parent | a71c085562bcc99e8b711cab4222bff1f6e955da (diff) |
[NETFILTER]: nf_conntrack_expect: convert proc functions to hash
Convert from the global expectation list to the hash table.
Signed-off-by: Patrick McHardy <kaber@trash.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4')
-rw-r--r-- | net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | 83 |
1 files changed, 60 insertions, 23 deletions
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c index 12d6a6327b63..ab8e4c607b7a 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c | |||
@@ -207,47 +207,68 @@ static const struct file_operations ct_file_ops = { | |||
207 | }; | 207 | }; |
208 | 208 | ||
209 | /* expects */ | 209 | /* expects */ |
210 | static void *exp_seq_start(struct seq_file *s, loff_t *pos) | 210 | struct ct_expect_iter_state { |
211 | unsigned int bucket; | ||
212 | }; | ||
213 | |||
214 | static struct hlist_node *ct_expect_get_first(struct seq_file *seq) | ||
211 | { | 215 | { |
212 | struct list_head *e = &nf_ct_expect_list; | 216 | struct ct_expect_iter_state *st = seq->private; |
213 | loff_t i; | ||
214 | 217 | ||
215 | /* strange seq_file api calls stop even if we fail, | 218 | for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) { |
216 | * thus we need to grab lock since stop unlocks */ | 219 | if (!hlist_empty(&nf_ct_expect_hash[st->bucket])) |
217 | read_lock_bh(&nf_conntrack_lock); | 220 | return nf_ct_expect_hash[st->bucket].first; |
221 | } | ||
222 | return NULL; | ||
223 | } | ||
218 | 224 | ||
219 | if (list_empty(e)) | 225 | static struct hlist_node *ct_expect_get_next(struct seq_file *seq, |
220 | return NULL; | 226 | struct hlist_node *head) |
227 | { | ||
228 | struct ct_expect_iter_state *st = seq->private; | ||
221 | 229 | ||
222 | for (i = 0; i <= *pos; i++) { | 230 | head = head->next; |
223 | e = e->next; | 231 | while (head == NULL) { |
224 | if (e == &nf_ct_expect_list) | 232 | if (++st->bucket >= nf_ct_expect_hsize) |
225 | return NULL; | 233 | return NULL; |
234 | head = nf_ct_expect_hash[st->bucket].first; | ||
226 | } | 235 | } |
227 | return e; | 236 | return head; |
228 | } | 237 | } |
229 | 238 | ||
230 | static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) | 239 | static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos) |
231 | { | 240 | { |
232 | struct list_head *e = v; | 241 | struct hlist_node *head = ct_expect_get_first(seq); |
233 | 242 | ||
234 | ++*pos; | 243 | if (head) |
235 | e = e->next; | 244 | while (pos && (head = ct_expect_get_next(seq, head))) |
245 | pos--; | ||
246 | return pos ? NULL : head; | ||
247 | } | ||
236 | 248 | ||
237 | if (e == &nf_ct_expect_list) | 249 | static void *exp_seq_start(struct seq_file *seq, loff_t *pos) |
238 | return NULL; | 250 | { |
251 | read_lock_bh(&nf_conntrack_lock); | ||
252 | return ct_expect_get_idx(seq, *pos); | ||
253 | } | ||
239 | 254 | ||
240 | return e; | 255 | static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
256 | { | ||
257 | (*pos)++; | ||
258 | return ct_expect_get_next(seq, v); | ||
241 | } | 259 | } |
242 | 260 | ||
243 | static void exp_seq_stop(struct seq_file *s, void *v) | 261 | static void exp_seq_stop(struct seq_file *seq, void *v) |
244 | { | 262 | { |
245 | read_unlock_bh(&nf_conntrack_lock); | 263 | read_unlock_bh(&nf_conntrack_lock); |
246 | } | 264 | } |
247 | 265 | ||
248 | static int exp_seq_show(struct seq_file *s, void *v) | 266 | static int exp_seq_show(struct seq_file *s, void *v) |
249 | { | 267 | { |
250 | struct nf_conntrack_expect *exp = v; | 268 | struct nf_conntrack_expect *exp; |
269 | struct hlist_node *n = v; | ||
270 | |||
271 | exp = hlist_entry(n, struct nf_conntrack_expect, hnode); | ||
251 | 272 | ||
252 | if (exp->tuple.src.l3num != AF_INET) | 273 | if (exp->tuple.src.l3num != AF_INET) |
253 | return 0; | 274 | return 0; |
@@ -276,7 +297,23 @@ static struct seq_operations exp_seq_ops = { | |||
276 | 297 | ||
277 | static int exp_open(struct inode *inode, struct file *file) | 298 | static int exp_open(struct inode *inode, struct file *file) |
278 | { | 299 | { |
279 | return seq_open(file, &exp_seq_ops); | 300 | struct seq_file *seq; |
301 | struct ct_expect_iter_state *st; | ||
302 | int ret; | ||
303 | |||
304 | st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL); | ||
305 | if (st == NULL) | ||
306 | return -ENOMEM; | ||
307 | ret = seq_open(file, &exp_seq_ops); | ||
308 | if (ret) | ||
309 | goto out_free; | ||
310 | seq = file->private_data; | ||
311 | seq->private = st; | ||
312 | memset(st, 0, sizeof(struct ct_expect_iter_state)); | ||
313 | return ret; | ||
314 | out_free: | ||
315 | kfree(st); | ||
316 | return ret; | ||
280 | } | 317 | } |
281 | 318 | ||
282 | static const struct file_operations ip_exp_file_ops = { | 319 | static const struct file_operations ip_exp_file_ops = { |
@@ -284,7 +321,7 @@ static const struct file_operations ip_exp_file_ops = { | |||
284 | .open = exp_open, | 321 | .open = exp_open, |
285 | .read = seq_read, | 322 | .read = seq_read, |
286 | .llseek = seq_lseek, | 323 | .llseek = seq_lseek, |
287 | .release = seq_release | 324 | .release = seq_release_private, |
288 | }; | 325 | }; |
289 | 326 | ||
290 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) | 327 | static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) |