Commit f94161c1bbdf7af11729cf106b4452f2432448e0

Authored by Gao feng
Committed by Pablo Neira Ayuso
1 parent 8a454ab95e

netfilter: nf_conntrack: move initialization out of pernet operations

nf_conntrack initialization and cleanup codes happens in pernet
operations function. This task should be done in module_init/exit.
We can't use init_net to identify if it's the right time to initialize
or cleanup since we cannot make assumption on the order netns are
created/destroyed.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 3 changed files with 77 additions and 83 deletions Side-by-side Diff

include/net/netfilter/nf_conntrack_core.h
... ... @@ -25,12 +25,16 @@
25 25 unsigned int hooknum,
26 26 struct sk_buff *skb);
27 27  
28   -extern int nf_conntrack_init(struct net *net);
29   -extern void nf_conntrack_cleanup(struct net *net);
  28 +extern int nf_conntrack_init_net(struct net *net);
  29 +extern void nf_conntrack_cleanup_net(struct net *net);
30 30  
31 31 extern int nf_conntrack_proto_init(struct net *net);
32 32 extern void nf_conntrack_proto_fini(struct net *net);
33 33  
  34 +extern int nf_conntrack_init_start(void);
  35 +extern void nf_conntrack_cleanup_start(void);
  36 +
  37 +extern void nf_conntrack_init_end(void);
34 38 extern void nf_conntrack_cleanup_end(void);
35 39  
36 40 extern bool
net/netfilter/nf_conntrack_core.c
... ... @@ -1334,8 +1334,14 @@
1334 1334 return cnt;
1335 1335 }
1336 1336  
1337   -static void nf_conntrack_cleanup_init_net(void)
  1337 +void nf_conntrack_cleanup_start(void)
1338 1338 {
  1339 + RCU_INIT_POINTER(ip_ct_attach, NULL);
  1340 +}
  1341 +
  1342 +void nf_conntrack_cleanup_end(void)
  1343 +{
  1344 + RCU_INIT_POINTER(nf_ct_destroy, NULL);
1339 1345 while (untrack_refs() > 0)
1340 1346 schedule();
1341 1347  
1342 1348  
... ... @@ -1344,8 +1350,18 @@
1344 1350 #endif
1345 1351 }
1346 1352  
1347   -static void nf_conntrack_cleanup_net(struct net *net)
  1353 +/*
  1354 + * Mishearing the voices in his head, our hero wonders how he's
  1355 + * supposed to kill the mall.
  1356 + */
  1357 +void nf_conntrack_cleanup_net(struct net *net)
1348 1358 {
  1359 + /*
  1360 + * This makes sure all current packets have passed through
  1361 + * netfilter framework. Roll on, two-stage module
  1362 + * delete...
  1363 + */
  1364 + synchronize_net();
1349 1365 i_see_dead_people:
1350 1366 nf_ct_iterate_cleanup(net, kill_all, NULL);
1351 1367 nf_ct_release_dying_list(net);
... ... @@ -1355,6 +1371,7 @@
1355 1371 }
1356 1372  
1357 1373 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
  1374 + nf_conntrack_proto_fini(net);
1358 1375 nf_conntrack_labels_fini(net);
1359 1376 nf_conntrack_helper_fini(net);
1360 1377 nf_conntrack_timeout_fini(net);
... ... @@ -1367,27 +1384,6 @@
1367 1384 free_percpu(net->ct.stat);
1368 1385 }
1369 1386  
1370   -/* Mishearing the voices in his head, our hero wonders how he's
1371   - supposed to kill the mall. */
1372   -void nf_conntrack_cleanup(struct net *net)
1373   -{
1374   - if (net_eq(net, &init_net))
1375   - RCU_INIT_POINTER(ip_ct_attach, NULL);
1376   -
1377   - /* This makes sure all current packets have passed through
1378   - netfilter framework. Roll on, two-stage module
1379   - delete... */
1380   - synchronize_net();
1381   - nf_conntrack_proto_fini(net);
1382   - nf_conntrack_cleanup_net(net);
1383   -}
1384   -
1385   -void nf_conntrack_cleanup_end(void)
1386   -{
1387   - RCU_INIT_POINTER(nf_ct_destroy, NULL);
1388   - nf_conntrack_cleanup_init_net();
1389   -}
1390   -
1391 1387 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
1392 1388 {
1393 1389 struct hlist_nulls_head *hash;
... ... @@ -1478,7 +1474,7 @@
1478 1474 }
1479 1475 EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or);
1480 1476  
1481   -static int nf_conntrack_init_init_net(void)
  1477 +int nf_conntrack_init_start(void)
1482 1478 {
1483 1479 int max_factor = 8;
1484 1480 int ret, cpu;
... ... @@ -1526,6 +1522,16 @@
1526 1522 return ret;
1527 1523 }
1528 1524  
  1525 +void nf_conntrack_init_end(void)
  1526 +{
  1527 + /* For use by REJECT target */
  1528 + RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
  1529 + RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
  1530 +
  1531 + /* Howto get NAT offsets */
  1532 + RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
  1533 +}
  1534 +
1529 1535 /*
1530 1536 * We need to use special "null" values, not used in hash table
1531 1537 */
... ... @@ -1533,7 +1539,7 @@
1533 1539 #define DYING_NULLS_VAL ((1<<30)+1)
1534 1540 #define TEMPLATE_NULLS_VAL ((1<<30)+2)
1535 1541  
1536   -static int nf_conntrack_init_net(struct net *net)
  1542 +int nf_conntrack_init_net(struct net *net)
1537 1543 {
1538 1544 int ret;
1539 1545  
1540 1546  
... ... @@ -1592,8 +1598,13 @@
1592 1598 if (ret < 0)
1593 1599 goto err_labels;
1594 1600  
  1601 + ret = nf_conntrack_proto_init(net);
  1602 + if (ret < 0)
  1603 + goto err_proto;
1595 1604 return 0;
1596 1605  
  1606 +err_proto:
  1607 + nf_conntrack_labels_fini(net);
1597 1608 err_labels:
1598 1609 nf_conntrack_helper_fini(net);
1599 1610 err_helper:
... ... @@ -1622,39 +1633,4 @@
1622 1633 enum ip_conntrack_dir dir,
1623 1634 u32 seq);
1624 1635 EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
1625   -
1626   -int nf_conntrack_init(struct net *net)
1627   -{
1628   - int ret;
1629   -
1630   - if (net_eq(net, &init_net)) {
1631   - ret = nf_conntrack_init_init_net();
1632   - if (ret < 0)
1633   - goto out_init_net;
1634   - }
1635   - ret = nf_conntrack_proto_init(net);
1636   - if (ret < 0)
1637   - goto out_proto;
1638   - ret = nf_conntrack_init_net(net);
1639   - if (ret < 0)
1640   - goto out_net;
1641   -
1642   - if (net_eq(net, &init_net)) {
1643   - /* For use by REJECT target */
1644   - RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
1645   - RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
1646   -
1647   - /* Howto get NAT offsets */
1648   - RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
1649   - }
1650   - return 0;
1651   -
1652   -out_net:
1653   - nf_conntrack_proto_fini(net);
1654   -out_proto:
1655   - if (net_eq(net, &init_net))
1656   - nf_conntrack_cleanup_init_net();
1657   -out_init_net:
1658   - return ret;
1659   -}
net/netfilter/nf_conntrack_standalone.c
... ... @@ -472,13 +472,6 @@
472 472 {
473 473 struct ctl_table *table;
474 474  
475   - if (net_eq(net, &init_net)) {
476   - nf_ct_netfilter_header =
477   - register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
478   - if (!nf_ct_netfilter_header)
479   - goto out;
480   - }
481   -
482 475 table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
483 476 GFP_KERNEL);
484 477 if (!table)
... ... @@ -502,10 +495,6 @@
502 495 out_unregister_netfilter:
503 496 kfree(table);
504 497 out_kmemdup:
505   - if (net_eq(net, &init_net))
506   - unregister_net_sysctl_table(nf_ct_netfilter_header);
507   -out:
508   - printk(KERN_ERR "nf_conntrack: can't register to sysctl.\n");
509 498 return -ENOMEM;
510 499 }
511 500  
... ... @@ -513,8 +502,6 @@
513 502 {
514 503 struct ctl_table *table;
515 504  
516   - if (net_eq(net, &init_net))
517   - unregister_net_sysctl_table(nf_ct_netfilter_header);
518 505 table = net->ct.sysctl_header->ctl_table_arg;
519 506 unregister_net_sysctl_table(net->ct.sysctl_header);
520 507 kfree(table);
521 508  
522 509  
523 510  
524 511  
525 512  
526 513  
527 514  
528 515  
529 516  
530 517  
531 518  
... ... @@ -530,51 +517,78 @@
530 517 }
531 518 #endif /* CONFIG_SYSCTL */
532 519  
533   -static int nf_conntrack_net_init(struct net *net)
  520 +static int nf_conntrack_pernet_init(struct net *net)
534 521 {
535 522 int ret;
536 523  
537   - ret = nf_conntrack_init(net);
  524 + ret = nf_conntrack_init_net(net);
538 525 if (ret < 0)
539 526 goto out_init;
  527 +
540 528 ret = nf_conntrack_standalone_init_proc(net);
541 529 if (ret < 0)
542 530 goto out_proc;
  531 +
543 532 net->ct.sysctl_checksum = 1;
544 533 net->ct.sysctl_log_invalid = 0;
545 534 ret = nf_conntrack_standalone_init_sysctl(net);
546 535 if (ret < 0)
547 536 goto out_sysctl;
  537 +
548 538 return 0;
549 539  
550 540 out_sysctl:
551 541 nf_conntrack_standalone_fini_proc(net);
552 542 out_proc:
553   - nf_conntrack_cleanup(net);
  543 + nf_conntrack_cleanup_net(net);
554 544 out_init:
555 545 return ret;
556 546 }
557 547  
558   -static void nf_conntrack_net_exit(struct net *net)
  548 +static void nf_conntrack_pernet_exit(struct net *net)
559 549 {
560 550 nf_conntrack_standalone_fini_sysctl(net);
561 551 nf_conntrack_standalone_fini_proc(net);
562   - nf_conntrack_cleanup(net);
  552 + nf_conntrack_cleanup_net(net);
563 553 }
564 554  
565 555 static struct pernet_operations nf_conntrack_net_ops = {
566   - .init = nf_conntrack_net_init,
567   - .exit = nf_conntrack_net_exit,
  556 + .init = nf_conntrack_pernet_init,
  557 + .exit = nf_conntrack_pernet_exit,
568 558 };
569 559  
570 560 static int __init nf_conntrack_standalone_init(void)
571 561 {
572   - return register_pernet_subsys(&nf_conntrack_net_ops);
  562 + int ret = nf_conntrack_init_start();
  563 + if (ret < 0)
  564 + goto out_start;
  565 +
  566 + nf_ct_netfilter_header =
  567 + register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
  568 + if (!nf_ct_netfilter_header)
  569 + goto out_sysctl;
  570 +
  571 + ret = register_pernet_subsys(&nf_conntrack_net_ops);
  572 + if (ret < 0)
  573 + goto out_pernet;
  574 +
  575 + nf_conntrack_init_end();
  576 + return 0;
  577 +
  578 +out_pernet:
  579 + unregister_net_sysctl_table(nf_ct_netfilter_header);
  580 +out_sysctl:
  581 + pr_err("nf_conntrack: can't register to sysctl.\n");
  582 + nf_conntrack_cleanup_end();
  583 +out_start:
  584 + return ret;
573 585 }
574 586  
575 587 static void __exit nf_conntrack_standalone_fini(void)
576 588 {
  589 + nf_conntrack_cleanup_start();
577 590 unregister_pernet_subsys(&nf_conntrack_net_ops);
  591 + unregister_net_sysctl_table(nf_ct_netfilter_header);
578 592 nf_conntrack_cleanup_end();
579 593 }
580 594