netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH][v2] netfilter: use kvzalloc to allocate memory for hashtable
@ 2018-07-25  5:34 Li RongQing
  2018-07-25  5:44 ` Eric Dumazet
  0 siblings, 1 reply; 3+ messages in thread
From: Li RongQing @ 2018-07-25  5:34 UTC (permalink / raw)
  To: netdev, pablo, kadlec, fw, netfilter-devel, coreteam, edumazet

nf_ct_alloc_hashtable is used to allocate memory for conntrack,
NAT bysrc and expectation hashtable. Assuming 64k bucket size,
which means 7th order page allocation, __get_free_pages, called
by nf_ct_alloc_hashtable, will trigger the direct memory reclaim
and stall for a long time, when system has lots of memory stress

so replace combination of __get_free_pages and vzalloc with
kvzalloc, which provides a fallback if no high order memory
is available, and do not retry to reclaim memory, reduce stall

and remove nf_ct_free_hashtable, since it is just a kvfree

Signed-off-by: Zhang Yu <zhangyu31@baidu.com>
Signed-off-by: Wang Li <wangli39@baidu.com>
Signed-off-by: Li RongQing <lirongqing@baidu.com>
---
 include/net/netfilter/nf_conntrack.h |  2 --
 net/netfilter/nf_conntrack_core.c    | 23 +++++------------------
 net/netfilter/nf_conntrack_expect.c  |  2 +-
 net/netfilter/nf_conntrack_helper.c  |  4 ++--
 net/netfilter/nf_nat_core.c          |  4 ++--
 5 files changed, 10 insertions(+), 25 deletions(-)

diff --git a/include/net/netfilter/nf_conntrack.h b/include/net/netfilter/nf_conntrack.h
index a2b0ed025908..7e012312cd61 100644
--- a/include/net/netfilter/nf_conntrack.h
+++ b/include/net/netfilter/nf_conntrack.h
@@ -176,8 +176,6 @@ void nf_ct_netns_put(struct net *net, u8 nfproto);
  */
 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls);
 
-void nf_ct_free_hashtable(void *hash, unsigned int size);
-
 int nf_conntrack_hash_check_insert(struct nf_conn *ct);
 bool nf_ct_delete(struct nf_conn *ct, u32 pid, int report);
 
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 8a113ca1eea2..191140c469d5 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2022,16 +2022,6 @@ static int kill_all(struct nf_conn *i, void *data)
 	return net_eq(nf_ct_net(i), data);
 }
 
-void nf_ct_free_hashtable(void *hash, unsigned int size)
-{
-	if (is_vmalloc_addr(hash))
-		vfree(hash);
-	else
-		free_pages((unsigned long)hash,
-			   get_order(sizeof(struct hlist_head) * size));
-}
-EXPORT_SYMBOL_GPL(nf_ct_free_hashtable);
-
 void nf_conntrack_cleanup_start(void)
 {
 	conntrack_gc_work.exiting = true;
@@ -2042,7 +2032,7 @@ void nf_conntrack_cleanup_end(void)
 {
 	RCU_INIT_POINTER(nf_ct_hook, NULL);
 	cancel_delayed_work_sync(&conntrack_gc_work.dwork);
-	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size);
+	kvfree(nf_conntrack_hash);
 
 	nf_conntrack_proto_fini();
 	nf_conntrack_seqadj_fini();
@@ -2120,10 +2110,7 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
 		return NULL;
 
 	sz = nr_slots * sizeof(struct hlist_nulls_head);
-	hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
-					get_order(sz));
-	if (!hash)
-		hash = vzalloc(sz);
+	hash = kvzalloc(sz, GFP_KERNEL);
 
 	if (hash && nulls)
 		for (i = 0; i < nr_slots; i++)
@@ -2150,7 +2137,7 @@ int nf_conntrack_hash_resize(unsigned int hashsize)
 
 	old_size = nf_conntrack_htable_size;
 	if (old_size == hashsize) {
-		nf_ct_free_hashtable(hash, hashsize);
+		kvfree(hash);
 		return 0;
 	}
 
@@ -2186,7 +2173,7 @@ int nf_conntrack_hash_resize(unsigned int hashsize)
 	local_bh_enable();
 
 	synchronize_net();
-	nf_ct_free_hashtable(old_hash, old_size);
+	kvfree(old_hash);
 	return 0;
 }
 
@@ -2350,7 +2337,7 @@ int nf_conntrack_init_start(void)
 err_expect:
 	kmem_cache_destroy(nf_conntrack_cachep);
 err_cachep:
-	nf_ct_free_hashtable(nf_conntrack_hash, nf_conntrack_htable_size);
+	kvfree(nf_conntrack_hash);
 	return ret;
 }
 
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c
index 3f586ba23d92..27b84231db10 100644
--- a/net/netfilter/nf_conntrack_expect.c
+++ b/net/netfilter/nf_conntrack_expect.c
@@ -712,5 +712,5 @@ void nf_conntrack_expect_fini(void)
 {
 	rcu_barrier(); /* Wait for call_rcu() before destroy */
 	kmem_cache_destroy(nf_ct_expect_cachep);
-	nf_ct_free_hashtable(nf_ct_expect_hash, nf_ct_expect_hsize);
+	kvfree(nf_ct_expect_hash);
 }
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c
index d557a425289d..e24b762ffa1d 100644
--- a/net/netfilter/nf_conntrack_helper.c
+++ b/net/netfilter/nf_conntrack_helper.c
@@ -562,12 +562,12 @@ int nf_conntrack_helper_init(void)
 
 	return 0;
 out_extend:
-	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
+	kvfree(nf_ct_helper_hash);
 	return ret;
 }
 
 void nf_conntrack_helper_fini(void)
 {
 	nf_ct_extend_unregister(&helper_extend);
-	nf_ct_free_hashtable(nf_ct_helper_hash, nf_ct_helper_hsize);
+	kvfree(nf_ct_helper_hash);
 }
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c
index 6366f0c0b8c1..e2b196054dfc 100644
--- a/net/netfilter/nf_nat_core.c
+++ b/net/netfilter/nf_nat_core.c
@@ -1056,7 +1056,7 @@ static int __init nf_nat_init(void)
 
 	ret = nf_ct_extend_register(&nat_extend);
 	if (ret < 0) {
-		nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
+		kvfree(nf_nat_bysource);
 		pr_err("Unable to register extension\n");
 		return ret;
 	}
@@ -1094,7 +1094,7 @@ static void __exit nf_nat_cleanup(void)
 	for (i = 0; i < NFPROTO_NUMPROTO; i++)
 		kfree(nf_nat_l4protos[i]);
 	synchronize_net();
-	nf_ct_free_hashtable(nf_nat_bysource, nf_nat_htable_size);
+	kvfree(nf_nat_bysource);
 	unregister_pernet_subsys(&nat_net_ops);
 }
 
-- 
2.16.2

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH][v2] netfilter: use kvzalloc to allocate memory for hashtable
  2018-07-25  5:34 [PATCH][v2] netfilter: use kvzalloc to allocate memory for hashtable Li RongQing
@ 2018-07-25  5:44 ` Eric Dumazet
  2018-07-25  5:49   ` 答复: " Li,Rongqing
  0 siblings, 1 reply; 3+ messages in thread
From: Eric Dumazet @ 2018-07-25  5:44 UTC (permalink / raw)
  To: Li RongQing, netdev, pablo, kadlec, fw, netfilter-devel, coreteam,
	edumazet



On 07/24/2018 10:34 PM, Li RongQing wrote:
> nf_ct_alloc_hashtable is used to allocate memory for conntrack,
> NAT bysrc and expectation hashtable. Assuming 64k bucket size,
> which means 7th order page allocation, __get_free_pages, called
> by nf_ct_alloc_hashtable, will trigger the direct memory reclaim
> and stall for a long time, when system has lots of memory stress

...

>  	sz = nr_slots * sizeof(struct hlist_nulls_head);
> -	hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN | __GFP_ZERO,
> -					get_order(sz));
> -	if (!hash)
> -		hash = vzalloc(sz);
> +	hash = kvzalloc(sz, GFP_KERNEL);


You could remove the @sz computation and call 

hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL);

Thanks to kvmalloc_array() check, you also could remove the :

if (nr_slots > (UINT_MAX / sizeof(struct hlist_nulls_head)))
    return NULL;

That would remove a lot of stuff now we have proper helpers.

^ permalink raw reply	[flat|nested] 3+ messages in thread

* 答复: [PATCH][v2] netfilter: use kvzalloc to allocate memory for hashtable
  2018-07-25  5:44 ` Eric Dumazet
@ 2018-07-25  5:49   ` Li,Rongqing
  0 siblings, 0 replies; 3+ messages in thread
From: Li,Rongqing @ 2018-07-25  5:49 UTC (permalink / raw)
  To: Eric Dumazet, netdev@vger.kernel.org, pablo@netfilter.org,
	kadlec@blackhole.kfki.hu, fw@strlen.de,
	netfilter-devel@vger.kernel.org, coreteam@netfilter.org,
	edumazet@google.com



> -----邮件原件-----
> 发件人: Eric Dumazet [mailto:eric.dumazet@gmail.com]
> 发送时间: 2018年7月25日 13:45
> 收件人: Li,Rongqing <lirongqing@baidu.com>; netdev@vger.kernel.org;
> pablo@netfilter.org; kadlec@blackhole.kfki.hu; fw@strlen.de; netfilter-
> devel@vger.kernel.org; coreteam@netfilter.org; edumazet@google.com
> 主题: Re: [PATCH][v2] netfilter: use kvzalloc to allocate memory for
> hashtable
> 
> 
> 
> On 07/24/2018 10:34 PM, Li RongQing wrote:
> > nf_ct_alloc_hashtable is used to allocate memory for conntrack, NAT
> > bysrc and expectation hashtable. Assuming 64k bucket size, which means
> > 7th order page allocation, __get_free_pages, called by
> > nf_ct_alloc_hashtable, will trigger the direct memory reclaim and
> > stall for a long time, when system has lots of memory stress
> 
> ...
> 
> >  	sz = nr_slots * sizeof(struct hlist_nulls_head);
> > -	hash = (void *)__get_free_pages(GFP_KERNEL | __GFP_NOWARN |
> __GFP_ZERO,
> > -					get_order(sz));
> > -	if (!hash)
> > -		hash = vzalloc(sz);
> > +	hash = kvzalloc(sz, GFP_KERNEL);
> 
> 
> You could remove the @sz computation and call
> 
> hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL);
> 
> Thanks to kvmalloc_array() check, you also could remove the :
> 
> if (nr_slots > (UINT_MAX / sizeof(struct hlist_nulls_head)))
>     return NULL;
> 
> That would remove a lot of stuff now we have proper helpers.


Ok, I will send v3

Thanks

-RongQing

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2018-07-25  6:59 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2018-07-25  5:34 [PATCH][v2] netfilter: use kvzalloc to allocate memory for hashtable Li RongQing
2018-07-25  5:44 ` Eric Dumazet
2018-07-25  5:49   ` 答复: " Li,Rongqing

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).