aboutsummaryrefslogtreecommitdiffstats
path: root/net/netfilter
diff options
context:
space:
mode:
authorPatrick McHardy <kaber@trash.net>2007-07-08 01:34:07 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-11 01:18:00 -0400
commit5d08ad440feae11b8d6e7599147a8a20ac60f99a (patch)
tree41043588598c7dae1b1edecaac3764924f0cf3bf /net/netfilter
parenta71c085562bcc99e8b711cab4222bff1f6e955da (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/netfilter')
-rw-r--r--net/netfilter/nf_conntrack_expect.c85
1 files changed, 61 insertions, 24 deletions
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 0696f87aaef1..c5006b0a4e65 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -377,47 +377,68 @@ out:
377EXPORT_SYMBOL_GPL(nf_ct_expect_related); 377EXPORT_SYMBOL_GPL(nf_ct_expect_related);
378 378
379#ifdef CONFIG_PROC_FS 379#ifdef CONFIG_PROC_FS
380static void *exp_seq_start(struct seq_file *s, loff_t *pos) 380struct ct_expect_iter_state {
381 unsigned int bucket;
382};
383
384static struct hlist_node *ct_expect_get_first(struct seq_file *seq)
381{ 385{
382 struct list_head *e = &nf_ct_expect_list; 386 struct ct_expect_iter_state *st = seq->private;
383 loff_t i;
384 387
385 /* strange seq_file api calls stop even if we fail, 388 for (st->bucket = 0; st->bucket < nf_ct_expect_hsize; st->bucket++) {
386 * thus we need to grab lock since stop unlocks */ 389 if (!hlist_empty(&nf_ct_expect_hash[st->bucket]))
387 read_lock_bh(&nf_conntrack_lock); 390 return nf_ct_expect_hash[st->bucket].first;
391 }
392 return NULL;
393}
388 394
389 if (list_empty(e)) 395static struct hlist_node *ct_expect_get_next(struct seq_file *seq,
390 return NULL; 396 struct hlist_node *head)
397{
398 struct ct_expect_iter_state *st = seq->private;
391 399
392 for (i = 0; i <= *pos; i++) { 400 head = head->next;
393 e = e->next; 401 while (head == NULL) {
394 if (e == &nf_ct_expect_list) 402 if (++st->bucket >= nf_ct_expect_hsize)
395 return NULL; 403 return NULL;
404 head = nf_ct_expect_hash[st->bucket].first;
396 } 405 }
397 return e; 406 return head;
398} 407}
399 408
400static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) 409static struct hlist_node *ct_expect_get_idx(struct seq_file *seq, loff_t pos)
401{ 410{
402 struct list_head *e = v; 411 struct hlist_node *head = ct_expect_get_first(seq);
403 412
404 ++*pos; 413 if (head)
405 e = e->next; 414 while (pos && (head = ct_expect_get_next(seq, head)))
415 pos--;
416 return pos ? NULL : head;
417}
406 418
407 if (e == &nf_ct_expect_list) 419static void *exp_seq_start(struct seq_file *seq, loff_t *pos)
408 return NULL; 420{
421 read_lock_bh(&nf_conntrack_lock);
422 return ct_expect_get_idx(seq, *pos);
423}
409 424
410 return e; 425static void *exp_seq_next(struct seq_file *seq, void *v, loff_t *pos)
426{
427 (*pos)++;
428 return ct_expect_get_next(seq, v);
411} 429}
412 430
413static void exp_seq_stop(struct seq_file *s, void *v) 431static void exp_seq_stop(struct seq_file *seq, void *v)
414{ 432{
415 read_unlock_bh(&nf_conntrack_lock); 433 read_unlock_bh(&nf_conntrack_lock);
416} 434}
417 435
418static int exp_seq_show(struct seq_file *s, void *v) 436static int exp_seq_show(struct seq_file *s, void *v)
419{ 437{
420 struct nf_conntrack_expect *expect = v; 438 struct nf_conntrack_expect *expect;
439 struct hlist_node *n = v;
440
441 expect = hlist_entry(n, struct nf_conntrack_expect, hnode);
421 442
422 if (expect->timeout.function) 443 if (expect->timeout.function)
423 seq_printf(s, "%ld ", timer_pending(&expect->timeout) 444 seq_printf(s, "%ld ", timer_pending(&expect->timeout)
@@ -443,15 +464,31 @@ static struct seq_operations exp_seq_ops = {
443 464
444static int exp_open(struct inode *inode, struct file *file) 465static int exp_open(struct inode *inode, struct file *file)
445{ 466{
446 return seq_open(file, &exp_seq_ops); 467 struct seq_file *seq;
468 struct ct_expect_iter_state *st;
469 int ret;
470
471 st = kmalloc(sizeof(struct ct_expect_iter_state), GFP_KERNEL);
472 if (st == NULL)
473 return -ENOMEM;
474 ret = seq_open(file, &exp_seq_ops);
475 if (ret)
476 goto out_free;
477 seq = file->private_data;
478 seq->private = st;
479 memset(st, 0, sizeof(struct ct_expect_iter_state));
480 return ret;
481out_free:
482 kfree(st);
483 return ret;
447} 484}
448 485
449const struct file_operations exp_file_ops = { 486static const struct file_operations exp_file_ops = {
450 .owner = THIS_MODULE, 487 .owner = THIS_MODULE,
451 .open = exp_open, 488 .open = exp_open,
452 .read = seq_read, 489 .read = seq_read,
453 .llseek = seq_lseek, 490 .llseek = seq_lseek,
454 .release = seq_release 491 .release = seq_release_private,
455}; 492};
456#endif /* CONFIG_PROC_FS */ 493#endif /* CONFIG_PROC_FS */
457 494