]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
IB/sdp: emulate completion with error if packet queued after disconnect.
authorMichael S. Tsirkin <mst@mellanox.co.il>
Mon, 11 Sep 2006 05:24:22 +0000 (08:24 +0300)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:03:59 +0000 (05:03 -0700)
In TCP packet is sent, and we get RST from the remote. Emulate this in SDP.

drivers/infiniband/ulp/sdp/sdp.h
drivers/infiniband/ulp/sdp/sdp_bcopy.c
drivers/infiniband/ulp/sdp/sdp_main.c

index 3fd0caf7d726e1d6b1f28fe1d0a18bd9fb55ea79..5476c56aec001c7c7124f0186bf2e937a38248f8 100644 (file)
@@ -171,6 +171,7 @@ static inline void sdp_set_state(struct sock *sk, int state)
 extern struct workqueue_struct *sdp_workqueue;
 
 int sdp_cma_handler(struct rdma_cm_id *, struct rdma_cm_event *);
+void sdp_reset(struct sock *sk);
 void sdp_reset_sk(struct sock *sk, int rc);
 void sdp_time_wait_destroy_sk(struct sdp_sock *ssk);
 void sdp_completion_handler(struct ib_cq *cq, void *cq_context);
index 4540fa4889fdf09c62bb566c3be6e776bd7d2da2..ad7c6daf1e9d5083564e0c7be126786252d08a38 100644 (file)
@@ -324,8 +324,15 @@ void sdp_post_sends(struct sdp_sock *ssk, int nonagle)
        struct sk_buff *skb;
        int c;
 
-       if (unlikely(!ssk->id))
+       if (unlikely(!ssk->id)) {
+               if (ssk->isk.sk.sk_send_head) {
+                       sdp_dbg(&ssk->isk.sk,
+                               "Send on socket without cmid ECONNRESET.\n");
+                       /* TODO: flush send queue? */
+                       sdp_reset(&ssk->isk.sk);
+               }
                return;
+       }
 
        while (ssk->bufs > SDP_MIN_BUFS &&
               ssk->tx_head - ssk->tx_tail < SDP_TX_SIZE &&
@@ -383,8 +390,7 @@ static void sdp_handle_wc(struct sdp_sock *ssk, struct ib_wc *wc)
                                sdp_dbg(&ssk->isk.sk,
                                                "Recv completion with error. "
                                                "Status %d\n", wc->status);
-                               sdp_set_error(&ssk->isk.sk, -ECONNRESET);
-                               wake_up(&ssk->wq);
+                               sdp_reset(&ssk->isk.sk);
                        }
                        __kfree_skb(skb);
                } else {
index 64e55199af693bf2da94692ce22370bc07e49c42..20e5f47fc524e527dc16de2e71284538e7888b15 100644 (file)
@@ -210,6 +210,27 @@ void sdp_reset_sk(struct sock *sk, int rc)
                sdp_dbg(sk, "%s: destroy in time wait state\n", __func__);
                sdp_time_wait_destroy_sk(ssk);
        }
+
+       sk->sk_state_change(sk);
+}
+
+/* Like tcp_reset */
+/* When we get a reset (completion with error) we do this. */
+void sdp_reset(struct sock *sk)
+{
+       int err;
+
+       if (sk->sk_state != TCP_ESTABLISHED)
+               return;
+
+       /* We want the right error as BSD sees it (and indeed as we do). */
+
+       /* On fin we currently only set RCV_SHUTDOWN, so .. */
+       err = (sk->sk_shutdown & RCV_SHUTDOWN) ? EPIPE : ECONNRESET;
+
+       sdp_set_error(sk, -err);
+       wake_up(&sdp_sk(sk)->wq);
+       sk->sk_state_change(sk);
 }
 
 /* TODO: linger? */