diff options
author | Chuck Lever <chuck.lever@oracle.com> | 2017-02-07 11:58:15 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2017-02-08 14:41:24 -0500 |
commit | cbaf58032efca401834518b905f528ac912449e4 (patch) | |
tree | b1d3b67f20557bc45115931fff8df5aad433f799 | |
parent | b880092109323d1cc608c420fa712d3e19508e13 (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.h | 9 | ||||
-rw-r--r-- | include/linux/sunrpc/svc_rdma.h | 2 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_marshal.c | 49 | ||||
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_sendto.c | 3 |
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 | */ | ||
115 | enum { | ||
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); |
221 | extern int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *); | 221 | extern unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp); |
222 | 222 | ||
223 | /* svc_rdma_recvfrom.c */ | 223 | /* svc_rdma_recvfrom.c */ |
224 | extern int svc_rdma_recvfrom(struct svc_rqst *); | 224 | extern 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 | ||
263 | int 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 | */ | ||
269 | unsigned 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 | ||
291 | void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *rmsgp, int chunks) | 294 | void 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); |