diff options
| author | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2006-05-19 00:43:53 +0900 |
|---|---|---|
| committer | KaiGai Kohei <kaigai@ak.jp.nec.com> | 2006-05-19 00:43:53 +0900 |
| commit | 20a92fc74c5c91c7bc5693d51acc2b99aceb0465 (patch) | |
| tree | 41bf535f38ff1a29c560bcf622e9b4ef03c2c106 /net/dccp/proto.c | |
| parent | 21b9879bf2817aca343cdda11ade6a87f5373e74 (diff) | |
| parent | f6a673b3f4f93c1c50e1b18f29254b0531b722a8 (diff) | |
Merge git://git.infradead.org/mtd-2.6
Diffstat (limited to 'net/dccp/proto.c')
| -rw-r--r-- | net/dccp/proto.c | 13 |
1 files changed, 10 insertions, 3 deletions
diff --git a/net/dccp/proto.c b/net/dccp/proto.c index 1ff7328b0e1..2e0ee8355c4 100644 --- a/net/dccp/proto.c +++ b/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 @@ adjudge_to_death: 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 @@ adjudge_to_death: #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); |
