return cnt;
 }
 
-static void nf_conntrack_cleanup_init_net(void)
+void nf_conntrack_cleanup_start(void)
 {
+       RCU_INIT_POINTER(ip_ct_attach, NULL);
+}
+
+void nf_conntrack_cleanup_end(void)
+{
+       RCU_INIT_POINTER(nf_ct_destroy, NULL);
        while (untrack_refs() > 0)
                schedule();
 
 #endif
 }
 
-static void nf_conntrack_cleanup_net(struct net *net)
+/*
+ * Mishearing the voices in his head, our hero wonders how he's
+ * supposed to kill the mall.
+ */
+void nf_conntrack_cleanup_net(struct net *net)
 {
+       /*
+        * This makes sure all current packets have passed through
+        *  netfilter framework.  Roll on, two-stage module
+        *  delete...
+        */
+       synchronize_net();
  i_see_dead_people:
        nf_ct_iterate_cleanup(net, kill_all, NULL);
        nf_ct_release_dying_list(net);
        }
 
        nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
+       nf_conntrack_proto_fini(net);
        nf_conntrack_labels_fini(net);
        nf_conntrack_helper_fini(net);
        nf_conntrack_timeout_fini(net);
        free_percpu(net->ct.stat);
 }
 
-/* Mishearing the voices in his head, our hero wonders how he's
-   supposed to kill the mall. */
-void nf_conntrack_cleanup(struct net *net)
-{
-       if (net_eq(net, &init_net))
-               RCU_INIT_POINTER(ip_ct_attach, NULL);
-
-       /* This makes sure all current packets have passed through
-          netfilter framework.  Roll on, two-stage module
-          delete... */
-       synchronize_net();
-       nf_conntrack_proto_fini(net);
-       nf_conntrack_cleanup_net(net);
-}
-
-void nf_conntrack_cleanup_end(void)
-{
-       RCU_INIT_POINTER(nf_ct_destroy, NULL);
-       nf_conntrack_cleanup_init_net();
-}
-
 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
 {
        struct hlist_nulls_head *hash;
 }
 EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or);
 
-static int nf_conntrack_init_init_net(void)
+int nf_conntrack_init_start(void)
 {
        int max_factor = 8;
        int ret, cpu;
        return ret;
 }
 
+void nf_conntrack_init_end(void)
+{
+       /* For use by REJECT target */
+       RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
+       RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
+
+       /* Howto get NAT offsets */
+       RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
+}
+
 /*
  * We need to use special "null" values, not used in hash table
  */
 #define DYING_NULLS_VAL                ((1<<30)+1)
 #define TEMPLATE_NULLS_VAL     ((1<<30)+2)
 
-static int nf_conntrack_init_net(struct net *net)
+int nf_conntrack_init_net(struct net *net)
 {
        int ret;
 
        if (ret < 0)
                goto err_labels;
 
+       ret = nf_conntrack_proto_init(net);
+       if (ret < 0)
+               goto err_proto;
        return 0;
 
+err_proto:
+       nf_conntrack_labels_fini(net);
 err_labels:
        nf_conntrack_helper_fini(net);
 err_helper:
                        enum ip_conntrack_dir dir,
                        u32 seq);
 EXPORT_SYMBOL_GPL(nf_ct_nat_offset);
-
-int nf_conntrack_init(struct net *net)
-{
-       int ret;
-
-       if (net_eq(net, &init_net)) {
-               ret = nf_conntrack_init_init_net();
-               if (ret < 0)
-                       goto out_init_net;
-       }
-       ret = nf_conntrack_proto_init(net);
-       if (ret < 0)
-               goto out_proto;
-       ret = nf_conntrack_init_net(net);
-       if (ret < 0)
-               goto out_net;
-
-       if (net_eq(net, &init_net)) {
-               /* For use by REJECT target */
-               RCU_INIT_POINTER(ip_ct_attach, nf_conntrack_attach);
-               RCU_INIT_POINTER(nf_ct_destroy, destroy_conntrack);
-
-               /* Howto get NAT offsets */
-               RCU_INIT_POINTER(nf_ct_nat_offset, NULL);
-       }
-       return 0;
-
-out_net:
-       nf_conntrack_proto_fini(net);
-out_proto:
-       if (net_eq(net, &init_net))
-               nf_conntrack_cleanup_init_net();
-out_init_net:
-       return ret;
-}
 
 {
        struct ctl_table *table;
 
-       if (net_eq(net, &init_net)) {
-               nf_ct_netfilter_header =
-                      register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
-               if (!nf_ct_netfilter_header)
-                       goto out;
-       }
-
        table = kmemdup(nf_ct_sysctl_table, sizeof(nf_ct_sysctl_table),
                        GFP_KERNEL);
        if (!table)
 out_unregister_netfilter:
        kfree(table);
 out_kmemdup:
-       if (net_eq(net, &init_net))
-               unregister_net_sysctl_table(nf_ct_netfilter_header);
-out:
-       printk(KERN_ERR "nf_conntrack: can't register to sysctl.\n");
        return -ENOMEM;
 }
 
 {
        struct ctl_table *table;
 
-       if (net_eq(net, &init_net))
-               unregister_net_sysctl_table(nf_ct_netfilter_header);
        table = net->ct.sysctl_header->ctl_table_arg;
        unregister_net_sysctl_table(net->ct.sysctl_header);
        kfree(table);
 }
 #endif /* CONFIG_SYSCTL */
 
-static int nf_conntrack_net_init(struct net *net)
+static int nf_conntrack_pernet_init(struct net *net)
 {
        int ret;
 
-       ret = nf_conntrack_init(net);
+       ret = nf_conntrack_init_net(net);
        if (ret < 0)
                goto out_init;
+
        ret = nf_conntrack_standalone_init_proc(net);
        if (ret < 0)
                goto out_proc;
+
        net->ct.sysctl_checksum = 1;
        net->ct.sysctl_log_invalid = 0;
        ret = nf_conntrack_standalone_init_sysctl(net);
        if (ret < 0)
                goto out_sysctl;
+
        return 0;
 
 out_sysctl:
        nf_conntrack_standalone_fini_proc(net);
 out_proc:
-       nf_conntrack_cleanup(net);
+       nf_conntrack_cleanup_net(net);
 out_init:
        return ret;
 }
 
-static void nf_conntrack_net_exit(struct net *net)
+static void nf_conntrack_pernet_exit(struct net *net)
 {
        nf_conntrack_standalone_fini_sysctl(net);
        nf_conntrack_standalone_fini_proc(net);
-       nf_conntrack_cleanup(net);
+       nf_conntrack_cleanup_net(net);
 }
 
 static struct pernet_operations nf_conntrack_net_ops = {
-       .init = nf_conntrack_net_init,
-       .exit = nf_conntrack_net_exit,
+       .init = nf_conntrack_pernet_init,
+       .exit = nf_conntrack_pernet_exit,
 };
 
 static int __init nf_conntrack_standalone_init(void)
 {
-       return register_pernet_subsys(&nf_conntrack_net_ops);
+       int ret = nf_conntrack_init_start();
+       if (ret < 0)
+               goto out_start;
+
+       nf_ct_netfilter_header =
+               register_net_sysctl(&init_net, "net", nf_ct_netfilter_table);
+       if (!nf_ct_netfilter_header)
+               goto out_sysctl;
+
+       ret = register_pernet_subsys(&nf_conntrack_net_ops);
+       if (ret < 0)
+               goto out_pernet;
+
+       nf_conntrack_init_end();
+       return 0;
+
+out_pernet:
+       unregister_net_sysctl_table(nf_ct_netfilter_header);
+out_sysctl:
+       pr_err("nf_conntrack: can't register to sysctl.\n");
+       nf_conntrack_cleanup_end();
+out_start:
+       return ret;
 }
 
 static void __exit nf_conntrack_standalone_fini(void)
 {
+       nf_conntrack_cleanup_start();
        unregister_pernet_subsys(&nf_conntrack_net_ops);
+       unregister_net_sysctl_table(nf_ct_netfilter_header);
        nf_conntrack_cleanup_end();
 }