diff options
Diffstat (limited to 'net/sunrpc/xprtrdma/svc_rdma_recvfrom.c')
-rw-r--r-- | net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | 39 |
1 files changed, 36 insertions, 3 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index a67dd1a081dd..36cf51a3eab7 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -60,6 +60,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp, | |||
60 | struct svc_rdma_op_ctxt *ctxt, | 60 | struct svc_rdma_op_ctxt *ctxt, |
61 | u32 byte_count) | 61 | u32 byte_count) |
62 | { | 62 | { |
63 | struct rpcrdma_msg *rmsgp; | ||
63 | struct page *page; | 64 | struct page *page; |
64 | u32 bc; | 65 | u32 bc; |
65 | int sge_no; | 66 | int sge_no; |
@@ -82,7 +83,14 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp, | |||
82 | /* If data remains, store it in the pagelist */ | 83 | /* If data remains, store it in the pagelist */ |
83 | rqstp->rq_arg.page_len = bc; | 84 | rqstp->rq_arg.page_len = bc; |
84 | rqstp->rq_arg.page_base = 0; | 85 | rqstp->rq_arg.page_base = 0; |
85 | rqstp->rq_arg.pages = &rqstp->rq_pages[1]; | 86 | |
87 | /* RDMA_NOMSG: RDMA READ data should land just after RDMA RECV data */ | ||
88 | rmsgp = (struct rpcrdma_msg *)rqstp->rq_arg.head[0].iov_base; | ||
89 | if (be32_to_cpu(rmsgp->rm_type) == RDMA_NOMSG) | ||
90 | rqstp->rq_arg.pages = &rqstp->rq_pages[0]; | ||
91 | else | ||
92 | rqstp->rq_arg.pages = &rqstp->rq_pages[1]; | ||
93 | |||
86 | sge_no = 1; | 94 | sge_no = 1; |
87 | while (bc && sge_no < ctxt->count) { | 95 | while (bc && sge_no < ctxt->count) { |
88 | page = ctxt->pages[sge_no]; | 96 | page = ctxt->pages[sge_no]; |
@@ -383,7 +391,6 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, | |||
383 | */ | 391 | */ |
384 | head->arg.head[0] = rqstp->rq_arg.head[0]; | 392 | head->arg.head[0] = rqstp->rq_arg.head[0]; |
385 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; | 393 | head->arg.tail[0] = rqstp->rq_arg.tail[0]; |
386 | head->arg.pages = &head->pages[head->count]; | ||
387 | head->hdr_count = head->count; | 394 | head->hdr_count = head->count; |
388 | head->arg.page_base = 0; | 395 | head->arg.page_base = 0; |
389 | head->arg.page_len = 0; | 396 | head->arg.page_len = 0; |
@@ -393,9 +400,17 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, | |||
393 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; | 400 | ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0]; |
394 | position = be32_to_cpu(ch->rc_position); | 401 | position = be32_to_cpu(ch->rc_position); |
395 | 402 | ||
403 | /* RDMA_NOMSG: RDMA READ data should land just after RDMA RECV data */ | ||
404 | if (position == 0) { | ||
405 | head->arg.pages = &head->pages[0]; | ||
406 | page_offset = head->byte_len; | ||
407 | } else { | ||
408 | head->arg.pages = &head->pages[head->count]; | ||
409 | page_offset = 0; | ||
410 | } | ||
411 | |||
396 | ret = 0; | 412 | ret = 0; |
397 | page_no = 0; | 413 | page_no = 0; |
398 | page_offset = 0; | ||
399 | for (; ch->rc_discrim != xdr_zero; ch++) { | 414 | for (; ch->rc_discrim != xdr_zero; ch++) { |
400 | if (be32_to_cpu(ch->rc_position) != position) | 415 | if (be32_to_cpu(ch->rc_position) != position) |
401 | goto err; | 416 | goto err; |
@@ -418,7 +433,10 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, | |||
418 | head->arg.buflen += ret; | 433 | head->arg.buflen += ret; |
419 | } | 434 | } |
420 | } | 435 | } |
436 | |||
421 | ret = 1; | 437 | ret = 1; |
438 | head->position = position; | ||
439 | |||
422 | err: | 440 | err: |
423 | /* Detach arg pages. svc_recv will replenish them */ | 441 | /* Detach arg pages. svc_recv will replenish them */ |
424 | for (page_no = 0; | 442 | for (page_no = 0; |
@@ -465,6 +483,21 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
465 | put_page(rqstp->rq_pages[page_no]); | 483 | put_page(rqstp->rq_pages[page_no]); |
466 | rqstp->rq_pages[page_no] = head->pages[page_no]; | 484 | rqstp->rq_pages[page_no] = head->pages[page_no]; |
467 | } | 485 | } |
486 | |||
487 | /* Adjustments made for RDMA_NOMSG type requests */ | ||
488 | if (head->position == 0) { | ||
489 | if (head->arg.len <= head->sge[0].length) { | ||
490 | head->arg.head[0].iov_len = head->arg.len - | ||
491 | head->byte_len; | ||
492 | head->arg.page_len = 0; | ||
493 | } else { | ||
494 | head->arg.head[0].iov_len = head->sge[0].length - | ||
495 | head->byte_len; | ||
496 | head->arg.page_len = head->arg.len - | ||
497 | head->sge[0].length; | ||
498 | } | ||
499 | } | ||
500 | |||
468 | /* Point rq_arg.pages past header */ | 501 | /* Point rq_arg.pages past header */ |
469 | rdma_fix_xdr_pad(&head->arg); | 502 | rdma_fix_xdr_pad(&head->arg); |
470 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; | 503 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; |