Skip to content

Commit 193bcb7

Browse files
chuckleverJ. Bruce Fields
authored andcommitted
svcrdma: Populate tail iovec when receiving
So that NFS WRITE payloads can eventually be placed directly into a file's page cache, enable the RPC-over-RDMA transport to present these payloads in the xdr_buf's page list, while placing trailing content (such as a GETATTR operation) in the xdr_buf's tail. After this change, the RPC-over-RDMA's "copy tail" hack, added by commit a97c331 ("svcrdma: Handle additional inline content"), is no longer needed and can be removed. Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: J. Bruce Fields <[email protected]>
1 parent eae03e2 commit 193bcb7

File tree

1 file changed

+15
-93
lines changed

1 file changed

+15
-93
lines changed

net/sunrpc/xprtrdma/svc_rdma_rw.c

Lines changed: 15 additions & 93 deletions
Original file line numberDiff line numberDiff line change
@@ -691,78 +691,6 @@ static int svc_rdma_build_read_chunk(struct svc_rqst *rqstp,
691691
return ret;
692692
}
693693

694-
/* If there is inline content following the Read chunk, append it to
695-
* the page list immediately following the data payload. This has to
696-
* be done after the reader function has determined how many pages
697-
* were consumed for RDMA Read.
698-
*
699-
* On entry, ri_pageno and ri_pageoff point directly to the end of the
700-
* page list. On exit, both have been updated to the new "next byte".
701-
*
702-
* Assumptions:
703-
* - Inline content fits entirely in rq_pages[0]
704-
* - Trailing content is only a handful of bytes
705-
*/
706-
static int svc_rdma_copy_tail(struct svc_rqst *rqstp,
707-
struct svc_rdma_read_info *info)
708-
{
709-
struct svc_rdma_op_ctxt *head = info->ri_readctxt;
710-
unsigned int tail_length, remaining;
711-
u8 *srcp, *destp;
712-
713-
/* Assert that all inline content fits in page 0. This is an
714-
* implementation limit, not a protocol limit.
715-
*/
716-
if (head->arg.head[0].iov_len > PAGE_SIZE) {
717-
pr_warn_once("svcrdma: too much trailing inline content\n");
718-
return -EINVAL;
719-
}
720-
721-
srcp = head->arg.head[0].iov_base;
722-
srcp += info->ri_position;
723-
tail_length = head->arg.head[0].iov_len - info->ri_position;
724-
remaining = tail_length;
725-
726-
/* If there is room on the last page in the page list, try to
727-
* fit the trailing content there.
728-
*/
729-
if (info->ri_pageoff > 0) {
730-
unsigned int len;
731-
732-
len = min_t(unsigned int, remaining,
733-
PAGE_SIZE - info->ri_pageoff);
734-
destp = page_address(rqstp->rq_pages[info->ri_pageno]);
735-
destp += info->ri_pageoff;
736-
737-
memcpy(destp, srcp, len);
738-
srcp += len;
739-
destp += len;
740-
info->ri_pageoff += len;
741-
remaining -= len;
742-
743-
if (info->ri_pageoff == PAGE_SIZE) {
744-
info->ri_pageno++;
745-
info->ri_pageoff = 0;
746-
}
747-
}
748-
749-
/* Otherwise, a fresh page is needed. */
750-
if (remaining) {
751-
head->arg.pages[info->ri_pageno] =
752-
rqstp->rq_pages[info->ri_pageno];
753-
head->count++;
754-
755-
destp = page_address(rqstp->rq_pages[info->ri_pageno]);
756-
memcpy(destp, srcp, remaining);
757-
info->ri_pageoff += remaining;
758-
}
759-
760-
head->arg.page_len += tail_length;
761-
head->arg.len += tail_length;
762-
head->arg.buflen += tail_length;
763-
return 0;
764-
}
765-
766694
/* Construct RDMA Reads to pull over a normal Read chunk. The chunk
767695
* data lands in the page list of head->arg.pages.
768696
*
@@ -787,34 +715,28 @@ static int svc_rdma_build_normal_read_chunk(struct svc_rqst *rqstp,
787715
if (ret < 0)
788716
goto out;
789717

790-
/* Read chunk may need XDR round-up (see RFC 5666, s. 3.7).
718+
/* Split the Receive buffer between the head and tail
719+
* buffers at Read chunk's position. XDR roundup of the
720+
* chunk is not included in either the pagelist or in
721+
* the tail.
791722
*/
792-
if (info->ri_chunklen & 3) {
793-
u32 padlen = 4 - (info->ri_chunklen & 3);
794-
795-
info->ri_chunklen += padlen;
723+
head->arg.tail[0].iov_base =
724+
head->arg.head[0].iov_base + info->ri_position;
725+
head->arg.tail[0].iov_len =
726+
head->arg.head[0].iov_len - info->ri_position;
727+
head->arg.head[0].iov_len = info->ri_position;
796728

797-
/* NB: data payload always starts on XDR alignment,
798-
* thus the pad can never contain a page boundary.
799-
*/
800-
info->ri_pageoff += padlen;
801-
if (info->ri_pageoff == PAGE_SIZE) {
802-
info->ri_pageno++;
803-
info->ri_pageoff = 0;
804-
}
805-
}
729+
/* Read chunk may need XDR roundup (see RFC 5666, s. 3.7).
730+
*
731+
* NFSv2/3 write decoders need the length of the tail to
732+
* contain the size of the roundup padding.
733+
*/
734+
head->arg.tail[0].iov_len += 4 - (info->ri_chunklen & 3);
806735

807736
head->arg.page_len = info->ri_chunklen;
808737
head->arg.len += info->ri_chunklen;
809738
head->arg.buflen += info->ri_chunklen;
810739

811-
if (info->ri_position < head->arg.head[0].iov_len) {
812-
ret = svc_rdma_copy_tail(rqstp, info);
813-
if (ret < 0)
814-
goto out;
815-
}
816-
head->arg.head[0].iov_len = info->ri_position;
817-
818740
out:
819741
return ret;
820742
}

0 commit comments

Comments
 (0)