svcrdma: Another sendto chunk list parsing update
Commit 5fdca65314
("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>
This commit is contained in:
parent
b880092109
commit
cbaf58032e
|
@ -109,6 +109,15 @@ struct rpcrdma_msg {
|
|||
} rm_body;
|
||||
};
|
||||
|
||||
/*
|
||||
* XDR sizes, in quads
|
||||
*/
|
||||
enum {
|
||||
rpcrdma_fixed_maxsz = 4,
|
||||
rpcrdma_segment_maxsz = 4,
|
||||
rpcrdma_readchunk_maxsz = 2 + rpcrdma_segment_maxsz,
|
||||
};
|
||||
|
||||
/*
|
||||
* Smallest RPC/RDMA header: rm_xid through rm_type, then rm_nochunks
|
||||
*/
|
||||
|
|
|
@ -218,7 +218,7 @@ extern void svc_rdma_xdr_encode_reply_header(struct svcxprt_rdma *,
|
|||
struct rpcrdma_msg *,
|
||||
struct rpcrdma_msg *,
|
||||
enum rpcrdma_proc);
|
||||
extern int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *);
|
||||
extern unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp);
|
||||
|
||||
/* svc_rdma_recvfrom.c */
|
||||
extern int svc_rdma_recvfrom(struct svc_rqst *);
|
||||
|
|
|
@ -260,32 +260,35 @@ int svc_rdma_xdr_encode_error(struct svcxprt_rdma *xprt,
|
|||
return (int)((unsigned long)va - (unsigned long)startp);
|
||||
}
|
||||
|
||||
int svc_rdma_xdr_get_reply_hdr_len(struct rpcrdma_msg *rmsgp)
|
||||
/**
|
||||
* svc_rdma_xdr_get_reply_hdr_length - Get length of Reply transport header
|
||||
* @rdma_resp: buffer containing Reply transport header
|
||||
*
|
||||
* Returns length of transport header, in bytes.
|
||||
*/
|
||||
unsigned int svc_rdma_xdr_get_reply_hdr_len(__be32 *rdma_resp)
|
||||
{
|
||||
struct rpcrdma_write_array *wr_ary;
|
||||
unsigned int nsegs;
|
||||
__be32 *p;
|
||||
|
||||
/* There is no read-list in a reply */
|
||||
p = rdma_resp;
|
||||
|
||||
/* skip write list */
|
||||
wr_ary = (struct rpcrdma_write_array *)
|
||||
&rmsgp->rm_body.rm_chunks[1];
|
||||
if (wr_ary->wc_discrim)
|
||||
wr_ary = (struct rpcrdma_write_array *)
|
||||
&wr_ary->wc_array[be32_to_cpu(wr_ary->wc_nchunks)].
|
||||
wc_target.rs_length;
|
||||
else
|
||||
wr_ary = (struct rpcrdma_write_array *)
|
||||
&wr_ary->wc_nchunks;
|
||||
/* RPC-over-RDMA V1 replies never have a Read list. */
|
||||
p += rpcrdma_fixed_maxsz + 1;
|
||||
|
||||
/* skip reply array */
|
||||
if (wr_ary->wc_discrim)
|
||||
wr_ary = (struct rpcrdma_write_array *)
|
||||
&wr_ary->wc_array[be32_to_cpu(wr_ary->wc_nchunks)];
|
||||
else
|
||||
wr_ary = (struct rpcrdma_write_array *)
|
||||
&wr_ary->wc_nchunks;
|
||||
/* Skip Write list. */
|
||||
while (*p++ != xdr_zero) {
|
||||
nsegs = be32_to_cpup(p++);
|
||||
p += nsegs * rpcrdma_segment_maxsz;
|
||||
}
|
||||
|
||||
return (unsigned long) wr_ary - (unsigned long) rmsgp;
|
||||
/* Skip Reply chunk. */
|
||||
if (*p++ != xdr_zero) {
|
||||
nsegs = be32_to_cpup(p++);
|
||||
p += nsegs * rpcrdma_segment_maxsz;
|
||||
}
|
||||
|
||||
return (unsigned long)p - (unsigned long)rdma_resp;
|
||||
}
|
||||
|
||||
void svc_rdma_xdr_encode_write_list(struct rpcrdma_msg *rmsgp, int chunks)
|
||||
|
|
|
@ -476,7 +476,8 @@ static int send_reply(struct svcxprt_rdma *rdma,
|
|||
|
||||
/* Prepare the SGE for the RPCRDMA Header */
|
||||
ctxt->sge[0].lkey = rdma->sc_pd->local_dma_lkey;
|
||||
ctxt->sge[0].length = svc_rdma_xdr_get_reply_hdr_len(rdma_resp);
|
||||
ctxt->sge[0].length =
|
||||
svc_rdma_xdr_get_reply_hdr_len((__be32 *)rdma_resp);
|
||||
ctxt->sge[0].addr =
|
||||
ib_dma_map_page(rdma->sc_cm_id->device, page, 0,
|
||||
ctxt->sge[0].length, DMA_TO_DEVICE);
|
||||
|
|
Loading…
Reference in a new issue