Skip to content

Commit 82078b9

Browse files
committed
NFSD: Ensure that xdr_write_pages updates rq_next_page
All other NFSv[23] procedures manage to keep page_ptr and rq_next_page in lock step. Signed-off-by: Chuck Lever <[email protected]>
1 parent 66a21db commit 82078b9

File tree

3 files changed

+35
-8
lines changed

3 files changed

+35
-8
lines changed

fs/nfsd/nfs3xdr.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,8 @@ nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
828828
return false;
829829
if (xdr_stream_encode_u32(xdr, resp->len) < 0)
830830
return false;
831-
xdr_write_pages(xdr, resp->pages, 0, resp->len);
831+
svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0,
832+
resp->len);
832833
if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
833834
return false;
834835
break;
@@ -859,8 +860,9 @@ nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
859860
return false;
860861
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
861862
return false;
862-
xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
863-
resp->count);
863+
svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
864+
rqstp->rq_res.page_base,
865+
resp->count);
864866
if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
865867
return false;
866868
break;
@@ -961,7 +963,8 @@ nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
961963
return false;
962964
if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
963965
return false;
964-
xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
966+
svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
967+
dirlist->len);
965968
/* no more entries */
966969
if (xdr_stream_encode_item_absent(xdr) < 0)
967970
return false;

fs/nfsd/nfsxdr.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,7 +468,8 @@ nfssvc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
468468
case nfs_ok:
469469
if (xdr_stream_encode_u32(xdr, resp->len) < 0)
470470
return false;
471-
xdr_write_pages(xdr, &resp->page, 0, resp->len);
471+
svcxdr_encode_opaque_pages(rqstp, xdr, &resp->page, 0,
472+
resp->len);
472473
if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
473474
return false;
474475
break;
@@ -491,8 +492,9 @@ nfssvc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
491492
return false;
492493
if (xdr_stream_encode_u32(xdr, resp->count) < 0)
493494
return false;
494-
xdr_write_pages(xdr, resp->pages, rqstp->rq_res.page_base,
495-
resp->count);
495+
svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
496+
rqstp->rq_res.page_base,
497+
resp->count);
496498
if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
497499
return false;
498500
break;
@@ -511,7 +513,8 @@ nfssvc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
511513
return false;
512514
switch (resp->status) {
513515
case nfs_ok:
514-
xdr_write_pages(xdr, dirlist->pages, 0, dirlist->len);
516+
svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
517+
dirlist->len);
515518
/* no more entries */
516519
if (xdr_stream_encode_item_absent(xdr) < 0)
517520
return false;

include/linux/sunrpc/svc.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,27 @@ static inline void svcxdr_init_encode(struct svc_rqst *rqstp)
508508
xdr->rqst = NULL;
509509
}
510510

511+
/**
512+
* svcxdr_encode_opaque_pages - Insert pages into an xdr_stream
513+
* @xdr: xdr_stream to be updated
514+
* @pages: array of pages to insert
515+
* @base: starting offset of first data byte in @pages
516+
* @len: number of data bytes in @pages to insert
517+
*
518+
* After the @pages are added, the tail iovec is instantiated pointing
519+
* to end of the head buffer, and the stream is set up to encode
520+
* subsequent items into the tail.
521+
*/
522+
static inline void svcxdr_encode_opaque_pages(struct svc_rqst *rqstp,
523+
struct xdr_stream *xdr,
524+
struct page **pages,
525+
unsigned int base,
526+
unsigned int len)
527+
{
528+
xdr_write_pages(xdr, pages, base, len);
529+
xdr->page_ptr = rqstp->rq_next_page - 1;
530+
}
531+
511532
/**
512533
* svcxdr_set_auth_slack -
513534
* @rqstp: RPC transaction

0 commit comments

Comments
 (0)