Skip to content

Commit cf500ba

Browse files
chuckleveramschuma-ntap
authored andcommitted
SUNRPC: Introduce rpc_prepare_reply_pages()
prepare_reply_buffer() and its NFSv4 equivalents expose the details of the RPC header and the auth slack values to upper layer consumers, creating a layering violation, and duplicating code. Remedy these issues by adding a new RPC client API that hides those details from upper layers in a common helper function. Signed-off-by: Chuck Lever <[email protected]> Signed-off-by: Anna Schumaker <[email protected]>
1 parent 2573a46 commit cf500ba

File tree

7 files changed

+102
-73
lines changed

7 files changed

+102
-73
lines changed

fs/nfs/nfs2xdr.c

Lines changed: 6 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -65,21 +65,6 @@
6565

6666
static int nfs_stat_to_errno(enum nfs_stat);
6767

68-
/*
69-
* While encoding arguments, set up the reply buffer in advance to
70-
* receive reply data directly into the page cache.
71-
*/
72-
static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
73-
unsigned int base, unsigned int len,
74-
unsigned int bufsize)
75-
{
76-
struct rpc_auth *auth = req->rq_cred->cr_auth;
77-
unsigned int replen;
78-
79-
replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
80-
xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
81-
}
82-
8368
/*
8469
* Encode/decode NFSv2 basic data types
8570
*
@@ -593,8 +578,8 @@ static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
593578
const struct nfs_readlinkargs *args = data;
594579

595580
encode_fhandle(xdr, args->fh);
596-
prepare_reply_buffer(req, args->pages, args->pgbase,
597-
args->pglen, NFS_readlinkres_sz);
581+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
582+
args->pglen, NFS_readlinkres_sz);
598583
}
599584

600585
/*
@@ -629,8 +614,8 @@ static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
629614
const struct nfs_pgio_args *args = data;
630615

631616
encode_readargs(xdr, args);
632-
prepare_reply_buffer(req, args->pages, args->pgbase,
633-
args->count, NFS_readres_sz);
617+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
618+
args->count, NFS_readres_sz);
634619
req->rq_rcv_buf.flags |= XDRBUF_READ;
635620
}
636621

@@ -787,8 +772,8 @@ static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
787772
const struct nfs_readdirargs *args = data;
788773

789774
encode_readdirargs(xdr, args);
790-
prepare_reply_buffer(req, args->pages, 0,
791-
args->count, NFS_readdirres_sz);
775+
rpc_prepare_reply_pages(req, args->pages, 0,
776+
args->count, NFS_readdirres_sz);
792777
}
793778

794779
/*

fs/nfs/nfs3xdr.c

Lines changed: 7 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -104,21 +104,6 @@ static const umode_t nfs_type2fmt[] = {
104104
[NF3FIFO] = S_IFIFO,
105105
};
106106

107-
/*
108-
* While encoding arguments, set up the reply buffer in advance to
109-
* receive reply data directly into the page cache.
110-
*/
111-
static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
112-
unsigned int base, unsigned int len,
113-
unsigned int bufsize)
114-
{
115-
struct rpc_auth *auth = req->rq_cred->cr_auth;
116-
unsigned int replen;
117-
118-
replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
119-
xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
120-
}
121-
122107
/*
123108
* Encode/decode NFSv3 basic data types
124109
*
@@ -910,8 +895,8 @@ static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
910895
const struct nfs3_readlinkargs *args = data;
911896

912897
encode_nfs_fh3(xdr, args->fh);
913-
prepare_reply_buffer(req, args->pages, args->pgbase,
914-
args->pglen, NFS3_readlinkres_sz);
898+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
899+
args->pglen, NFS3_readlinkres_sz);
915900
}
916901

917902
/*
@@ -943,8 +928,8 @@ static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
943928
unsigned int replen = args->replen ? args->replen : NFS3_readres_sz;
944929

945930
encode_read3args(xdr, args);
946-
prepare_reply_buffer(req, args->pages, args->pgbase,
947-
args->count, replen);
931+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
932+
args->count, replen);
948933
req->rq_rcv_buf.flags |= XDRBUF_READ;
949934
}
950935

@@ -1236,7 +1221,7 @@ static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
12361221
const struct nfs3_readdirargs *args = data;
12371222

12381223
encode_readdir3args(xdr, args);
1239-
prepare_reply_buffer(req, args->pages, 0,
1224+
rpc_prepare_reply_pages(req, args->pages, 0,
12401225
args->count, NFS3_readdirres_sz);
12411226
}
12421227

@@ -1278,7 +1263,7 @@ static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
12781263
const struct nfs3_readdirargs *args = data;
12791264

12801265
encode_readdirplus3args(xdr, args);
1281-
prepare_reply_buffer(req, args->pages, 0,
1266+
rpc_prepare_reply_pages(req, args->pages, 0,
12821267
args->count, NFS3_readdirres_sz);
12831268
}
12841269

@@ -1323,7 +1308,7 @@ static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
13231308
encode_nfs_fh3(xdr, args->fh);
13241309
encode_uint32(xdr, args->mask);
13251310
if (args->mask & (NFS_ACL | NFS_DFACL)) {
1326-
prepare_reply_buffer(req, args->pages, 0,
1311+
rpc_prepare_reply_pages(req, args->pages, 0,
13271312
NFSACL_MAXPAGES << PAGE_SHIFT,
13281313
ACL3_getaclres_sz);
13291314
req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;

fs/nfs/nfs4xdr.c

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1016,12 +1016,11 @@ static void encode_compound_hdr(struct xdr_stream *xdr,
10161016
struct compound_hdr *hdr)
10171017
{
10181018
__be32 *p;
1019-
struct rpc_auth *auth = req->rq_cred->cr_auth;
10201019

10211020
/* initialize running count of expected bytes in reply.
10221021
* NOTE: the replied tag SHOULD be the same is the one sent,
10231022
* but this is not required as a MUST for the server to do so. */
1024-
hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
1023+
hdr->replen = 3 + hdr->taglen;
10251024

10261025
WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
10271026
encode_string(xdr, hdr->taglen, hdr->tag);
@@ -2341,9 +2340,9 @@ static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
23412340
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
23422341
if (args->lg_args) {
23432342
encode_layoutget(xdr, args->lg_args, &hdr);
2344-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2345-
args->lg_args->layout.pages,
2346-
0, args->lg_args->layout.pglen);
2343+
rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
2344+
args->lg_args->layout.pglen,
2345+
hdr.replen);
23472346
}
23482347
encode_nops(&hdr);
23492348
}
@@ -2387,9 +2386,9 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
23872386
encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
23882387
if (args->lg_args) {
23892388
encode_layoutget(xdr, args->lg_args, &hdr);
2390-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2391-
args->lg_args->layout.pages,
2392-
0, args->lg_args->layout.pglen);
2389+
rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
2390+
args->lg_args->layout.pglen,
2391+
hdr.replen);
23932392
}
23942393
encode_nops(&hdr);
23952394
}
@@ -2499,8 +2498,8 @@ static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr,
24992498
encode_putfh(xdr, args->fh, &hdr);
25002499
encode_readlink(xdr, args, req, &hdr);
25012500

2502-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2503-
args->pgbase, args->pglen);
2501+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
2502+
args->pglen, hdr.replen);
25042503
encode_nops(&hdr);
25052504
}
25062505

@@ -2520,11 +2519,8 @@ static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr,
25202519
encode_putfh(xdr, args->fh, &hdr);
25212520
encode_readdir(xdr, args, req, &hdr);
25222521

2523-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2524-
args->pgbase, args->count);
2525-
dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
2526-
__func__, hdr.replen << 2, args->pages,
2527-
args->pgbase, args->count);
2522+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
2523+
args->count, hdr.replen);
25282524
encode_nops(&hdr);
25292525
}
25302526

@@ -2544,8 +2540,8 @@ static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr,
25442540
encode_putfh(xdr, args->fh, &hdr);
25452541
encode_read(xdr, args, &hdr);
25462542

2547-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2548-
args->pages, args->pgbase, args->count);
2543+
rpc_prepare_reply_pages(req, args->pages, args->pgbase,
2544+
args->count, hdr.replen);
25492545
req->rq_rcv_buf.flags |= XDRBUF_READ;
25502546
encode_nops(&hdr);
25512547
}
@@ -2591,9 +2587,8 @@ static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
25912587
encode_getattr(xdr, nfs4_acl_bitmap, NULL,
25922588
ARRAY_SIZE(nfs4_acl_bitmap), &hdr);
25932589

2594-
xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
2595-
args->acl_pages, 0, args->acl_len);
2596-
2590+
rpc_prepare_reply_pages(req, args->acl_pages, 0,
2591+
args->acl_len, replen);
25972592
encode_nops(&hdr);
25982593
}
25992594

@@ -2814,9 +2809,8 @@ static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
28142809
encode_fs_locations(xdr, args->bitmask, &hdr);
28152810
}
28162811

2817-
/* Set up reply kvec to capture returned fs_locations array. */
2818-
xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
2819-
(struct page **)&args->page, 0, PAGE_SIZE);
2812+
rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
2813+
PAGE_SIZE, replen);
28202814
encode_nops(&hdr);
28212815
}
28222816

@@ -3018,10 +3012,8 @@ static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req,
30183012

30193013
/* set up reply kvec. Subtract notification bitmap max size (2)
30203014
* so that notification bitmap is put in xdr_buf tail */
3021-
xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
3022-
args->pdev->pages, args->pdev->pgbase,
3023-
args->pdev->pglen);
3024-
3015+
rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase,
3016+
args->pdev->pglen, hdr.replen - 2);
30253017
encode_nops(&hdr);
30263018
}
30273019

@@ -3042,9 +3034,8 @@ static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
30423034
encode_putfh(xdr, NFS_FH(args->inode), &hdr);
30433035
encode_layoutget(xdr, args, &hdr);
30443036

3045-
xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
3046-
args->layout.pages, 0, args->layout.pglen);
3047-
3037+
rpc_prepare_reply_pages(req, args->layout.pages, 0,
3038+
args->layout.pglen, hdr.replen);
30483039
encode_nops(&hdr);
30493040
}
30503041

include/linux/sunrpc/clnt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,9 @@ int rpcb_v4_register(struct net *net, const u32 program,
169169
const char *netid);
170170
void rpcb_getport_async(struct rpc_task *);
171171

172+
void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
173+
unsigned int base, unsigned int len,
174+
unsigned int hdrsize);
172175
void rpc_call_start(struct rpc_task *);
173176
int rpc_call_async(struct rpc_clnt *clnt,
174177
const struct rpc_message *msg, int flags,

include/trace/events/sunrpc.h

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -461,6 +461,43 @@ TRACE_EVENT(rpc_xdr_alignment,
461461
)
462462
);
463463

464+
TRACE_EVENT(rpc_reply_pages,
465+
TP_PROTO(
466+
const struct rpc_rqst *req
467+
),
468+
469+
TP_ARGS(req),
470+
471+
TP_STRUCT__entry(
472+
__field(unsigned int, task_id)
473+
__field(unsigned int, client_id)
474+
__field(const void *, head_base)
475+
__field(size_t, head_len)
476+
__field(const void *, tail_base)
477+
__field(size_t, tail_len)
478+
__field(unsigned int, page_len)
479+
),
480+
481+
TP_fast_assign(
482+
__entry->task_id = req->rq_task->tk_pid;
483+
__entry->client_id = req->rq_task->tk_client->cl_clid;
484+
485+
__entry->head_base = req->rq_rcv_buf.head[0].iov_base;
486+
__entry->head_len = req->rq_rcv_buf.head[0].iov_len;
487+
__entry->page_len = req->rq_rcv_buf.page_len;
488+
__entry->tail_base = req->rq_rcv_buf.tail[0].iov_base;
489+
__entry->tail_len = req->rq_rcv_buf.tail[0].iov_len;
490+
),
491+
492+
TP_printk(
493+
"task:%u@%u xdr=[%p,%zu]/%u/[%p,%zu]\n",
494+
__entry->task_id, __entry->client_id,
495+
__entry->head_base, __entry->head_len,
496+
__entry->page_len,
497+
__entry->tail_base, __entry->tail_len
498+
)
499+
);
500+
464501
/*
465502
* First define the enums in the below macros to be exported to userspace
466503
* via TRACE_DEFINE_ENUM().

net/sunrpc/clnt.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,6 +1164,25 @@ struct rpc_task *rpc_run_bc_task(struct rpc_rqst *req)
11641164
}
11651165
#endif /* CONFIG_SUNRPC_BACKCHANNEL */
11661166

1167+
/**
1168+
* rpc_prepare_reply_pages - Prepare to receive a reply data payload into pages
1169+
* @req: RPC request to prepare
1170+
* @pages: vector of struct page pointers
1171+
* @base: offset in first page where receive should start, in bytes
1172+
* @len: expected size of the upper layer data payload, in bytes
1173+
* @hdrsize: expected size of upper layer reply header, in XDR words
1174+
*
1175+
*/
1176+
void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
1177+
unsigned int base, unsigned int len,
1178+
unsigned int hdrsize)
1179+
{
1180+
hdrsize += RPC_REPHDRSIZE + req->rq_cred->cr_auth->au_rslack;
1181+
xdr_inline_pages(&req->rq_rcv_buf, hdrsize << 2, pages, base, len);
1182+
trace_rpc_reply_pages(req);
1183+
}
1184+
EXPORT_SYMBOL_GPL(rpc_prepare_reply_pages);
1185+
11671186
void
11681187
rpc_call_start(struct rpc_task *task)
11691188
{

net/sunrpc/xdr.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,15 @@ xdr_free_bvec(struct xdr_buf *buf)
163163
buf->bvec = NULL;
164164
}
165165

166+
/**
167+
* xdr_inline_pages - Prepare receive buffer for a large reply
168+
* @xdr: xdr_buf into which reply will be placed
169+
* @offset: expected offset where data payload will start, in bytes
170+
* @pages: vector of struct page pointers
171+
* @base: offset in first page where receive should start, in bytes
172+
* @len: expected size of the upper layer data payload, in bytes
173+
*
174+
*/
166175
void
167176
xdr_inline_pages(struct xdr_buf *xdr, unsigned int offset,
168177
struct page **pages, unsigned int base, unsigned int len)

0 commit comments

Comments
 (0)