[rh7] net: silence high-order allocation warning from UDP with big headers.

Submitted by Andrey Ryabinin on May 29, 2019, 12:01 p.m.

Details

Message ID 20190529120152.9686-1-aryabinin@virtuozzo.com
State New
Series "net: silence high-order allocation warning from UDP with big headers."
Headers show

Commit Message

Andrey Ryabinin May 29, 2019, 12:01 p.m.
Silence this one:
WARNING: CPU: 2 PID: 180404 at mm/page_alloc.c:3533 __alloc_pages_nodemask+0x1b1/0x600
order 3 >= 3, gfp 0x2044d0
Call Trace:
 dump_stack+0x19/0x1b
 __warn+0xd8/0x100
 warn_slowpath_fmt+0x5f/0x80
 __alloc_pages_nodemask+0x1b1/0x600
 kmalloc_large_node+0x5f/0x80
 __kmalloc_node_track_caller+0x292/0x300
 __kmalloc_reserve.isra.32+0x44/0xa0
 __alloc_skb+0x8d/0x2d0
 alloc_skb_with_frags+0x57/0x1e0
 sock_alloc_send_pskb+0x1b9/0x260
 sock_alloc_send_skb+0x18/0x20
 __ip6_append_data.isra.37+0x9a3/0xd30
 ip6_make_skb+0x152/0x1e0
 udpv6_sendmsg+0x961/0xc30
 inet_sendmsg+0x69/0xb0
 sock_sendmsg+0xb0/0xf0
 SYSC_sendto+0x121/0x1c0
 SyS_sendto+0xe/0x10
 tracesys+0xa3/0xc9

https://jira.sw.ru/browse/PSBM-94717
Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com>
---
 include/net/sock.h    |  5 +++++
 net/core/sock.c       | 21 ++++++++++++++++++---
 net/ipv4/ip_output.c  |  5 +++--
 net/ipv6/ip6_output.c |  5 +++--
 4 files changed, 29 insertions(+), 7 deletions(-)

Patch hide | download patch | download mbox

diff --git a/include/net/sock.h b/include/net/sock.h
index f90941ef02a2..b953c2c496c3 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -1600,6 +1600,11 @@  extern struct sk_buff		*sock_alloc_send_skb(struct sock *sk,
 						     unsigned long size,
 						     int noblock,
 						     int *errcode);
+extern struct sk_buff		*sock_alloc_send_skb_flags(struct sock *sk,
+							   unsigned long size,
+							   int noblock,
+							   int *errcode,
+							   gfp_t extra_flags);
 extern struct sk_buff		*sock_alloc_send_pskb(struct sock *sk,
 						      unsigned long header_len,
 						      unsigned long data_len,
diff --git a/net/core/sock.c b/net/core/sock.c
index ffd747cc30a4..5af59d087610 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -1887,9 +1887,9 @@  static long sock_wait_for_wmem(struct sock *sk, long timeo)
  *	Generic send/receive buffer handlers
  */
 
-struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
+static inline struct sk_buff *__sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 				     unsigned long data_len, int noblock,
-				     int *errcode, int max_page_order)
+				     int *errcode, int max_page_order, gfp_t extra_flags)
 {
 	struct sk_buff *skb;
 	long timeo;
@@ -1918,7 +1918,7 @@  struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 		timeo = sock_wait_for_wmem(sk, timeo);
 	}
 	skb = alloc_skb_with_frags(header_len, data_len, max_page_order,
-				   errcode, sk->sk_allocation);
+				   errcode, sk->sk_allocation|extra_flags);
 	if (skb)
 		skb_set_owner_w(skb, sk);
 	return skb;
@@ -1929,6 +1929,14 @@  struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
 	*errcode = err;
 	return NULL;
 }
+
+struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len,
+				     unsigned long data_len, int noblock,
+				     int *errcode, int max_page_order)
+{
+	return __sock_alloc_send_pskb(sk, header_len, data_len, noblock,
+				errcode, max_page_order, 0);
+}
 EXPORT_SYMBOL(sock_alloc_send_pskb);
 
 struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
@@ -1938,6 +1946,13 @@  struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size,
 }
 EXPORT_SYMBOL(sock_alloc_send_skb);
 
+struct sk_buff *sock_alloc_send_skb_flags(struct sock *sk, unsigned long size,
+				    int noblock, int *errcode, gfp_t extra_flags)
+{
+	return __sock_alloc_send_pskb(sk, size, 0, noblock, errcode, 0, extra_flags);
+}
+EXPORT_SYMBOL(sock_alloc_send_skb_flags);
+
 /* On 32bit arches, an skb frag is limited to 2^15 */
 #define SKB_FRAG_PAGE_ORDER	get_order(32768)
 
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a3f486d3e42b..2ce2ec458ad5 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -993,9 +993,10 @@  static int __ip_append_data(struct sock *sk,
 				alloclen += rt->dst.trailer_len;
 
 			if (transhdrlen) {
-				skb = sock_alloc_send_skb(sk,
+				skb = sock_alloc_send_skb_flags(sk,
 						alloclen + hh_len + 15,
-						(flags & MSG_DONTWAIT), &err);
+						(flags & MSG_DONTWAIT), &err,
+						__GFP_ORDER_NOWARN);
 			} else {
 				skb = NULL;
 				if (atomic_read(&sk->sk_wmem_alloc) <=
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index f398bb628876..89b4444e11fd 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1396,9 +1396,10 @@  static int __ip6_append_data(struct sock *sk,
 				goto error;
 			}
 			if (transhdrlen) {
-				skb = sock_alloc_send_skb(sk,
+				skb = sock_alloc_send_skb_flags(sk,
 						alloclen + hh_len,
-						(flags & MSG_DONTWAIT), &err);
+						(flags & MSG_DONTWAIT), &err,
+						__GFP_ORDER_NOWARN);
 			} else {
 				skb = NULL;
 				if (atomic_read(&sk->sk_wmem_alloc) <=