diff options
Diffstat (limited to 'net/sunrpc/xprtrdma/rpc_rdma.c')
-rw-r--r-- | net/sunrpc/xprtrdma/rpc_rdma.c | 29 |
1 files changed, 24 insertions, 5 deletions
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 5c1954d28d09..14106d26bb95 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -118,6 +118,10 @@ rpcrdma_convert_iovs(struct xdr_buf *xdrbuf, unsigned int pos, | |||
118 | } | 118 | } |
119 | 119 | ||
120 | if (xdrbuf->tail[0].iov_len) { | 120 | if (xdrbuf->tail[0].iov_len) { |
121 | /* the rpcrdma protocol allows us to omit any trailing | ||
122 | * xdr pad bytes, saving the server an RDMA operation. */ | ||
123 | if (xdrbuf->tail[0].iov_len < 4 && xprt_rdma_pad_optimize) | ||
124 | return n; | ||
121 | if (n == nsegs) | 125 | if (n == nsegs) |
122 | return 0; | 126 | return 0; |
123 | seg[n].mr_page = NULL; | 127 | seg[n].mr_page = NULL; |
@@ -508,8 +512,8 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
508 | if (hdrlen == 0) | 512 | if (hdrlen == 0) |
509 | return -1; | 513 | return -1; |
510 | 514 | ||
511 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd\n" | 515 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd" |
512 | " headerp 0x%p base 0x%p lkey 0x%x\n", | 516 | " headerp 0x%p base 0x%p lkey 0x%x\n", |
513 | __func__, transfertypes[wtype], hdrlen, rpclen, padlen, | 517 | __func__, transfertypes[wtype], hdrlen, rpclen, padlen, |
514 | headerp, base, req->rl_iov.lkey); | 518 | headerp, base, req->rl_iov.lkey); |
515 | 519 | ||
@@ -594,7 +598,7 @@ rpcrdma_count_chunks(struct rpcrdma_rep *rep, unsigned int max, int wrchunk, __b | |||
594 | * Scatter inline received data back into provided iov's. | 598 | * Scatter inline received data back into provided iov's. |
595 | */ | 599 | */ |
596 | static void | 600 | static void |
597 | rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) | 601 | rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) |
598 | { | 602 | { |
599 | int i, npages, curlen, olen; | 603 | int i, npages, curlen, olen; |
600 | char *destp; | 604 | char *destp; |
@@ -660,6 +664,13 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len) | |||
660 | } else | 664 | } else |
661 | rqst->rq_rcv_buf.tail[0].iov_len = 0; | 665 | rqst->rq_rcv_buf.tail[0].iov_len = 0; |
662 | 666 | ||
667 | if (pad) { | ||
668 | /* implicit padding on terminal chunk */ | ||
669 | unsigned char *p = rqst->rq_rcv_buf.tail[0].iov_base; | ||
670 | while (pad--) | ||
671 | p[rqst->rq_rcv_buf.tail[0].iov_len++] = 0; | ||
672 | } | ||
673 | |||
663 | if (copy_len) | 674 | if (copy_len) |
664 | dprintk("RPC: %s: %d bytes in" | 675 | dprintk("RPC: %s: %d bytes in" |
665 | " %d extra segments (%d lost)\n", | 676 | " %d extra segments (%d lost)\n", |
@@ -681,12 +692,14 @@ rpcrdma_conn_func(struct rpcrdma_ep *ep) | |||
681 | struct rpc_xprt *xprt = ep->rep_xprt; | 692 | struct rpc_xprt *xprt = ep->rep_xprt; |
682 | 693 | ||
683 | spin_lock_bh(&xprt->transport_lock); | 694 | spin_lock_bh(&xprt->transport_lock); |
695 | if (++xprt->connect_cookie == 0) /* maintain a reserved value */ | ||
696 | ++xprt->connect_cookie; | ||
684 | if (ep->rep_connected > 0) { | 697 | if (ep->rep_connected > 0) { |
685 | if (!xprt_test_and_set_connected(xprt)) | 698 | if (!xprt_test_and_set_connected(xprt)) |
686 | xprt_wake_pending_tasks(xprt, 0); | 699 | xprt_wake_pending_tasks(xprt, 0); |
687 | } else { | 700 | } else { |
688 | if (xprt_test_and_clear_connected(xprt)) | 701 | if (xprt_test_and_clear_connected(xprt)) |
689 | xprt_wake_pending_tasks(xprt, ep->rep_connected); | 702 | xprt_wake_pending_tasks(xprt, -ENOTCONN); |
690 | } | 703 | } |
691 | spin_unlock_bh(&xprt->transport_lock); | 704 | spin_unlock_bh(&xprt->transport_lock); |
692 | } | 705 | } |
@@ -792,14 +805,20 @@ repost: | |||
792 | ((unsigned char *)iptr - (unsigned char *)headerp); | 805 | ((unsigned char *)iptr - (unsigned char *)headerp); |
793 | status = rep->rr_len + rdmalen; | 806 | status = rep->rr_len + rdmalen; |
794 | r_xprt->rx_stats.total_rdma_reply += rdmalen; | 807 | r_xprt->rx_stats.total_rdma_reply += rdmalen; |
808 | /* special case - last chunk may omit padding */ | ||
809 | if (rdmalen &= 3) { | ||
810 | rdmalen = 4 - rdmalen; | ||
811 | status += rdmalen; | ||
812 | } | ||
795 | } else { | 813 | } else { |
796 | /* else ordinary inline */ | 814 | /* else ordinary inline */ |
815 | rdmalen = 0; | ||
797 | iptr = (__be32 *)((unsigned char *)headerp + 28); | 816 | iptr = (__be32 *)((unsigned char *)headerp + 28); |
798 | rep->rr_len -= 28; /*sizeof *headerp;*/ | 817 | rep->rr_len -= 28; /*sizeof *headerp;*/ |
799 | status = rep->rr_len; | 818 | status = rep->rr_len; |
800 | } | 819 | } |
801 | /* Fix up the rpc results for upper layer */ | 820 | /* Fix up the rpc results for upper layer */ |
802 | rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len); | 821 | rpcrdma_inline_fixup(rqst, (char *)iptr, rep->rr_len, rdmalen); |
803 | break; | 822 | break; |
804 | 823 | ||
805 | case htonl(RDMA_NOMSG): | 824 | case htonl(RDMA_NOMSG): |