aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2015-01-13 11:03:28 -0500
committerJ. Bruce Fields <bfields@redhat.com>2015-01-15 15:01:47 -0500
commit61edbcb7c7f4efb65df4ad793d007237f9fa311f (patch)
treefc0bc3b1ff1b5f1ad72bda0f4165faecb418c1e7 /net
parente54524111f51eac1900cf91aca3d38a92a6b11c0 (diff)
svcrdma: rc_position sanity checking
An RPC/RDMA client may send large RPC arguments via a read list. This is a list of scatter/gather elements which convey RPC call arguments too large to fit in a small RDMA SEND. Each entry in the read list has a "position" field, whose value is the byte offset in the XDR stream where the data in that entry is to be inserted. Entries which share the same "position" value make up the same RPC argument. The receiver inserts entries with the same position field value in list order into the XDR stream. Currently the Linux NFS/RDMA server cannot handle receiving read chunks in more than one position, mostly because no current client sends read lists with elements in more than one position. As a sanity check, ensure that all received chunks have the same "rc_position." Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Steve Wise <swise@opengridcomputing.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index c3aebc1bf0a6..a67dd1a081dd 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -365,6 +365,7 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
365 int page_no, ret; 365 int page_no, ret;
366 struct rpcrdma_read_chunk *ch; 366 struct rpcrdma_read_chunk *ch;
367 u32 handle, page_offset, byte_count; 367 u32 handle, page_offset, byte_count;
368 u32 position;
368 u64 rs_offset; 369 u64 rs_offset;
369 bool last; 370 bool last;
370 371
@@ -389,10 +390,17 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
389 head->arg.len = rqstp->rq_arg.len; 390 head->arg.len = rqstp->rq_arg.len;
390 head->arg.buflen = rqstp->rq_arg.buflen; 391 head->arg.buflen = rqstp->rq_arg.buflen;
391 392
392 page_no = 0; page_offset = 0; 393 ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
393 for (ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; 394 position = be32_to_cpu(ch->rc_position);
394 ch->rc_discrim != 0; ch++) { 395
395 handle = be32_to_cpu(ch->rc_target.rs_handle); 396 ret = 0;
397 page_no = 0;
398 page_offset = 0;
399 for (; ch->rc_discrim != xdr_zero; ch++) {
400 if (be32_to_cpu(ch->rc_position) != position)
401 goto err;
402
403 handle = be32_to_cpu(ch->rc_target.rs_handle),
396 byte_count = be32_to_cpu(ch->rc_target.rs_length); 404 byte_count = be32_to_cpu(ch->rc_target.rs_length);
397 xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset, 405 xdr_decode_hyper((__be32 *)&ch->rc_target.rs_offset,
398 &rs_offset); 406 &rs_offset);