[Devel] [PATCH RHEL7 COMMIT] net/sctp: Suppress high order allocation warning
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Apr 2 17:34:38 MSK 2018
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 at 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 at 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));
More information about the Devel
mailing list