Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cf500bac authored by Chuck Lever's avatar Chuck Lever Committed by Anna Schumaker
Browse files

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: default avatarChuck Lever <chuck.lever@oracle.com>
Signed-off-by: default avatarAnna Schumaker <Anna.Schumaker@Netapp.com>
parent 2573a464
Loading
Loading
Loading
Loading
+6 −21
Original line number Diff line number Diff line
@@ -65,21 +65,6 @@

static int nfs_stat_to_errno(enum nfs_stat);

/*
 * While encoding arguments, set up the reply buffer in advance to
 * receive reply data directly into the page cache.
 */
static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
				 unsigned int base, unsigned int len,
				 unsigned int bufsize)
{
	struct rpc_auth	*auth = req->rq_cred->cr_auth;
	unsigned int replen;

	replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
}

/*
 * Encode/decode NFSv2 basic data types
 *
@@ -593,7 +578,7 @@ static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
	const struct nfs_readlinkargs *args = data;

	encode_fhandle(xdr, args->fh);
	prepare_reply_buffer(req, args->pages, args->pgbase,
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->pglen, NFS_readlinkres_sz);
}

@@ -629,7 +614,7 @@ static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
	const struct nfs_pgio_args *args = data;

	encode_readargs(xdr, args);
	prepare_reply_buffer(req, args->pages, args->pgbase,
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->count, NFS_readres_sz);
	req->rq_rcv_buf.flags |= XDRBUF_READ;
}
@@ -787,7 +772,7 @@ static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
	const struct nfs_readdirargs *args = data;

	encode_readdirargs(xdr, args);
	prepare_reply_buffer(req, args->pages, 0,
	rpc_prepare_reply_pages(req, args->pages, 0,
				args->count, NFS_readdirres_sz);
}

+7 −22
Original line number Diff line number Diff line
@@ -104,21 +104,6 @@ static const umode_t nfs_type2fmt[] = {
	[NF3FIFO] = S_IFIFO,
};

/*
 * While encoding arguments, set up the reply buffer in advance to
 * receive reply data directly into the page cache.
 */
static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
				 unsigned int base, unsigned int len,
				 unsigned int bufsize)
{
	struct rpc_auth	*auth = req->rq_cred->cr_auth;
	unsigned int replen;

	replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
}

/*
 * Encode/decode NFSv3 basic data types
 *
@@ -910,7 +895,7 @@ static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
	const struct nfs3_readlinkargs *args = data;

	encode_nfs_fh3(xdr, args->fh);
	prepare_reply_buffer(req, args->pages, args->pgbase,
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->pglen, NFS3_readlinkres_sz);
}

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

	encode_read3args(xdr, args);
	prepare_reply_buffer(req, args->pages, args->pgbase,
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->count, replen);
	req->rq_rcv_buf.flags |= XDRBUF_READ;
}
@@ -1236,7 +1221,7 @@ static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
	const struct nfs3_readdirargs *args = data;

	encode_readdir3args(xdr, args);
	prepare_reply_buffer(req, args->pages, 0,
	rpc_prepare_reply_pages(req, args->pages, 0,
				args->count, NFS3_readdirres_sz);
}

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

	encode_readdirplus3args(xdr, args);
	prepare_reply_buffer(req, args->pages, 0,
	rpc_prepare_reply_pages(req, args->pages, 0,
				args->count, NFS3_readdirres_sz);
}

@@ -1323,7 +1308,7 @@ static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
	encode_nfs_fh3(xdr, args->fh);
	encode_uint32(xdr, args->mask);
	if (args->mask & (NFS_ACL | NFS_DFACL)) {
		prepare_reply_buffer(req, args->pages, 0,
		rpc_prepare_reply_pages(req, args->pages, 0,
					NFSACL_MAXPAGES << PAGE_SHIFT,
					ACL3_getaclres_sz);
		req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
+21 −30
Original line number Diff line number Diff line
@@ -1016,12 +1016,11 @@ static void encode_compound_hdr(struct xdr_stream *xdr,
				struct compound_hdr *hdr)
{
	__be32 *p;
	struct rpc_auth *auth = req->rq_cred->cr_auth;

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

	WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
	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,
	encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
	if (args->lg_args) {
		encode_layoutget(xdr, args->lg_args, &hdr);
		xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
				 args->lg_args->layout.pages,
				 0, args->lg_args->layout.pglen);
		rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
					args->lg_args->layout.pglen,
					hdr.replen);
	}
	encode_nops(&hdr);
}
@@ -2387,9 +2386,9 @@ static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
	encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
	if (args->lg_args) {
		encode_layoutget(xdr, args->lg_args, &hdr);
		xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
				 args->lg_args->layout.pages,
				 0, args->lg_args->layout.pglen);
		rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
					args->lg_args->layout.pglen,
					hdr.replen);
	}
	encode_nops(&hdr);
}
@@ -2499,8 +2498,8 @@ static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr,
	encode_putfh(xdr, args->fh, &hdr);
	encode_readlink(xdr, args, req, &hdr);

	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
			args->pgbase, args->pglen);
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->pglen, hdr.replen);
	encode_nops(&hdr);
}

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

	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
			 args->pgbase, args->count);
	dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
			__func__, hdr.replen << 2, args->pages,
			args->pgbase, args->count);
	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
				args->count, hdr.replen);
	encode_nops(&hdr);
}

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

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

	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
		args->acl_pages, 0, args->acl_len);

	rpc_prepare_reply_pages(req, args->acl_pages, 0,
				args->acl_len, replen);
	encode_nops(&hdr);
}

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

	/* Set up reply kvec to capture returned fs_locations array. */
	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
			 (struct page **)&args->page, 0, PAGE_SIZE);
	rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
				PAGE_SIZE, replen);
	encode_nops(&hdr);
}

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

	/* set up reply kvec. Subtract notification bitmap max size (2)
	 * so that notification bitmap is put in xdr_buf tail */
	xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
			 args->pdev->pages, args->pdev->pgbase,
			 args->pdev->pglen);

	rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase,
				args->pdev->pglen, hdr.replen - 2);
	encode_nops(&hdr);
}

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

	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
	    args->layout.pages, 0, args->layout.pglen);

	rpc_prepare_reply_pages(req, args->layout.pages, 0,
				args->layout.pglen, hdr.replen);
	encode_nops(&hdr);
}

+3 −0
Original line number Diff line number Diff line
@@ -169,6 +169,9 @@ int rpcb_v4_register(struct net *net, const u32 program,
				 const char *netid);
void		rpcb_getport_async(struct rpc_task *);

void rpc_prepare_reply_pages(struct rpc_rqst *req, struct page **pages,
			     unsigned int base, unsigned int len,
			     unsigned int hdrsize);
void		rpc_call_start(struct rpc_task *);
int		rpc_call_async(struct rpc_clnt *clnt,
			       const struct rpc_message *msg, int flags,
+37 −0
Original line number Diff line number Diff line
@@ -461,6 +461,43 @@ TRACE_EVENT(rpc_xdr_alignment,
	)
);

TRACE_EVENT(rpc_reply_pages,
	TP_PROTO(
		const struct rpc_rqst *req
	),

	TP_ARGS(req),

	TP_STRUCT__entry(
		__field(unsigned int, task_id)
		__field(unsigned int, client_id)
		__field(const void *, head_base)
		__field(size_t, head_len)
		__field(const void *, tail_base)
		__field(size_t, tail_len)
		__field(unsigned int, page_len)
	),

	TP_fast_assign(
		__entry->task_id = req->rq_task->tk_pid;
		__entry->client_id = req->rq_task->tk_client->cl_clid;

		__entry->head_base = req->rq_rcv_buf.head[0].iov_base;
		__entry->head_len = req->rq_rcv_buf.head[0].iov_len;
		__entry->page_len = req->rq_rcv_buf.page_len;
		__entry->tail_base = req->rq_rcv_buf.tail[0].iov_base;
		__entry->tail_len = req->rq_rcv_buf.tail[0].iov_len;
	),

	TP_printk(
		"task:%u@%u xdr=[%p,%zu]/%u/[%p,%zu]\n",
		__entry->task_id, __entry->client_id,
		__entry->head_base, __entry->head_len,
		__entry->page_len,
		__entry->tail_base, __entry->tail_len
	)
);

/*
 * First define the enums in the below macros to be exported to userspace
 * via TRACE_DEFINE_ENUM().
Loading