]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
sdp: Fix partial ZCopy send bug + recvmsg with MSG_PEEK support
authorAmir Vadai <amirv@mellanox.co.il>
Sun, 27 Dec 2009 09:08:26 +0000 (11:08 +0200)
committerMukesh Kacker <mukesh.kacker@oracle.com>
Tue, 6 Oct 2015 12:04:45 +0000 (05:04 -0700)
Signed-off-by: Amir Vadai <amirv@mellanox.co.il>
drivers/infiniband/ulp/sdp/sdp.h
drivers/infiniband/ulp/sdp/sdp_main.c
drivers/infiniband/ulp/sdp/sdp_zcopy.c

index afb829d552095edc8b789a13342c849dfa68c6ed..534c2761cfbacb494c8f3238ef83f0026c694a36 100644 (file)
@@ -68,10 +68,10 @@ struct sdp_skb_cb {
        struct tx_srcavail_state *tx_sa;
 };
 
-#define BZCOPY_STATE(skb) (((struct sdp_skb_cb *)(skb->cb))->bz)
-#define RX_SRCAVAIL_STATE(skb) (((struct sdp_skb_cb *)(skb->cb))->rx_sa)
-#define TX_SRCAVAIL_STATE(skb) (((struct sdp_skb_cb *)(skb->cb))->tx_sa)
-#define SDP_SKB_CB(__skb)      ((struct sdp_skb_cb *)&((__skb)->cb[0]))
+#define SDP_SKB_CB(__skb)      ((struct sdp_skb_cb *)&((__skb)->cb[0]))
+#define BZCOPY_STATE(skb)      (SDP_SKB_CB(skb)->bz)
+#define RX_SRCAVAIL_STATE(skb) (SDP_SKB_CB(skb)->rx_sa)
+#define TX_SRCAVAIL_STATE(skb) (SDP_SKB_CB(skb)->tx_sa)
 
 #ifndef MIN
 #define MIN(a, b) (a < b ? a : b)
index e97100fcbc666ef0f47dd5d63aef45dabf4adb85..be77cdf94aa06a0a944b64fb6d48284711efd274 100644 (file)
@@ -1812,17 +1812,16 @@ static int sdp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
 
        if (sdp_zcopy_thresh && size > sdp_zcopy_thresh && size > SDP_MIN_ZCOPY_THRESH) {
                zcopied = sdp_sendmsg_zcopy(iocb, sk, msg, size);
-               if (zcopied == -EAGAIN || zcopied == -ETIME) {
-                       sdp_dbg_data(sk, "Got SendSM/Timedout - fallback to regular send\n");
-               } else if (zcopied < 0) {
+
+               if (zcopied < 0) {
                        sdp_dbg_data(sk, "ZCopy send err: %d\n", zcopied);
                        return zcopied;
-               }
-
-               if (size == zcopied) {
+               } else if (size == zcopied) {
                        return size;
                }
 
+               sdp_dbg_data(sk, "Got SendSM/Timedout - fallback to regular send\n");
+
                sdp_dbg_data(sk, "ZCopied: 0x%x\n", zcopied);
                sdp_dbg_data(sk, "Continue to BCopy 0x%lx bytes left\n", size - zcopied);
        }
@@ -2021,6 +2020,19 @@ out_err:
        return err;
 }
 
+static inline int sdp_abort_rx_srcavail(struct sock *sk, struct sk_buff *skb)
+{
+       struct sdp_bsdh *h = (struct sdp_bsdh *)skb_transport_header(skb);
+
+       sdp_dbg_data(sk, "SrcAvail aborted\n");
+
+       h->mid = SDP_MID_DATA;
+       kfree(RX_SRCAVAIL_STATE(skb));
+       RX_SRCAVAIL_STATE(skb) = NULL;
+
+       return 0;
+}
+
 /* Like tcp_recvmsg */
 /* Maybe use skb_recv_datagram here? */
 /* Note this does not seem to handle vectored messages. Relevant? */
@@ -2103,6 +2115,13 @@ static int sdp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                        case SDP_MID_SRCAVAIL:
                                rx_sa = RX_SRCAVAIL_STATE(skb);
 
+                               if (rx_sa->mseq < ssk->srcavail_cancel_mseq) {
+                                       sdp_dbg_data(sk, "Ignoring src avail "
+                                                       "due to SrcAvailCancel\n");
+                                       sdp_abort_rx_srcavail(sk, skb);
+                                       goto sdp_mid_data;
+                               }
+
                                /* if has payload - handle as if MID_DATA */
                                if (rx_sa->used < skb->len) {
                                        sdp_dbg_data(sk, "SrcAvail has "
@@ -2115,23 +2134,21 @@ static int sdp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                                "RDMAing: %d/%d\n",
                                                rx_sa->used, rx_sa->len);
 
-                                       if (rx_sa->mseq < ssk->srcavail_cancel_mseq) {
-                                               rx_sa->flags |= RX_SA_ABORTED;
-                                               sdp_dbg_data(sk, "Ignoring src avail "
-                                                               "due to SrcAvailCancel\n");
-                                       }
-
-                                       if (rx_sa->flags & RX_SA_ABORTED) {
-                                               sdp_dbg_data(sk, "rx_sa aborted. not rdmaing\n");
-                                               goto skb_cleanup;
+                                       if (flags & MSG_PEEK) {
+                                               sdp_dbg_data(sk, "Peek on RDMA data - "
+                                                               "fallback to BCopy\n");
+                                               sdp_abort_rx_srcavail(sk, skb);
+                                               sdp_post_sendsm(sk);
+                                               rx_sa = NULL;
+                                       } else {
+                                               avail_bytes_count = rx_sa->len;
                                        }
-
-                                       avail_bytes_count = rx_sa->len;
                                }
 
                                break;
 
                        case SDP_MID_DATA:
+sdp_mid_data:                          
                                rx_sa = NULL;
                                avail_bytes_count = skb->len;
                                break;
@@ -2151,6 +2168,9 @@ static int sdp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                goto found_ok_skb;
 
                        WARN_ON(!(flags & MSG_PEEK));
+
+                       WARN_ON(h->mid == SDP_MID_SRCAVAIL);
+
                        skb = skb->next;
                } while (skb != (struct sk_buff *)&sk->sk_receive_queue);
 
@@ -2248,8 +2268,9 @@ static int sdp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                if (!(flags & MSG_TRUNC)) {
                        if (rx_sa && rx_sa->used >= skb->len) {
                                /* No more payload - start rdma copy */
-                               sdp_dbg_data(sk, "RDMA copy of %ld bytes\n", used);
+                               sdp_dbg_data(sk, "RDMA copy of %lx bytes\n", used);
                                err = sdp_rdma_to_iovec(sk, msg->msg_iov, skb, &used);
+                               sdp_dbg_data(sk, "used = %lx bytes\n", used);
                                if (err == -EAGAIN) {
                                        sdp_dbg_data(sk, "RDMA Read aborted\n");
                                        goto skb_cleanup;
@@ -2261,7 +2282,7 @@ static int sdp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                                err = skb_copy_datagram_iovec(skb, offset,
                                                /* TODO: skip header? */
                                                msg->msg_iov, used);
-                               if (rx_sa) {
+                               if (rx_sa && !(flags & MSG_PEEK)) {
                                        rx_sa->used += used;
                                        rx_sa->reported += used;
                                }
@@ -2305,8 +2326,7 @@ skip_copy:
                offset = 0;
 
 skb_cleanup:
-               if (!(flags & MSG_PEEK) ||
-                               (rx_sa && (rx_sa->flags & RX_SA_ABORTED))) {
+               if (!(flags & MSG_PEEK)) {
                        struct sdp_bsdh *h;
                        h = (struct sdp_bsdh *)skb_transport_header(skb);
                        sdp_prf1(sk, skb, "READ finished. mseq: %d mseq_ack:%d",
@@ -2322,6 +2342,7 @@ skb_cleanup:
                                
                        }
 
+                       sdp_dbg_data(sk, "unlinking skb %p\n", skb);
                        skb_unlink(skb, &sk->sk_receive_queue);
                        __kfree_skb(skb);
                }
@@ -2344,6 +2365,7 @@ out:
        sdp_auto_moderation(ssk);
 
        release_sock(sk);
+       sdp_dbg_data(sk, "recvmsg finished. ret = %d\n", err);  
        return err;
 
 recv_urg:
index 2c83d2868b0cc4341ef9a3eff65719049cfacaa1..69ad2dbc4307a58a255ba5f00af9f727c58bc3a5 100644 (file)
@@ -766,7 +766,10 @@ err:
 
        sock_put(&ssk->isk.sk, SOCK_REF_ZCOPY);
 
-       return rc ?: copied;
+       if (rc < 0 && rc != -EAGAIN && rc != -ETIME)
+               return rc;
+
+       return copied;
 }
 
 void sdp_abort_srcavail(struct sock *sk)