Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hch/hfsplus
[pandora-kernel.git] / net / sctp / socket.c
index 08c6238..d3ccf79 100644 (file)
@@ -1384,6 +1384,7 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
        struct sctp_endpoint *ep;
        struct sctp_association *asoc;
        struct list_head *pos, *temp;
+       unsigned int data_was_unread;
 
        SCTP_DEBUG_PRINTK("sctp_close(sk: 0x%p, timeout:%ld)\n", sk, timeout);
 
@@ -1393,6 +1394,10 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
 
        ep = sctp_sk(sk)->ep;
 
+       /* Clean up any skbs sitting on the receive queue.  */
+       data_was_unread = sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
+       data_was_unread += sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
+
        /* Walk all associations on an endpoint.  */
        list_for_each_safe(pos, temp, &ep->asocs) {
                asoc = list_entry(pos, struct sctp_association, asocs);
@@ -1410,7 +1415,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
                        }
                }
 
-               if (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime) {
+               if (data_was_unread || !skb_queue_empty(&asoc->ulpq.lobby) ||
+                   !skb_queue_empty(&asoc->ulpq.reasm) ||
+                   (sock_flag(sk, SOCK_LINGER) && !sk->sk_lingertime)) {
                        struct sctp_chunk *chunk;
 
                        chunk = sctp_make_abort_user(asoc, NULL, 0);
@@ -1420,10 +1427,6 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
                        sctp_primitive_SHUTDOWN(asoc, NULL);
        }
 
-       /* Clean up any skbs sitting on the receive queue.  */
-       sctp_queue_purge_ulpevents(&sk->sk_receive_queue);
-       sctp_queue_purge_ulpevents(&sctp_sk(sk)->pd_lobby);
-
        /* On a TCP-style socket, block for at most linger_time if set. */
        if (sctp_style(sk, TCP) && timeout)
                sctp_wait_for_close(sk, timeout);