[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <1481343298.4930.208.camel@edumazet-glaptop3.roam.corp.google.com>
Date: Fri, 09 Dec 2016 20:14:58 -0800
From: Eric Dumazet <eric.dumazet@...il.com>
To: Josef Bacik <jbacik@...com>
Cc: Hannes Frederic Sowa <hannes@...essinduktion.org>,
Tom Herbert <tom@...bertland.com>,
Linux Kernel Network Developers <netdev@...r.kernel.org>
Subject: Re: Soft lockup in inet_put_port on 4.6
On Fri, 2016-12-09 at 19:47 -0800, Eric Dumazet wrote:
>
> Hmm... Is your ephemeral port range includes the port your load
> balancing app is using ?
I suspect that you might have processes doing bind( port = 0) that are
trapped into the bind_conflict() scan ?
With 100,000 + timewaits there, this possibly hurts.
Can you try the following loop breaker ?
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index d5d3ead0a6c31e42e8843d30f8c643324a91b8e9..74f0f5ee6a02c624edb0263b9ddd27813f68d0a5 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -51,7 +51,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
int reuse = sk->sk_reuse;
int reuseport = sk->sk_reuseport;
kuid_t uid = sock_i_uid((struct sock *)sk);
-
+ unsigned int max_count;
/*
* Unlike other sk lookup places we do not check
* for sk_net here, since _all_ the socks listed
@@ -59,6 +59,7 @@ int inet_csk_bind_conflict(const struct sock *sk,
* one this bucket belongs to.
*/
+ max_count = relax ? ~0U : 100;
sk_for_each_bound(sk2, &tb->owners) {
if (sk != sk2 &&
!inet_v6_ipv6only(sk2) &&
@@ -84,6 +85,8 @@ int inet_csk_bind_conflict(const struct sock *sk,
break;
}
}
+ if (--max_count == 0)
+ return 1;
}
return sk2 != NULL;
}
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c
index 1c86c478f578b49373e61a4c397f23f3dc7f3fc6..4f63d06e0d601da94eb3f2b35a988abd060e156c 100644
--- a/net/ipv6/inet6_connection_sock.c
+++ b/net/ipv6/inet6_connection_sock.c
@@ -35,12 +35,14 @@ int inet6_csk_bind_conflict(const struct sock *sk,
int reuse = sk->sk_reuse;
int reuseport = sk->sk_reuseport;
kuid_t uid = sock_i_uid((struct sock *)sk);
+ unsigned int max_count;
/* We must walk the whole port owner list in this case. -DaveM */
/*
* See comment in inet_csk_bind_conflict about sock lookup
* vs net namespaces issues.
*/
+ max_count = relax ? ~0U : 100;
sk_for_each_bound(sk2, &tb->owners) {
if (sk != sk2 &&
(!sk->sk_bound_dev_if ||
@@ -61,6 +63,8 @@ int inet6_csk_bind_conflict(const struct sock *sk,
ipv6_rcv_saddr_equal(sk, sk2, true))
break;
}
+ if (--max_count == 0)
+ return 1;
}
return sk2 != NULL;
Powered by blists - more mailing lists