Commit 8c293ef9 authored by Chuck Lever's avatar Chuck Lever
Browse files

NFSD: Update the NFSv2 READ argument decoder to use struct xdr_stream



The code that sets up rq_vec is refactored so that it is now
adjacent to the nfsd_read() call site where it is used.

Signed-off-by: default avatarChuck Lever <chuck.lever@oracle.com>
parent ebcd8e8b
Loading
Loading
Loading
Loading
+18 −14
Original line number Diff line number Diff line
@@ -171,32 +171,36 @@ nfsd_proc_read(struct svc_rqst *rqstp)
{
	struct nfsd_readargs *argp = rqstp->rq_argp;
	struct nfsd_readres *resp = rqstp->rq_resp;
	unsigned int len;
	u32 eof;
	int v;

	dprintk("nfsd: READ    %s %d bytes at %d\n",
		SVCFH_fmt(&argp->fh),
		argp->count, argp->offset);

	argp->count = min_t(u32, argp->count, NFSSVC_MAXBLKSIZE_V2);

	v = 0;
	len = argp->count;
	while (len > 0) {
		struct page *page = *(rqstp->rq_next_page++);

		rqstp->rq_vec[v].iov_base = page_address(page);
		rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
		len -= rqstp->rq_vec[v].iov_len;
		v++;
	}

	/* Obtain buffer pointer for payload. 19 is 1 word for
	 * status, 17 words for fattr, and 1 word for the byte count.
	 */

	if (NFSSVC_MAXBLKSIZE_V2 < argp->count) {
		char buf[RPC_MAX_ADDRBUFLEN];
		printk(KERN_NOTICE
			"oversized read request from %s (%d bytes)\n",
				svc_print_addr(rqstp, buf, sizeof(buf)),
				argp->count);
		argp->count = NFSSVC_MAXBLKSIZE_V2;
	}
	svc_reserve_auth(rqstp, (19<<2) + argp->count + 4);

	resp->count = argp->count;
	resp->status = nfsd_read(rqstp, fh_copy(&resp->fh, &argp->fh),
				 argp->offset,
				 rqstp->rq_vec, argp->vlen,
				 &resp->count,
				 &eof);
	fh_copy(&resp->fh, &argp->fh);
	resp->status = nfsd_read(rqstp, &resp->fh, argp->offset,
				 rqstp->rq_vec, v, &resp->count, &eof);
	if (resp->status == nfs_ok)
		resp->status = fh_getattr(&resp->fh, &resp->stat);
	else if (resp->status == nfserr_jukebox)
+12 −24
Original line number Diff line number Diff line
@@ -246,33 +246,21 @@ nfssvc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p)
int
nfssvc_decode_readargs(struct svc_rqst *rqstp, __be32 *p)
{
	struct xdr_stream *xdr = &rqstp->rq_arg_stream;
	struct nfsd_readargs *args = rqstp->rq_argp;
	unsigned int len;
	int v;
	p = decode_fh(p, &args->fh);
	if (!p)
		return 0;
	u32 totalcount;

	args->offset    = ntohl(*p++);
	len = args->count     = ntohl(*p++);
	p++; /* totalcount - unused */

	len = min_t(unsigned int, len, NFSSVC_MAXBLKSIZE_V2);

	/* set up somewhere to store response.
	 * We take pages, put them on reslist and include in iovec
	 */
	v=0;
	while (len > 0) {
		struct page *p = *(rqstp->rq_next_page++);
	if (!svcxdr_decode_fhandle(xdr, &args->fh))
		return 0;
	if (xdr_stream_decode_u32(xdr, &args->offset) < 0)
		return 0;
	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
		return 0;
	/* totalcount is ignored */
	if (xdr_stream_decode_u32(xdr, &totalcount) < 0)
		return 0;

		rqstp->rq_vec[v].iov_base = page_address(p);
		rqstp->rq_vec[v].iov_len = min_t(unsigned int, len, PAGE_SIZE);
		len -= rqstp->rq_vec[v].iov_len;
		v++;
	}
	args->vlen = v;
	return xdr_argsize_check(rqstp, p);
	return 1;
}

int
+0 −1
Original line number Diff line number Diff line
@@ -27,7 +27,6 @@ struct nfsd_readargs {
	struct svc_fh		fh;
	__u32			offset;
	__u32			count;
	int			vlen;
};

struct nfsd_writeargs {