aboutsummaryrefslogtreecommitdiffstats
path: root/net
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
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')
-rw-r--r--net/ipv4/netfilter/nf_conntrack_l3proto_ipv4_compat.c83
-rw-r--r--net/netfilter/nf_conntrack_expect.c85
2 files changed, 121 insertions, 47 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 */
210static void *exp_seq_start(struct seq_file *s, loff_t *pos) 210struct ct_expect_iter_state {
211 unsigned int bucket;
212};
213
214static 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)) 225static 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
230static void *exp_seq_next(struct seq_file *s, void *v, loff_t *pos) 239static 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) 249static 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; 255static 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
243static void exp_seq_stop(struct seq_file *s, void *v) 261static 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
248static int exp_seq_show(struct seq_file *s, void *v) 266static 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
277static int exp_open(struct inode *inode, struct file *file) 298static 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;
314out_free:
315 kfree(st);
316 return ret;
280} 317}
281 318
282static const struct file_operations ip_exp_file_ops = { 319static 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
290static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos) 327static void *ct_cpu_seq_start(struct seq_file *seq, loff_t *pos)
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