Merge git://git.kernel.org/pub/scm/linux/kernel/git/bunk/trivial
[pandora-kernel.git] / net / dccp / proto.c
index 1ff7328..f4f0627 100644 (file)
@@ -9,7 +9,6 @@
  *     published by the Free Software Foundation.
  */
 
-#include <linux/config.h>
 #include <linux/dccp.h>
 #include <linux/module.h>
 #include <linux/types.h>
@@ -719,7 +718,7 @@ int dccp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                }
                dccp_pr_debug("packet_type=%s\n",
                              dccp_packet_name(dh->dccph_type));
-               sk_eat_skb(sk, skb);
+               sk_eat_skb(sk, skb, 0);
 verify_sock_status:
                if (sock_flag(sk, SOCK_DONE)) {
                        len = 0;
@@ -773,7 +772,7 @@ verify_sock_status:
                }
        found_fin_ok:
                if (!(flags & MSG_PEEK))
-                       sk_eat_skb(sk, skb);
+                       sk_eat_skb(sk, skb, 0);
                break;
        } while (1);
 out:
@@ -848,6 +847,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 +882,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 +899,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 +921,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);