Skip to content

Commit 0b056c2

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
svcrdma: Support RDMA_NOMSG requests
Currently the Linux server can not decode RDMA_NOMSG type requests. Operations whose length exceeds the fixed size of RDMA SEND buffers, like large NFSv4 CREATE(NF4LNK) operations, must be conveyed via RDMA_NOMSG. For an RDMA_MSG type request, the client sends the RPC/RDMA, RPC headers, and some or all of the NFS arguments via RDMA SEND. For an RDMA_NOMSG type request, the client sends just the RPC/RDMA header via RDMA SEND. The request's read list contains elements for the entire RPC message, including the RPC header. NFSD expects the RPC/RMDA header and RPC header to be contiguous in page zero of the XDR buffer. Add logic in the RDMA READ path to make the read list contents land where the server prefers, when the incoming message is a type RDMA_NOMSG message. Signed-off-by: Chuck Lever <[email protected]> Reviewed-by: Steve Wise <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent 61edbcb commit 0b056c2

File tree

2 files changed

+37
-3
lines changed

2 files changed

+37
-3
lines changed

include/linux/sunrpc/svc_rdma.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ struct svc_rdma_op_ctxt {
7979
enum ib_wr_opcode wr_op;
8080
enum ib_wc_status wc_status;
8181
u32 byte_len;
82+
u32 position;
8283
struct svcxprt_rdma *xprt;
8384
unsigned long flags;
8485
enum dma_data_direction direction;

net/sunrpc/xprtrdma/svc_rdma_recvfrom.c

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp,
6060
struct svc_rdma_op_ctxt *ctxt,
6161
u32 byte_count)
6262
{
63+
struct rpcrdma_msg *rmsgp;
6364
struct page *page;
6465
u32 bc;
6566
int sge_no;
@@ -82,7 +83,14 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp,
8283
/* If data remains, store it in the pagelist */
8384
rqstp->rq_arg.page_len = bc;
8485
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+
8694
sge_no = 1;
8795
while (bc && sge_no < ctxt->count) {
8896
page = ctxt->pages[sge_no];
@@ -383,7 +391,6 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
383391
*/
384392
head->arg.head[0] = rqstp->rq_arg.head[0];
385393
head->arg.tail[0] = rqstp->rq_arg.tail[0];
386-
head->arg.pages = &head->pages[head->count];
387394
head->hdr_count = head->count;
388395
head->arg.page_base = 0;
389396
head->arg.page_len = 0;
@@ -393,9 +400,17 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
393400
ch = (struct rpcrdma_read_chunk *)&rmsgp->rm_body.rm_chunks[0];
394401
position = be32_to_cpu(ch->rc_position);
395402

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+
396412
ret = 0;
397413
page_no = 0;
398-
page_offset = 0;
399414
for (; ch->rc_discrim != xdr_zero; ch++) {
400415
if (be32_to_cpu(ch->rc_position) != position)
401416
goto err;
@@ -418,7 +433,10 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
418433
head->arg.buflen += ret;
419434
}
420435
}
436+
421437
ret = 1;
438+
head->position = position;
439+
422440
err:
423441
/* Detach arg pages. svc_recv will replenish them */
424442
for (page_no = 0;
@@ -465,6 +483,21 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
465483
put_page(rqstp->rq_pages[page_no]);
466484
rqstp->rq_pages[page_no] = head->pages[page_no];
467485
}
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+
468501
/* Point rq_arg.pages past header */
469502
rdma_fix_xdr_pad(&head->arg);
470503
rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count];

0 commit comments

Comments
 (0)