aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv4/tcp.c
diff options
context:
space:
mode:
authorHerbert Xu <herbert@gondor.apana.org.au>2008-12-30 02:04:08 -0500
committerDavid S. Miller <davem@davemloft.net>2008-12-30 02:04:08 -0500
commiteb4dea5853046727bfbb579f0c9a8cae7369f7c6 (patch)
tree79e18d6284494ab63a890885b0eecce9431a9597 /net/ipv4/tcp.c
parent0f23174aa8c1aa7a2a6050a72a60d290ef9ee578 (diff)
net: Fix percpu counters deadlock
When we converted the protocol atomic counters such as the orphan count and the total socket count deadlocks were introduced due to the mismatch in BH status of the spots that used the percpu counter operations. Based on the diagnosis and patch by Peter Zijlstra, this patch fixes these issues by disabling BH where we may be in process context. Reported-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Tested-by: Ingo Molnar <mingo@elte.hu> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/ipv4/tcp.c')
-rw-r--r--net/ipv4/tcp.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1f3d52946b3b..f28acf11fc67 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1836,7 +1836,6 @@ adjudge_to_death:
1836 state = sk->sk_state; 1836 state = sk->sk_state;
1837 sock_hold(sk); 1837 sock_hold(sk);
1838 sock_orphan(sk); 1838 sock_orphan(sk);
1839 percpu_counter_inc(sk->sk_prot->orphan_count);
1840 1839
1841 /* It is the last release_sock in its life. It will remove backlog. */ 1840 /* It is the last release_sock in its life. It will remove backlog. */
1842 release_sock(sk); 1841 release_sock(sk);
@@ -1849,6 +1848,8 @@ adjudge_to_death:
1849 bh_lock_sock(sk); 1848 bh_lock_sock(sk);
1850 WARN_ON(sock_owned_by_user(sk)); 1849 WARN_ON(sock_owned_by_user(sk));
1851 1850
1851 percpu_counter_inc(sk->sk_prot->orphan_count);
1852
1852 /* Have we already been destroyed by a softirq or backlog? */ 1853 /* Have we already been destroyed by a softirq or backlog? */
1853 if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) 1854 if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE)
1854 goto out; 1855 goto out;