aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorAlexey Dobriyan <adobriyan@gmail.com>2008-10-08 05:35:09 -0400
committerPatrick McHardy <kaber@trash.net>2008-10-08 05:35:09 -0400
commit08f6547d266fdba087f7fa7963fc0610be5b7cd7 (patch)
tree60e4dbfc5328d581503eb074c2ff0794be40ecd2 /net
parentd716a4dfbbdf0d4731d596a96e5f4b0d892ac168 (diff)
netfilter: netns nf_conntrack: final netns tweaks
Add init_net checks to not remove kmem_caches twice and so on. Refactor functions to split code which should be executed only for init_net into one place. ip_ct_attach and ip_ct_destroy assignments remain separate, because they're separate stages in setup and teardown. NOTE: NOTRACK code is in for-every-net part. It will be made per-netns after we decidce how to do it correctly. Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Patrick McHardy <kaber@trash.net>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_core.c151
-rw-r--r--net/netfilter/nf_conntrack_expect.c26
2 files changed, 114 insertions, 63 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index bb26460d897c..27de3c7b006e 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1010,17 +1010,15 @@ void nf_conntrack_flush(struct net *net)
1010} 1010}
1011EXPORT_SYMBOL_GPL(nf_conntrack_flush); 1011EXPORT_SYMBOL_GPL(nf_conntrack_flush);
1012 1012
1013/* Mishearing the voices in his head, our hero wonders how he's 1013static void nf_conntrack_cleanup_init_net(void)
1014 supposed to kill the mall. */
1015void nf_conntrack_cleanup(struct net *net)
1016{ 1014{
1017 rcu_assign_pointer(ip_ct_attach, NULL); 1015 nf_conntrack_helper_fini();
1018 1016 nf_conntrack_proto_fini();
1019 /* This makes sure all current packets have passed through 1017 kmem_cache_destroy(nf_conntrack_cachep);
1020 netfilter framework. Roll on, two-stage module 1018}
1021 delete... */
1022 synchronize_net();
1023 1019
1020static void nf_conntrack_cleanup_net(struct net *net)
1021{
1024 nf_ct_event_cache_flush(net); 1022 nf_ct_event_cache_flush(net);
1025 nf_conntrack_ecache_fini(net); 1023 nf_conntrack_ecache_fini(net);
1026 i_see_dead_people: 1024 i_see_dead_people:
@@ -1033,17 +1031,31 @@ void nf_conntrack_cleanup(struct net *net)
1033 while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1) 1031 while (atomic_read(&nf_conntrack_untracked.ct_general.use) > 1)
1034 schedule(); 1032 schedule();
1035 1033
1036 rcu_assign_pointer(nf_ct_destroy, NULL);
1037
1038 kmem_cache_destroy(nf_conntrack_cachep);
1039 nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, 1034 nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
1040 nf_conntrack_htable_size); 1035 nf_conntrack_htable_size);
1041
1042 nf_conntrack_acct_fini(net); 1036 nf_conntrack_acct_fini(net);
1043 nf_conntrack_expect_fini(net); 1037 nf_conntrack_expect_fini(net);
1044 free_percpu(net->ct.stat); 1038 free_percpu(net->ct.stat);
1045 nf_conntrack_helper_fini(); 1039}
1046 nf_conntrack_proto_fini(); 1040
1041/* Mishearing the voices in his head, our hero wonders how he's
1042 supposed to kill the mall. */
1043void nf_conntrack_cleanup(struct net *net)
1044{
1045 if (net_eq(net, &init_net))
1046 rcu_assign_pointer(ip_ct_attach, NULL);
1047
1048 /* This makes sure all current packets have passed through
1049 netfilter framework. Roll on, two-stage module
1050 delete... */
1051 synchronize_net();
1052
1053 nf_conntrack_cleanup_net(net);
1054
1055 if (net_eq(net, &init_net)) {
1056 rcu_assign_pointer(nf_ct_destroy, NULL);
1057 nf_conntrack_cleanup_init_net();
1058 }
1047} 1059}
1048 1060
1049struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced) 1061struct hlist_head *nf_ct_alloc_hashtable(unsigned int *sizep, int *vmalloced)
@@ -1128,7 +1140,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_set_hashsize);
1128module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint, 1140module_param_call(hashsize, nf_conntrack_set_hashsize, param_get_uint,
1129 &nf_conntrack_htable_size, 0600); 1141 &nf_conntrack_htable_size, 0600);
1130 1142
1131int nf_conntrack_init(struct net *net) 1143static int nf_conntrack_init_init_net(void)
1132{ 1144{
1133 int max_factor = 8; 1145 int max_factor = 8;
1134 int ret; 1146 int ret;
@@ -1150,21 +1162,6 @@ int nf_conntrack_init(struct net *net)
1150 * entries. */ 1162 * entries. */
1151 max_factor = 4; 1163 max_factor = 4;
1152 } 1164 }
1153 atomic_set(&net->ct.count, 0);
1154 net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
1155 if (!net->ct.stat)
1156 goto err_stat;
1157 ret = nf_conntrack_ecache_init(net);
1158 if (ret < 0)
1159 goto err_ecache;
1160 net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
1161 &net->ct.hash_vmalloc);
1162 if (!net->ct.hash) {
1163 printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
1164 goto err_hash;
1165 }
1166 INIT_HLIST_HEAD(&net->ct.unconfirmed);
1167
1168 nf_conntrack_max = max_factor * nf_conntrack_htable_size; 1165 nf_conntrack_max = max_factor * nf_conntrack_htable_size;
1169 1166
1170 printk("nf_conntrack version %s (%u buckets, %d max)\n", 1167 printk("nf_conntrack version %s (%u buckets, %d max)\n",
@@ -1176,28 +1173,55 @@ int nf_conntrack_init(struct net *net)
1176 0, 0, NULL); 1173 0, 0, NULL);
1177 if (!nf_conntrack_cachep) { 1174 if (!nf_conntrack_cachep) {
1178 printk(KERN_ERR "Unable to create nf_conn slab cache\n"); 1175 printk(KERN_ERR "Unable to create nf_conn slab cache\n");
1179 goto err_free_hash; 1176 ret = -ENOMEM;
1177 goto err_cache;
1180 } 1178 }
1181 1179
1182 ret = nf_conntrack_proto_init(); 1180 ret = nf_conntrack_proto_init();
1183 if (ret < 0) 1181 if (ret < 0)
1184 goto err_free_conntrack_slab; 1182 goto err_proto;
1185
1186 ret = nf_conntrack_expect_init(net);
1187 if (ret < 0)
1188 goto out_fini_proto;
1189 1183
1190 ret = nf_conntrack_helper_init(); 1184 ret = nf_conntrack_helper_init();
1191 if (ret < 0) 1185 if (ret < 0)
1192 goto out_fini_expect; 1186 goto err_helper;
1187
1188 return 0;
1189
1190err_helper:
1191 nf_conntrack_proto_fini();
1192err_proto:
1193 kmem_cache_destroy(nf_conntrack_cachep);
1194err_cache:
1195 return ret;
1196}
1197
1198static int nf_conntrack_init_net(struct net *net)
1199{
1200 int ret;
1193 1201
1202 atomic_set(&net->ct.count, 0);
1203 INIT_HLIST_HEAD(&net->ct.unconfirmed);
1204 net->ct.stat = alloc_percpu(struct ip_conntrack_stat);
1205 if (!net->ct.stat) {
1206 ret = -ENOMEM;
1207 goto err_stat;
1208 }
1209 ret = nf_conntrack_ecache_init(net);
1210 if (ret < 0)
1211 goto err_ecache;
1212 net->ct.hash = nf_ct_alloc_hashtable(&nf_conntrack_htable_size,
1213 &net->ct.hash_vmalloc);
1214 if (!net->ct.hash) {
1215 ret = -ENOMEM;
1216 printk(KERN_ERR "Unable to create nf_conntrack_hash\n");
1217 goto err_hash;
1218 }
1219 ret = nf_conntrack_expect_init(net);
1220 if (ret < 0)
1221 goto err_expect;
1194 ret = nf_conntrack_acct_init(net); 1222 ret = nf_conntrack_acct_init(net);
1195 if (ret < 0) 1223 if (ret < 0)
1196 goto out_fini_helper; 1224 goto err_acct;
1197
1198 /* For use by REJECT target */
1199 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
1200 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
1201 1225
1202 /* Set up fake conntrack: 1226 /* Set up fake conntrack:
1203 - to never be deleted, not in any hashes */ 1227 - to never be deleted, not in any hashes */
@@ -1208,17 +1232,11 @@ int nf_conntrack_init(struct net *net)
1208 /* - and look it like as a confirmed connection */ 1232 /* - and look it like as a confirmed connection */
1209 set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status); 1233 set_bit(IPS_CONFIRMED_BIT, &nf_conntrack_untracked.status);
1210 1234
1211 return ret; 1235 return 0;
1212 1236
1213out_fini_helper: 1237err_acct:
1214 nf_conntrack_helper_fini();
1215out_fini_expect:
1216 nf_conntrack_expect_fini(net); 1238 nf_conntrack_expect_fini(net);
1217out_fini_proto: 1239err_expect:
1218 nf_conntrack_proto_fini();
1219err_free_conntrack_slab:
1220 kmem_cache_destroy(nf_conntrack_cachep);
1221err_free_hash:
1222 nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc, 1240 nf_ct_free_hashtable(net->ct.hash, net->ct.hash_vmalloc,
1223 nf_conntrack_htable_size); 1241 nf_conntrack_htable_size);
1224err_hash: 1242err_hash:
@@ -1226,5 +1244,32 @@ err_hash:
1226err_ecache: 1244err_ecache:
1227 free_percpu(net->ct.stat); 1245 free_percpu(net->ct.stat);
1228err_stat: 1246err_stat:
1229 return -ENOMEM; 1247 return ret;
1248}
1249
1250int nf_conntrack_init(struct net *net)
1251{
1252 int ret;
1253
1254 if (net_eq(net, &init_net)) {
1255 ret = nf_conntrack_init_init_net();
1256 if (ret < 0)
1257 goto out_init_net;
1258 }
1259 ret = nf_conntrack_init_net(net);
1260 if (ret < 0)
1261 goto out_net;
1262
1263 if (net_eq(net, &init_net)) {
1264 /* For use by REJECT target */
1265 rcu_assign_pointer(ip_ct_attach, nf_conntrack_attach);
1266 rcu_assign_pointer(nf_ct_destroy, destroy_conntrack);
1267 }
1268 return 0;
1269
1270out_net:
1271 if (net_eq(net, &init_net))
1272 nf_conntrack_cleanup_init_net();
1273out_init_net:
1274 return ret;
1230} 1275}
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index b7f751171613..37a703bc3b8e 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -563,12 +563,14 @@ int nf_conntrack_expect_init(struct net *net)
563{ 563{
564 int err = -ENOMEM; 564 int err = -ENOMEM;
565 565
566 if (!nf_ct_expect_hsize) { 566 if (net_eq(net, &init_net)) {
567 nf_ct_expect_hsize = nf_conntrack_htable_size / 256; 567 if (!nf_ct_expect_hsize) {
568 if (!nf_ct_expect_hsize) 568 nf_ct_expect_hsize = nf_conntrack_htable_size / 256;
569 nf_ct_expect_hsize = 1; 569 if (!nf_ct_expect_hsize)
570 nf_ct_expect_hsize = 1;
571 }
572 nf_ct_expect_max = nf_ct_expect_hsize * 4;
570 } 573 }
571 nf_ct_expect_max = nf_ct_expect_hsize * 4;
572 574
573 net->ct.expect_count = 0; 575 net->ct.expect_count = 0;
574 net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize, 576 net->ct.expect_hash = nf_ct_alloc_hashtable(&nf_ct_expect_hsize,
@@ -576,11 +578,13 @@ int nf_conntrack_expect_init(struct net *net)
576 if (net->ct.expect_hash == NULL) 578 if (net->ct.expect_hash == NULL)
577 goto err1; 579 goto err1;
578 580
579 nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect", 581 if (net_eq(net, &init_net)) {
582 nf_ct_expect_cachep = kmem_cache_create("nf_conntrack_expect",
580 sizeof(struct nf_conntrack_expect), 583 sizeof(struct nf_conntrack_expect),
581 0, 0, NULL); 584 0, 0, NULL);
582 if (!nf_ct_expect_cachep) 585 if (!nf_ct_expect_cachep)
583 goto err2; 586 goto err2;
587 }
584 588
585 err = exp_proc_init(net); 589 err = exp_proc_init(net);
586 if (err < 0) 590 if (err < 0)
@@ -589,7 +593,8 @@ int nf_conntrack_expect_init(struct net *net)
589 return 0; 593 return 0;
590 594
591err3: 595err3:
592 kmem_cache_destroy(nf_ct_expect_cachep); 596 if (net_eq(net, &init_net))
597 kmem_cache_destroy(nf_ct_expect_cachep);
593err2: 598err2:
594 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, 599 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
595 nf_ct_expect_hsize); 600 nf_ct_expect_hsize);
@@ -600,7 +605,8 @@ err1:
600void nf_conntrack_expect_fini(struct net *net) 605void nf_conntrack_expect_fini(struct net *net)
601{ 606{
602 exp_proc_remove(net); 607 exp_proc_remove(net);
603 kmem_cache_destroy(nf_ct_expect_cachep); 608 if (net_eq(net, &init_net))
609 kmem_cache_destroy(nf_ct_expect_cachep);
604 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc, 610 nf_ct_free_hashtable(net->ct.expect_hash, net->ct.expect_vmalloc,
605 nf_ct_expect_hsize); 611 nf_ct_expect_hsize);
606} 612}