aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2016-03-04 11:28:18 -0500
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-03-14 14:55:59 -0400
commit59aa1f9a3cce388b4d7d842d6963df11d92a407e (patch)
tree65778460b9050948004b79b65b95a23b8faf840d
parentd8647f2d3c381a6f543358710eb07dafa7070854 (diff)
xprtrdma: Properly handle RDMA_ERROR replies
These are shorter than RPCRDMA_HDRLEN_MIN, and they need to complete the waiting RPC. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Sagi Grimberg <sagig@mellanox.com> Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r--include/linux/sunrpc/rpc_rdma.h11
-rw-r--r--net/sunrpc/xprtrdma/rpc_rdma.c51
2 files changed, 49 insertions, 13 deletions
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h
index 8c6d23cb0cae..3b1ff38f0c37 100644
--- a/include/linux/sunrpc/rpc_rdma.h
+++ b/include/linux/sunrpc/rpc_rdma.h
@@ -93,6 +93,12 @@ struct rpcrdma_msg {
93 __be32 rm_pempty[3]; /* 3 empty chunk lists */ 93 __be32 rm_pempty[3]; /* 3 empty chunk lists */
94 } rm_padded; 94 } rm_padded;
95 95
96 struct {
97 __be32 rm_err;
98 __be32 rm_vers_low;
99 __be32 rm_vers_high;
100 } rm_error;
101
96 __be32 rm_chunks[0]; /* read, write and reply chunks */ 102 __be32 rm_chunks[0]; /* read, write and reply chunks */
97 103
98 } rm_body; 104 } rm_body;
@@ -109,11 +115,6 @@ enum rpcrdma_errcode {
109 ERR_CHUNK = 2 115 ERR_CHUNK = 2
110}; 116};
111 117
112struct rpcrdma_err_vers {
113 uint32_t rdma_vers_low; /* Version range supported by peer */
114 uint32_t rdma_vers_high;
115};
116
117enum rpcrdma_proc { 118enum rpcrdma_proc {
118 RDMA_MSG = 0, /* An RPC call or reply msg */ 119 RDMA_MSG = 0, /* An RPC call or reply msg */
119 RDMA_NOMSG = 1, /* An RPC call or reply msg - separate body */ 120 RDMA_NOMSG = 1, /* An RPC call or reply msg - separate body */
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c
index 060739144552..35f810899729 100644
--- a/net/sunrpc/xprtrdma/rpc_rdma.c
+++ b/net/sunrpc/xprtrdma/rpc_rdma.c
@@ -795,7 +795,7 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
795 struct rpcrdma_xprt *r_xprt = rep->rr_rxprt; 795 struct rpcrdma_xprt *r_xprt = rep->rr_rxprt;
796 struct rpc_xprt *xprt = &r_xprt->rx_xprt; 796 struct rpc_xprt *xprt = &r_xprt->rx_xprt;
797 __be32 *iptr; 797 __be32 *iptr;
798 int rdmalen, status; 798 int rdmalen, status, rmerr;
799 unsigned long cwnd; 799 unsigned long cwnd;
800 u32 credits; 800 u32 credits;
801 801
@@ -803,12 +803,10 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
803 803
804 if (rep->rr_len == RPCRDMA_BAD_LEN) 804 if (rep->rr_len == RPCRDMA_BAD_LEN)
805 goto out_badstatus; 805 goto out_badstatus;
806 if (rep->rr_len < RPCRDMA_HDRLEN_MIN) 806 if (rep->rr_len < RPCRDMA_HDRLEN_ERR)
807 goto out_shortreply; 807 goto out_shortreply;
808 808
809 headerp = rdmab_to_msg(rep->rr_rdmabuf); 809 headerp = rdmab_to_msg(rep->rr_rdmabuf);
810 if (headerp->rm_vers != rpcrdma_version)
811 goto out_badversion;
812#if defined(CONFIG_SUNRPC_BACKCHANNEL) 810#if defined(CONFIG_SUNRPC_BACKCHANNEL)
813 if (rpcrdma_is_bcall(headerp)) 811 if (rpcrdma_is_bcall(headerp))
814 goto out_bcall; 812 goto out_bcall;
@@ -838,6 +836,9 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
838 req->rl_reply = rep; 836 req->rl_reply = rep;
839 xprt->reestablish_timeout = 0; 837 xprt->reestablish_timeout = 0;
840 838
839 if (headerp->rm_vers != rpcrdma_version)
840 goto out_badversion;
841
841 /* check for expected message types */ 842 /* check for expected message types */
842 /* The order of some of these tests is important. */ 843 /* The order of some of these tests is important. */
843 switch (headerp->rm_type) { 844 switch (headerp->rm_type) {
@@ -898,6 +899,9 @@ rpcrdma_reply_handler(struct rpcrdma_rep *rep)
898 status = rdmalen; 899 status = rdmalen;
899 break; 900 break;
900 901
902 case rdma_error:
903 goto out_rdmaerr;
904
901badheader: 905badheader:
902 default: 906 default:
903 dprintk("%s: invalid rpcrdma reply header (type %d):" 907 dprintk("%s: invalid rpcrdma reply header (type %d):"
@@ -913,6 +917,7 @@ badheader:
913 break; 917 break;
914 } 918 }
915 919
920out:
916 /* Invalidate and flush the data payloads before waking the 921 /* Invalidate and flush the data payloads before waking the
917 * waiting application. This guarantees the memory region is 922 * waiting application. This guarantees the memory region is
918 * properly fenced from the server before the application 923 * properly fenced from the server before the application
@@ -955,13 +960,43 @@ out_bcall:
955 return; 960 return;
956#endif 961#endif
957 962
958out_shortreply: 963/* If the incoming reply terminated a pending RPC, the next
959 dprintk("RPC: %s: short/invalid reply\n", __func__); 964 * RPC call will post a replacement receive buffer as it is
960 goto repost; 965 * being marshaled.
961 966 */
962out_badversion: 967out_badversion:
963 dprintk("RPC: %s: invalid version %d\n", 968 dprintk("RPC: %s: invalid version %d\n",
964 __func__, be32_to_cpu(headerp->rm_vers)); 969 __func__, be32_to_cpu(headerp->rm_vers));
970 status = -EIO;
971 r_xprt->rx_stats.bad_reply_count++;
972 goto out;
973
974out_rdmaerr:
975 rmerr = be32_to_cpu(headerp->rm_body.rm_error.rm_err);
976 switch (rmerr) {
977 case ERR_VERS:
978 pr_err("%s: server reports header version error (%u-%u)\n",
979 __func__,
980 be32_to_cpu(headerp->rm_body.rm_error.rm_vers_low),
981 be32_to_cpu(headerp->rm_body.rm_error.rm_vers_high));
982 break;
983 case ERR_CHUNK:
984 pr_err("%s: server reports header decoding error\n",
985 __func__);
986 break;
987 default:
988 pr_err("%s: server reports unknown error %d\n",
989 __func__, rmerr);
990 }
991 status = -EREMOTEIO;
992 r_xprt->rx_stats.bad_reply_count++;
993 goto out;
994
995/* If no pending RPC transaction was matched, post a replacement
996 * receive buffer before returning.
997 */
998out_shortreply:
999 dprintk("RPC: %s: short/invalid reply\n", __func__);
965 goto repost; 1000 goto repost;
966 1001
967out_nomatch: 1002out_nomatch: