From 1c3d6f1309ce6c749f0628145107ac5ce11b4f92 Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Wed, 3 May 2006 23:31:35 -0700 Subject: [PATCH] --- yaml --- r: 26488 b: refs/heads/master c: 75c2d9077c63ac21488129cc23561d4f4fd0f5e5 h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/ipv4/tcp.c | 13 +++++++++---- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/[refs] b/[refs] index 4ce617bc6fea..a1341da188f2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 82e84249f0ee098e004c8bd6d90a1640bd56cfbb +refs/heads/master: 75c2d9077c63ac21488129cc23561d4f4fd0f5e5 diff --git a/trunk/net/ipv4/tcp.c b/trunk/net/ipv4/tcp.c index 87f68e787d0c..e2b7b8055037 100644 --- a/trunk/net/ipv4/tcp.c +++ b/trunk/net/ipv4/tcp.c @@ -1468,6 +1468,7 @@ void tcp_close(struct sock *sk, long timeout) { struct sk_buff *skb; int data_was_unread = 0; + int state; lock_sock(sk); sk->sk_shutdown = SHUTDOWN_MASK; @@ -1544,6 +1545,11 @@ void tcp_close(struct sock *sk, long timeout) sk_stream_wait_close(sk, timeout); adjudge_to_death: + state = sk->sk_state; + sock_hold(sk); + sock_orphan(sk); + atomic_inc(sk->sk_prot->orphan_count); + /* It is the last release_sock in its life. It will remove backlog. */ release_sock(sk); @@ -1555,8 +1561,9 @@ void tcp_close(struct sock *sk, long timeout) bh_lock_sock(sk); BUG_TRAP(!sock_owned_by_user(sk)); - sock_hold(sk); - sock_orphan(sk); + /* Have we already been destroyed by a softirq or backlog? */ + if (state != TCP_CLOSE && sk->sk_state == TCP_CLOSE) + goto out; /* This is a (useful) BSD violating of the RFC. There is a * problem with TCP as specified in that the other end could @@ -1584,7 +1591,6 @@ void tcp_close(struct sock *sk, long timeout) if (tmo > TCP_TIMEWAIT_LEN) { inet_csk_reset_keepalive_timer(sk, tcp_fin_time(sk)); } else { - atomic_inc(sk->sk_prot->orphan_count); tcp_time_wait(sk, TCP_FIN_WAIT2, tmo); goto out; } @@ -1603,7 +1609,6 @@ void tcp_close(struct sock *sk, long timeout) NET_INC_STATS_BH(LINUX_MIB_TCPABORTONMEMORY); } } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == TCP_CLOSE) inet_csk_destroy_sock(sk);