aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChuck Lever <chuck.lever@oracle.com>2014-07-22 16:00:40 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-07-22 16:40:21 -0400
commite560e3b510d22e06081a72a4d49e559b9e392659 (patch)
tree9c6369050d01080f73c94ec41443b7ce17ad213c
parentd55a166c961714e18907f4723252f72097cd2d23 (diff)
svcrdma: Add zero padding if the client doesn't send it
See RFC 5666 section 3.7: clients don't have to send zero XDR padding. BugLink: https://bugzilla.linux-nfs.org/show_bug.cgi?id=246 Signed-off-by: Chuck Lever <chuck.lever@oracle.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
-rw-r--r--net/sunrpc/xprtrdma/svc_rdma_recvfrom.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
index 8f92a61ee2df..e0110270d650 100644
--- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
+++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c
@@ -43,6 +43,7 @@
43#include <linux/sunrpc/debug.h> 43#include <linux/sunrpc/debug.h>
44#include <linux/sunrpc/rpc_rdma.h> 44#include <linux/sunrpc/rpc_rdma.h>
45#include <linux/spinlock.h> 45#include <linux/spinlock.h>
46#include <linux/highmem.h>
46#include <asm/unaligned.h> 47#include <asm/unaligned.h>
47#include <rdma/ib_verbs.h> 48#include <rdma/ib_verbs.h>
48#include <rdma/rdma_cm.h> 49#include <rdma/rdma_cm.h>
@@ -435,6 +436,32 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt,
435 return ret; 436 return ret;
436} 437}
437 438
439/*
440 * To avoid a separate RDMA READ just for a handful of zero bytes,
441 * RFC 5666 section 3.7 allows the client to omit the XDR zero pad
442 * in chunk lists.
443 */
444static void
445rdma_fix_xdr_pad(struct xdr_buf *buf)
446{
447 unsigned int page_len = buf->page_len;
448 unsigned int size = (XDR_QUADLEN(page_len) << 2) - page_len;
449 unsigned int offset, pg_no;
450 char *p;
451
452 if (size == 0)
453 return;
454
455 pg_no = page_len >> PAGE_SHIFT;
456 offset = page_len & ~PAGE_MASK;
457 p = page_address(buf->pages[pg_no]);
458 memset(p + offset, 0, size);
459
460 buf->page_len += size;
461 buf->buflen += size;
462 buf->len += size;
463}
464
438static int rdma_read_complete(struct svc_rqst *rqstp, 465static int rdma_read_complete(struct svc_rqst *rqstp,
439 struct svc_rdma_op_ctxt *head) 466 struct svc_rdma_op_ctxt *head)
440{ 467{
@@ -449,6 +476,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp,
449 rqstp->rq_pages[page_no] = head->pages[page_no]; 476 rqstp->rq_pages[page_no] = head->pages[page_no];
450 } 477 }
451 /* Point rq_arg.pages past header */ 478 /* Point rq_arg.pages past header */
479 rdma_fix_xdr_pad(&head->arg);
452 rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; 480 rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count];
453 rqstp->rq_arg.page_len = head->arg.page_len; 481 rqstp->rq_arg.page_len = head->arg.page_len;
454 rqstp->rq_arg.page_base = head->arg.page_base; 482 rqstp->rq_arg.page_base = head->arg.page_base;