From 711eb3943a0c0ce5f7a725eb1a8a668ce87ec45a Mon Sep 17 00:00:00 2001 From: Herbert Xu Date: Fri, 5 May 2006 17:09:13 -0700 Subject: [PATCH] --- yaml --- r: 26528 b: refs/heads/master c: 134af34632a7b3b0a98a79a2e56bf9cc927e0eac h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/net/dccp/proto.c | 13 ++++++++++--- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/[refs] b/[refs] index 168dc1b56b20..9975bf8f23e2 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 1c29fc4989bc2a3838b2837adc12b8aeb0feeede +refs/heads/master: 134af34632a7b3b0a98a79a2e56bf9cc927e0eac diff --git a/trunk/net/dccp/proto.c b/trunk/net/dccp/proto.c index 1ff7328b0e17..2e0ee8355c41 100644 --- a/trunk/net/dccp/proto.c +++ b/trunk/net/dccp/proto.c @@ -848,6 +848,7 @@ static int dccp_close_state(struct sock *sk) void dccp_close(struct sock *sk, long timeout) { struct sk_buff *skb; + int state; lock_sock(sk); @@ -882,6 +883,11 @@ void dccp_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. */ @@ -894,8 +900,9 @@ void dccp_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 != DCCP_CLOSED && sk->sk_state == DCCP_CLOSED) + goto out; /* * The last release_sock may have processed the CLOSE or RESET @@ -915,12 +922,12 @@ void dccp_close(struct sock *sk, long timeout) #endif } - atomic_inc(sk->sk_prot->orphan_count); if (sk->sk_state == DCCP_CLOSED) inet_csk_destroy_sock(sk); /* Otherwise, socket is reprieved until protocol close. */ +out: bh_unlock_sock(sk); local_bh_enable(); sock_put(sk);