aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorVladimir Davydov <VDavydov@parallels.com>2013-03-13 19:40:14 -0400
committerPablo Neira Ayuso <pablo@netfilter.org>2013-03-19 12:08:31 -0400
commitdece40e848f6e022f960dc9de54be518928460c3 (patch)
tree4350c34ed329d2a4335f71c9bc4d3856c2530a38 /net
parent493763684fefca54502e2d95b057075ac8e279ea (diff)
netfilter: nf_conntrack: speed up module removal path if netns in use
The patch introduces nf_conntrack_cleanup_net_list(), which cleanups nf_conntrack for a list of netns and calls synchronize_net() only once for them all. This should reduce netns destruction time. I've measured cleanup time for 1k dummy net ns. Here are the results: <without the patch> # modprobe nf_conntrack # time modprobe -r nf_conntrack real 0m10.337s user 0m0.000s sys 0m0.376s <with the patch> # modprobe nf_conntrack # time modprobe -r nf_conntrack real 0m5.661s user 0m0.000s sys 0m0.216s Signed-off-by: Vladimir Davydov <vdavydov@parallels.com> Cc: Patrick McHardy <kaber@trash.net> Cc: "David S. Miller" <davem@davemloft.net> Cc: "Eric W. Biederman" <ebiederm@xmission.com> Acked-by: Gao feng <gaofeng@cn.fujitsu.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
Diffstat (limited to 'net')
-rw-r--r--net/netfilter/nf_conntrack_core.c46
-rw-r--r--net/netfilter/nf_conntrack_standalone.c16
2 files changed, 42 insertions, 20 deletions
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 1068deb97c8b..007e8c43d19a 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1365,30 +1365,48 @@ void nf_conntrack_cleanup_end(void)
1365 */ 1365 */
1366void nf_conntrack_cleanup_net(struct net *net) 1366void nf_conntrack_cleanup_net(struct net *net)
1367{ 1367{
1368 LIST_HEAD(single);
1369
1370 list_add(&net->exit_list, &single);
1371 nf_conntrack_cleanup_net_list(&single);
1372}
1373
1374void nf_conntrack_cleanup_net_list(struct list_head *net_exit_list)
1375{
1376 int busy;
1377 struct net *net;
1378
1368 /* 1379 /*
1369 * This makes sure all current packets have passed through 1380 * This makes sure all current packets have passed through
1370 * netfilter framework. Roll on, two-stage module 1381 * netfilter framework. Roll on, two-stage module
1371 * delete... 1382 * delete...
1372 */ 1383 */
1373 synchronize_net(); 1384 synchronize_net();
1374 i_see_dead_people: 1385i_see_dead_people:
1375 nf_ct_iterate_cleanup(net, kill_all, NULL); 1386 busy = 0;
1376 nf_ct_release_dying_list(net); 1387 list_for_each_entry(net, net_exit_list, exit_list) {
1377 if (atomic_read(&net->ct.count) != 0) { 1388 nf_ct_iterate_cleanup(net, kill_all, NULL);
1389 nf_ct_release_dying_list(net);
1390 if (atomic_read(&net->ct.count) != 0)
1391 busy = 1;
1392 }
1393 if (busy) {
1378 schedule(); 1394 schedule();
1379 goto i_see_dead_people; 1395 goto i_see_dead_people;
1380 } 1396 }
1381 1397
1382 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size); 1398 list_for_each_entry(net, net_exit_list, exit_list) {
1383 nf_conntrack_proto_pernet_fini(net); 1399 nf_ct_free_hashtable(net->ct.hash, net->ct.htable_size);
1384 nf_conntrack_helper_pernet_fini(net); 1400 nf_conntrack_proto_pernet_fini(net);
1385 nf_conntrack_ecache_pernet_fini(net); 1401 nf_conntrack_helper_pernet_fini(net);
1386 nf_conntrack_tstamp_pernet_fini(net); 1402 nf_conntrack_ecache_pernet_fini(net);
1387 nf_conntrack_acct_pernet_fini(net); 1403 nf_conntrack_tstamp_pernet_fini(net);
1388 nf_conntrack_expect_pernet_fini(net); 1404 nf_conntrack_acct_pernet_fini(net);
1389 kmem_cache_destroy(net->ct.nf_conntrack_cachep); 1405 nf_conntrack_expect_pernet_fini(net);
1390 kfree(net->ct.slabname); 1406 kmem_cache_destroy(net->ct.nf_conntrack_cachep);
1391 free_percpu(net->ct.stat); 1407 kfree(net->ct.slabname);
1408 free_percpu(net->ct.stat);
1409 }
1392} 1410}
1393 1411
1394void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls) 1412void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 6bcce401fd1c..6c69fbdb8361 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -545,16 +545,20 @@ out_init:
545 return ret; 545 return ret;
546} 546}
547 547
548static void nf_conntrack_pernet_exit(struct net *net) 548static void nf_conntrack_pernet_exit(struct list_head *net_exit_list)
549{ 549{
550 nf_conntrack_standalone_fini_sysctl(net); 550 struct net *net;
551 nf_conntrack_standalone_fini_proc(net); 551
552 nf_conntrack_cleanup_net(net); 552 list_for_each_entry(net, net_exit_list, exit_list) {
553 nf_conntrack_standalone_fini_sysctl(net);
554 nf_conntrack_standalone_fini_proc(net);
555 }
556 nf_conntrack_cleanup_net_list(net_exit_list);
553} 557}
554 558
555static struct pernet_operations nf_conntrack_net_ops = { 559static struct pernet_operations nf_conntrack_net_ops = {
556 .init = nf_conntrack_pernet_init, 560 .init = nf_conntrack_pernet_init,
557 .exit = nf_conntrack_pernet_exit, 561 .exit_batch = nf_conntrack_pernet_exit,
558}; 562};
559 563
560static int __init nf_conntrack_standalone_init(void) 564static int __init nf_conntrack_standalone_init(void)