aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2017-02-07 11:58:15 -0500
committerJ. Bruce Fields <bfields@redhat.com>2017-02-08 14:41:24 -0500
commitcbaf58032efca401834518b905f528ac912449e4 (patch)
treeb1d3b67f20557bc45115931fff8df5aad433f799
parentb880092109323d1cc608c420fa712d3e19508e13 (diff)
svcrdma: Another sendto chunk list parsing update
Commit 5fdca6531434 ("svcrdma: Renovate sendto chunk list parsing") missed a spot. svc_rdma_xdr_get_reply_hdr_len() also assumes the Write list has only one Write chunk. There's no harm in making this code more general. Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--include/linux/sunrpc/rpc_rdma.h9
-rw-r--r--include/linux/sunrpc/svc_rdma.h2
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_marshal.c49
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_sendto.c3
4 files changed, 38 insertions, 25 deletions
diff --git a/include/linux/sunrpc/rpc_rdma.h b/include/linux/sunrpc/rpc_rdma.h
index cfda6adcf33c..245fc59b7324 100644
--- a/include/linux/sunrpc/rpc_rdma.h
+++ b/include/linux/sunrpc/rpc_rdma.h
@@ -110,6 +110,15 @@ struct rpcrdma_msg {
110}; 110};
111 111
112/* 112/*
113 * XDR sizes, in quads
114 */
115enum {
116 rpcrdma_fixed_maxsz = 4,
117 rpcrdma_segment_maxsz = 4,
118 rpcrdma_readchunk_maxsz = 2 + rpcrdma_segment_maxsz,
119};
120
121/*
113 * Smallest RPC/RDMA header: rm_xid through rm_type, then rm_nochunks 122 * Smallest RPC/RDMA header: rm_xid through rm_type, then rm_nochunks
114 */ 123 */
115#define RPCRDMA_HDRLEN_MIN (sizeof(__be32) * 7) 124#define RPCRDMA_HDRLEN_MIN (sizeof(__be32) * 7)
diff --git a/include/linux/sunrpc/svc_rdma.h b/include/linux/sunrpc/svc_rdma.h
index 757fb963696c..551c51816352 100644
--- a/include/linux/sunrpc/svc_rdma.h
+++ b/include/linux/sunrpc/svc_rdma.h
@@ -218,7 +218,7 @@ extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *,
218 struct rpcrdma_msg *, 218 struct rpcrdma_msg *,
219 struct rpcrdma_msg *, 219 struct rpcrdma_msg *,
220 enum rpcrdma_proc); 220 enum rpcrdma_proc);
221extern int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *); 221extern unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp);
222 222
223/* svc_rdma_recvfrom.c */ 223/* svc_rdma_recvfrom.c */
224extern int svc_rdma_recvfrom(struct svc_rqst *); 224extern int svc_rdma_recvfrom(struct svc_rqst *);
diff --git a/net/sunrpc/xprtrdma/svc_rdma_marshal.c b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
index 0ba9887f3e22..4e7203439e2f 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_marshal.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_marshal.c
@@ -260,32 +260,35 @@ int svc_rdma_xdr_encode_error(struct svcxprt_rdma *xprt,
260 return (int)((unsigned long)va - (unsigned long)startp); 260 return (int)((unsigned long)va - (unsigned long)startp);
261} 261}
262 262
263int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *rmsgp) 263/**
264 * svc_rdma_xdr_get_reply_hdr_length - Get length of Reply transport header
265 * @rdma_resp: buffer containing Reply transport header
266 *
267 * Returns length of transport header, in bytes.
268 */
269unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp)
264{ 270{
265 struct rpcrdma_write_array *wr_ary; 271 unsigned int nsegs;
272 __be32 *p;
266 273
267 /* There is no read-list in a reply */ 274 p = rdma_resp;
268 275
269 /* skip write list */ 276 /* RPC-over-RDMA V1 replies never have a Read list. */
270 wr_ary = (struct rpcrdma_write_array *) 277 p += rpcrdma_fixed_maxsz + 1;
271 &rmsgp->rm_body.rm_chunks[1]; 278
272 if (wr_ary->wc_discrim) 279 /* Skip Write list. */
273 wr_ary = (struct rpcrdma_write_array *) 280 while (*p++ != xdr_zero) {
274 &wr_ary->wc_array[be32_to_cpu(wr_ary->wc_nchunks)]. 281 nsegs = be32_to_cpup(p++);
275 wc_target.rs_length; 282 p += nsegs * rpcrdma_segment_maxsz;
276 else 283 }
277 wr_ary = (struct rpcrdma_write_array *) 284
278 &wr_ary->wc_nchunks; 285 /* Skip Reply chunk. */
279 286 if (*p++ != xdr_zero) {
280 /* skip reply array */ 287 nsegs = be32_to_cpup(p++);
281 if (wr_ary->wc_discrim) 288 p += nsegs * rpcrdma_segment_maxsz;
282 wr_ary = (struct rpcrdma_write_array *) 289 }
283 &wr_ary->wc_array[be32_to_cpu(wr_ary->wc_nchunks)]; 290
284 else 291 return (unsigned long)p - (unsigned long)rdma_resp;
285 wr_ary = (struct rpcrdma_write_array *)
286 &wr_ary->wc_nchunks;
287
288 return (unsigned long) wr_ary - (unsigned long) rmsgp;
289} 292}
290 293
291void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *rmsgp, int chunks) 294void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *rmsgp, int chunks)
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
index ad4d286a83c5..ba76f1617965 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c
@@ -476,7 +476,8 @@ static int send_reply(struct svcxprt_rdma *rdma,
476 476
477 /* Prepare the SGE for the RPCRDMA Header */ 477 /* Prepare the SGE for the RPCRDMA Header */
478 ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey; 478 ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey;
479 ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp); 479 ctxt->sge[0].length =
480 svc_rdma_xdr_get_reply_hdr_len((__be32 *)rdma_resp);
480 ctxt->sge[0].addr = 481 ctxt->sge[0].addr =
481 ib_dma_map_page(rdma->sc_cm_id->device, page, 0, 482 ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
482 ctxt->sge[0].length, DMA_TO_DEVICE); 483 ctxt->sge[0].length, DMA_TO_DEVICE);