[RHEL7,COMMIT] net/sctp: Suppress high order allocation warning

Submitted by Konstantin Khorenko on April 2, 2018, 2:34 p.m.

Details

Message ID 201804021434.w32EYcHH024854@finist_ce7.work
State New
Series "net/sctp: Suppress high order allocation warning"
Headers show

Commit Message

Konstantin Khorenko April 2, 2018, 2:34 p.m.
The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.46.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-693.21.1.vz7.46.2
------>
commit 2f98c3fcb08a028de56103d6251ebefd2f611d7f
Author: Oleg Babin <obabin@virtuozzo.com>
Date:   Mon Apr 2 17:34:38 2018 +0300

    net/sctp: Suppress high order allocation warning
    
    SCTP protocol allocates TCB on INIT and COOKIE ECHO chunks, those
    chunks specify input and output stream count (can be up to 65535
    each), so the size of TCB depends on these values and can include
    up to 65535 * 2 * 2 bytes describing input/output streams (2 bytes
    per each stream), i.e. up to seventh order.
    
    As the chunks are handled in softirq context, allocation is made
    with kmalloc() with GFP_ATOMIC flag, so we can't just replace
    kmalloc() call with kvmalloc().
    
    So it was decided to introduce our own flag __GFP_NOWARNHIGHORDER
    and update warn_high_order() function accordingly so that we could
    selectively suppress high order warnings which can not be fixed
    right now without proper algorithm refactoring.
    
    https://jira.sw.ru/browse/PSBM-82552
    Signed-off-by: Oleg Babin <obabin@virtuozzo.com>
---
 include/linux/gfp.h | 3 +++
 mm/page_alloc.c     | 4 +++-
 net/sctp/ssnmap.c   | 2 +-
 3 files changed, 7 insertions(+), 2 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/linux/gfp.h b/include/linux/gfp.h
index ec5ae8aa1085..a6f000f3702a 100644
--- a/include/linux/gfp.h
+++ b/include/linux/gfp.h
@@ -41,6 +41,7 @@  struct vm_area_struct;
 #define ___GFP_NO_KSWAPD	0x400000u
 #define ___GFP_OTHER_NODE	0x800000u
 #define ___GFP_WRITE		0x1000000u
+#define ___GFP_NOWARNHIGHORDER	0x2000000u
 /* If the above are modified, __GFP_BITS_SHIFT may need updating */
 
 /*
@@ -98,6 +99,8 @@  struct vm_area_struct;
 #define __GFP_NO_KSWAPD	((__force gfp_t)___GFP_NO_KSWAPD)
 #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
 #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
+#define __GFP_NOWARNHIGHORDER ((__force gfp_t)___GFP_NOWARNHIGHORDER) /* Don't warn
+							 * on high order allocations */
 
 /*
  * This may seem redundant, but it's a way of annotating false positives vs.
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 15575b24a97c..8cc264c56fb2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -3184,6 +3184,8 @@  int proc_warn_high_order(struct ctl_table *table, int write,
 	return ret;
 }
 
+#define ORDER_NOWARN_MASK (__GFP_NOWARN | __GFP_NOWARNHIGHORDER)
+
 static __always_inline void warn_high_order(int order, gfp_t gfp_mask)
 {
 	static atomic_t warn_count = ATOMIC_INIT(32);
@@ -3191,7 +3193,7 @@  static __always_inline void warn_high_order(int order, gfp_t gfp_mask)
 	if (static_key_false(&warn_high_order_key)) {
 		int tmp_warn_order = smp_load_acquire(&warn_order);
 
-		if (order >= tmp_warn_order && !(gfp_mask & __GFP_NOWARN))
+		if (order >= tmp_warn_order && !(gfp_mask & ORDER_NOWARN_MASK))
 			WARN(atomic_dec_if_positive(&warn_count) >= 0,
 				"order %d >= %d, gfp 0x%x\n",
 				order, tmp_warn_order, gfp_mask);
diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
index da8603523808..989e1e8b4569 100644
--- a/net/sctp/ssnmap.c
+++ b/net/sctp/ssnmap.c
@@ -64,7 +64,7 @@  struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
 
 	size = sctp_ssnmap_size(in, out);
 	if (size <= KMALLOC_MAX_SIZE)
-		retval = kmalloc(size, gfp);
+		retval = kmalloc(size, gfp | __GFP_NOWARNHIGHORDER);
 	else
 		retval = (struct sctp_ssnmap *)
 			  __get_free_pages(gfp, get_order(size));

Comments

Konstantin Khorenko April 2, 2018, 2:37 p.m.
Please, disregard, dropped.

--
Best regards,

Konstantin Khorenko,
Virtuozzo Linux Kernel Team

On 04/02/2018 05:34 PM, Konstantin Khorenko wrote:
> The commit is pushed to "branch-rh7-3.10.0-693.21.1.vz7.46.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
> after rh7-3.10.0-693.21.1.vz7.46.2
> ------>
> commit 2f98c3fcb08a028de56103d6251ebefd2f611d7f
> Author: Oleg Babin <obabin@virtuozzo.com>
> Date:   Mon Apr 2 17:34:38 2018 +0300
>
>     net/sctp: Suppress high order allocation warning
>
>     SCTP protocol allocates TCB on INIT and COOKIE ECHO chunks, those
>     chunks specify input and output stream count (can be up to 65535
>     each), so the size of TCB depends on these values and can include
>     up to 65535 * 2 * 2 bytes describing input/output streams (2 bytes
>     per each stream), i.e. up to seventh order.
>
>     As the chunks are handled in softirq context, allocation is made
>     with kmalloc() with GFP_ATOMIC flag, so we can't just replace
>     kmalloc() call with kvmalloc().
>
>     So it was decided to introduce our own flag __GFP_NOWARNHIGHORDER
>     and update warn_high_order() function accordingly so that we could
>     selectively suppress high order warnings which can not be fixed
>     right now without proper algorithm refactoring.
>
>     https://jira.sw.ru/browse/PSBM-82552
>     Signed-off-by: Oleg Babin <obabin@virtuozzo.com>
> ---
>  include/linux/gfp.h | 3 +++
>  mm/page_alloc.c     | 4 +++-
>  net/sctp/ssnmap.c   | 2 +-
>  3 files changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/include/linux/gfp.h b/include/linux/gfp.h
> index ec5ae8aa1085..a6f000f3702a 100644
> --- a/include/linux/gfp.h
> +++ b/include/linux/gfp.h
> @@ -41,6 +41,7 @@ struct vm_area_struct;
>  #define ___GFP_NO_KSWAPD	0x400000u
>  #define ___GFP_OTHER_NODE	0x800000u
>  #define ___GFP_WRITE		0x1000000u
> +#define ___GFP_NOWARNHIGHORDER	0x2000000u
>  /* If the above are modified, __GFP_BITS_SHIFT may need updating */
>
>  /*
> @@ -98,6 +99,8 @@ struct vm_area_struct;
>  #define __GFP_NO_KSWAPD	((__force gfp_t)___GFP_NO_KSWAPD)
>  #define __GFP_OTHER_NODE ((__force gfp_t)___GFP_OTHER_NODE) /* On behalf of other node */
>  #define __GFP_WRITE	((__force gfp_t)___GFP_WRITE)	/* Allocator intends to dirty page */
> +#define __GFP_NOWARNHIGHORDER ((__force gfp_t)___GFP_NOWARNHIGHORDER) /* Don't warn
> +							 * on high order allocations */
>
>  /*
>   * This may seem redundant, but it's a way of annotating false positives vs.
> diff --git a/mm/page_alloc.c b/mm/page_alloc.c
> index 15575b24a97c..8cc264c56fb2 100644
> --- a/mm/page_alloc.c
> +++ b/mm/page_alloc.c
> @@ -3184,6 +3184,8 @@ int proc_warn_high_order(struct ctl_table *table, int write,
>  	return ret;
>  }
>
> +#define ORDER_NOWARN_MASK (__GFP_NOWARN | __GFP_NOWARNHIGHORDER)
> +
>  static __always_inline void warn_high_order(int order, gfp_t gfp_mask)
>  {
>  	static atomic_t warn_count = ATOMIC_INIT(32);
> @@ -3191,7 +3193,7 @@ static __always_inline void warn_high_order(int order, gfp_t gfp_mask)
>  	if (static_key_false(&warn_high_order_key)) {
>  		int tmp_warn_order = smp_load_acquire(&warn_order);
>
> -		if (order >= tmp_warn_order && !(gfp_mask & __GFP_NOWARN))
> +		if (order >= tmp_warn_order && !(gfp_mask & ORDER_NOWARN_MASK))
>  			WARN(atomic_dec_if_positive(&warn_count) >= 0,
>  				"order %d >= %d, gfp 0x%x\n",
>  				order, tmp_warn_order, gfp_mask);
> diff --git a/net/sctp/ssnmap.c b/net/sctp/ssnmap.c
> index da8603523808..989e1e8b4569 100644
> --- a/net/sctp/ssnmap.c
> +++ b/net/sctp/ssnmap.c
> @@ -64,7 +64,7 @@ struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,
>
>  	size = sctp_ssnmap_size(in, out);
>  	if (size <= KMALLOC_MAX_SIZE)
> -		retval = kmalloc(size, gfp);
> +		retval = kmalloc(size, gfp | __GFP_NOWARNHIGHORDER);
>  	else
>  		retval = (struct sctp_ssnmap *)
>  			  __get_free_pages(gfp, get_order(size));
> .
>