aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_marshal.c55
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c4
2 files changed, 46 insertions, 13 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
index b9ce01f6af90..765bca47c74d 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
@@ -148,22 +148,41 @@ static __be32 *decode_reply_array(__be32 *va, __be32 *vaend)
148int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp) 148int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp)
149{ 149{
150 __be32 *va, *vaend; 150 __be32 *va, *vaend;
151 unsigned int len;
151 u32 hdr_len; 152 u32 hdr_len;
152 153
153 /* Verify that there's enough bytes for header + something */ 154 /* Verify that there's enough bytes for header + something */
154 if (rqstp->rq_arg.len <= RPCRDMA_HDRLEN_MIN) { 155 if (rqstp->rq_arg.len <= RPCRDMA_HDRLEN_ERR) {
155 dprintk("svcrdma: header too short = %d\n", 156 dprintk("svcrdma: header too short = %d\n",
156 rqstp->rq_arg.len); 157 rqstp->rq_arg.len);
157 return -EINVAL; 158 return -EINVAL;
158 } 159 }
159 160
160 if (rmsgp->rm_vers != rpcrdma_version) 161 if (rmsgp->rm_vers != rpcrdma_version) {
162 dprintk("%s: bad version %u\n", __func__,
163 be32_to_cpu(rmsgp->rm_vers));
161 return -EPROTONOSUPPORT; 164 return -EPROTONOSUPPORT;
165 }
162 166
163 /* Pull in the extra for the padded case and bump our pointer */ 167 switch (be32_to_cpu(rmsgp->rm_type)) {
164 if (rmsgp->rm_type == rdma_msgp) { 168 case RDMA_MSG:
165 int hdrlen; 169 case RDMA_NOMSG:
166 170 break;
171
172 case RDMA_DONE:
173 /* Just drop it */
174 dprintk("svcrdma: dropping RDMA_DONE message\n");
175 return 0;
176
177 case RDMA_ERROR:
178 /* Possible if this is a backchannel reply.
179 * XXX: We should cancel this XID, though.
180 */
181 dprintk("svcrdma: dropping RDMA_ERROR message\n");
182 return 0;
183
184 case RDMA_MSGP:
185 /* Pull in the extra for the padded case, bump our pointer */
167 rmsgp->rm_body.rm_padded.rm_align = 186 rmsgp->rm_body.rm_padded.rm_align =
168 be32_to_cpu(rmsgp->rm_body.rm_padded.rm_align); 187 be32_to_cpu(rmsgp->rm_body.rm_padded.rm_align);
169 rmsgp->rm_body.rm_padded.rm_thresh = 188 rmsgp->rm_body.rm_padded.rm_thresh =
@@ -171,11 +190,15 @@ int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp)
171 190
172 va = &rmsgp->rm_body.rm_padded.rm_pempty[4]; 191 va = &rmsgp->rm_body.rm_padded.rm_pempty[4];
173 rqstp->rq_arg.head[0].iov_base = va; 192 rqstp->rq_arg.head[0].iov_base = va;
174 hdrlen = (u32)((unsigned long)va - (unsigned long)rmsgp); 193 len = (u32)((unsigned long)va - (unsigned long)rmsgp);
175 rqstp->rq_arg.head[0].iov_len -= hdrlen; 194 rqstp->rq_arg.head[0].iov_len -= len;
176 if (hdrlen > rqstp->rq_arg.len) 195 if (len > rqstp->rq_arg.len)
177 return -EINVAL; 196 return -EINVAL;
178 return hdrlen; 197 return len;
198 default:
199 dprintk("svcrdma: bad rdma procedure (%u)\n",
200 be32_to_cpu(rmsgp->rm_type));
201 return -EINVAL;
179 } 202 }
180 203
181 /* The chunk list may contain either a read chunk list or a write 204 /* The chunk list may contain either a read chunk list or a write
@@ -184,14 +207,20 @@ int svc_rdma_xdr_decode_req(struct rpcrdma_msg *rmsgp, struct svc_rqst *rqstp)
184 va = &rmsgp->rm_body.rm_chunks[0]; 207 va = &rmsgp->rm_body.rm_chunks[0];
185 vaend = (__be32 *)((unsigned long)rmsgp + rqstp->rq_arg.len); 208 vaend = (__be32 *)((unsigned long)rmsgp + rqstp->rq_arg.len);
186 va = decode_read_list(va, vaend); 209 va = decode_read_list(va, vaend);
187 if (!va) 210 if (!va) {
211 dprintk("svcrdma: failed to decode read list\n");
188 return -EINVAL; 212 return -EINVAL;
213 }
189 va = decode_write_list(va, vaend); 214 va = decode_write_list(va, vaend);
190 if (!va) 215 if (!va) {
216 dprintk("svcrdma: failed to decode write list\n");
191 return -EINVAL; 217 return -EINVAL;
218 }
192 va = decode_reply_array(va, vaend); 219 va = decode_reply_array(va, vaend);
193 if (!va) 220 if (!va) {
221 dprintk("svcrdma: failed to decode reply chunk\n");
194 return -EINVAL; 222 return -EINVAL;
223 }
195 224
196 rqstp->rq_arg.head[0].iov_base = va; 225 rqstp->rq_arg.head[0].iov_base = va;
197 hdr_len = (unsigned long)va - (unsigned long)rmsgp; 226 hdr_len = (unsigned long)va - (unsigned long)rmsgp;
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 8f68cb6d89fe..f8b840b17c02 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -657,6 +657,8 @@ int svc_rdma_recvfrom(struct svc_rqst *rqstp)
657 ret = svc_rdma_xdr_decode_req(rmsgp, rqstp); 657 ret = svc_rdma_xdr_decode_req(rmsgp, rqstp);
658 if (ret < 0) 658 if (ret < 0)
659 goto out_err; 659 goto out_err;
660 if (ret == 0)
661 goto out_drop;
660 rqstp->rq_xprt_hlen = ret; 662 rqstp->rq_xprt_hlen = ret;
661 663
662 if (svc_rdma_is_backchannel_reply(xprt, rmsgp)) { 664 if (svc_rdma_is_backchannel_reply(xprt, rmsgp)) {
@@ -710,6 +712,8 @@ out_err:
710defer: 712defer:
711 return 0; 713 return 0;
712 714
715out_drop:
716 svc_rdma_put_context(ctxt, 1);
713repost: 717repost:
714 return svc_rdma_repost_recv(rdma_xprt, GFP_KERNEL); 718 return svc_rdma_repost_recv(rdma_xprt, GFP_KERNEL);
715} 719}