diff options
Diffstat (limited to 'fs/nfsd/nfs4xdr.c')
| -rw-r--r-- | fs/nfsd/nfs4xdr.c | 123 | 
1 files changed, 56 insertions, 67 deletions
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c index 2acea7792bb2..1e9690a061ec 100644 --- a/fs/nfsd/nfs4xdr.c +++ b/fs/nfsd/nfs4xdr.c @@ -1810,7 +1810,7 @@ nfsd4_decode_test_stateid(struct nfsd4_compoundargs *argp, struct nfsd4_test_sta  	for (i = 0; i < test_stateid->ts_num_ids; i++) {  		stateid = svcxdr_tmpalloc(argp, sizeof(*stateid));  		if (!stateid) -			return nfserrno(-ENOMEM);	/* XXX: not jukebox? */ +			return nfserr_jukebox;  		INIT_LIST_HEAD(&stateid->ts_id_list);  		list_add_tail(&stateid->ts_id_list, &test_stateid->ts_stateid_list);  		status = nfsd4_decode_stateid4(argp, &stateid->ts_id_stateid); @@ -1896,8 +1896,8 @@ static __be32 nfsd4_decode_nl4_server(struct nfsd4_compoundargs *argp,  static __be32  nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)  { +	u32 consecutive, i, count, sync;  	struct nl4_server *ns_dummy; -	u32 consecutive, i, count;  	__be32 status;  	status = nfsd4_decode_stateid4(argp, ©->cp_src_stateid); @@ -1915,25 +1915,28 @@ nfsd4_decode_copy(struct nfsd4_compoundargs *argp, struct nfsd4_copy *copy)  	/* ca_consecutive: we always do consecutive copies */  	if (xdr_stream_decode_u32(argp->xdr, &consecutive) < 0)  		return nfserr_bad_xdr; -	if (xdr_stream_decode_u32(argp->xdr, ©->cp_synchronous) < 0) +	if (xdr_stream_decode_bool(argp->xdr, &sync) < 0)  		return nfserr_bad_xdr; +	nfsd4_copy_set_sync(copy, sync);  	if (xdr_stream_decode_u32(argp->xdr, &count) < 0)  		return nfserr_bad_xdr; -	copy->cp_intra = false; +	copy->cp_src = svcxdr_tmpalloc(argp, sizeof(*copy->cp_src)); +	if (copy->cp_src == NULL) +		return nfserr_jukebox;  	if (count == 0) { /* intra-server copy */ -		copy->cp_intra = true; +		__set_bit(NFSD4_COPY_F_INTRA, ©->cp_flags);  		return nfs_ok;  	}  	/* decode all the supplied server addresses but use only the first */ -	status = nfsd4_decode_nl4_server(argp, ©->cp_src); +	status = nfsd4_decode_nl4_server(argp, copy->cp_src);  	if (status)  		return status;  	ns_dummy = kmalloc(sizeof(struct nl4_server), GFP_KERNEL);  	if (ns_dummy == NULL) -		return nfserrno(-ENOMEM);	/* XXX: jukebox? */ +		return nfserr_jukebox;  	for (i = 0; i < count - 1; i++) {  		status = nfsd4_decode_nl4_server(argp, ns_dummy);  		if (status) { @@ -1952,10 +1955,17 @@ nfsd4_decode_copy_notify(struct nfsd4_compoundargs *argp,  {  	__be32 status; +	cn->cpn_src = svcxdr_tmpalloc(argp, sizeof(*cn->cpn_src)); +	if (cn->cpn_src == NULL) +		return nfserr_jukebox; +	cn->cpn_dst = svcxdr_tmpalloc(argp, sizeof(*cn->cpn_dst)); +	if (cn->cpn_dst == NULL) +		return nfserr_jukebox; +  	status = nfsd4_decode_stateid4(argp, &cn->cpn_src_stateid);  	if (status)  		return status; -	return nfsd4_decode_nl4_server(argp, &cn->cpn_dst); +	return nfsd4_decode_nl4_server(argp, cn->cpn_dst);  }  static __be32 @@ -2828,10 +2838,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,  	struct kstat stat;  	struct svc_fh *tempfh = NULL;  	struct kstatfs statfs; -	__be32 *p; +	__be32 *p, *attrlen_p;  	int starting_len = xdr->buf->len;  	int attrlen_offset; -	__be32 attrlen;  	u32 dummy;  	u64 dummy64;  	u32 rdattr_err = 0; @@ -2919,10 +2928,9 @@ nfsd4_encode_fattr(struct xdr_stream *xdr, struct svc_fh *fhp,  		goto out;  	attrlen_offset = xdr->buf->len; -	p = xdr_reserve_space(xdr, 4); -	if (!p) +	attrlen_p = xdr_reserve_space(xdr, XDR_UNIT); +	if (!attrlen_p)  		goto out_resource; -	p++;                /* to be backfilled later */  	if (bmval0 & FATTR4_WORD0_SUPPORTED_ATTRS) {  		u32 supp[3]; @@ -3344,8 +3352,7 @@ out_acl:  		*p++ = cpu_to_be32(err == 0);  	} -	attrlen = htonl(xdr->buf->len - attrlen_offset - 4); -	write_bytes_to_xdr_buf(xdr->buf, attrlen_offset, &attrlen, 4); +	*attrlen_p = cpu_to_be32(xdr->buf->len - attrlen_offset - XDR_UNIT);  	status = nfs_ok;  out: @@ -3882,16 +3889,15 @@ static __be32 nfsd4_encode_splice_read(  	struct xdr_stream *xdr = resp->xdr;  	struct xdr_buf *buf = xdr->buf;  	int status, space_left; -	u32 eof;  	__be32 nfserr; -	__be32 *p = xdr->p - 2;  	/* Make sure there will be room for padding if needed */  	if (xdr->end - xdr->p < 1)  		return nfserr_resource;  	nfserr = nfsd_splice_read(read->rd_rqstp, read->rd_fhp, -				  file, read->rd_offset, &maxcount, &eof); +				  file, read->rd_offset, &maxcount, +				  &read->rd_eof);  	read->rd_length = maxcount;  	if (nfserr)  		goto out_err; @@ -3902,9 +3908,6 @@ static __be32 nfsd4_encode_splice_read(  		goto out_err;  	} -	*(p++) = htonl(eof); -	*(p++) = htonl(maxcount); -  	buf->page_len = maxcount;  	buf->len += maxcount;  	xdr->page_ptr += (buf->page_base + maxcount + PAGE_SIZE - 1) @@ -3946,11 +3949,9 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,  				 struct file *file, unsigned long maxcount)  {  	struct xdr_stream *xdr = resp->xdr; -	u32 eof; -	int starting_len = xdr->buf->len - 8; +	unsigned int starting_len = xdr->buf->len; +	__be32 zero = xdr_zero;  	__be32 nfserr; -	__be32 tmp; -	int pad;  	read->rd_vlen = xdr_reserve_space_vec(xdr, resp->rqstp->rq_vec, maxcount);  	if (read->rd_vlen < 0) @@ -3958,31 +3959,24 @@ static __be32 nfsd4_encode_readv(struct nfsd4_compoundres *resp,  	nfserr = nfsd_readv(resp->rqstp, read->rd_fhp, file, read->rd_offset,  			    resp->rqstp->rq_vec, read->rd_vlen, &maxcount, -			    &eof); +			    &read->rd_eof);  	read->rd_length = maxcount;  	if (nfserr)  		return nfserr; -	if (svc_encode_result_payload(resp->rqstp, starting_len + 8, maxcount)) +	if (svc_encode_result_payload(resp->rqstp, starting_len, maxcount))  		return nfserr_io; -	xdr_truncate_encode(xdr, starting_len + 8 + xdr_align_size(maxcount)); - -	tmp = htonl(eof); -	write_bytes_to_xdr_buf(xdr->buf, starting_len    , &tmp, 4); -	tmp = htonl(maxcount); -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 4, &tmp, 4); - -	tmp = xdr_zero; -	pad = (maxcount&3) ? 4 - (maxcount&3) : 0; -	write_bytes_to_xdr_buf(xdr->buf, starting_len + 8 + maxcount, -								&tmp, pad); -	return 0; +	xdr_truncate_encode(xdr, starting_len + xdr_align_size(maxcount)); +	write_bytes_to_xdr_buf(xdr->buf, starting_len + maxcount, &zero, +			       xdr_pad_size(maxcount)); +	return nfs_ok;  }  static __be32  nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,  		  struct nfsd4_read *read)  { +	bool splice_ok = test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags);  	unsigned long maxcount;  	struct xdr_stream *xdr = resp->xdr;  	struct file *file; @@ -3995,11 +3989,10 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,  	p = xdr_reserve_space(xdr, 8); /* eof flag and byte count */  	if (!p) { -		WARN_ON_ONCE(test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)); +		WARN_ON_ONCE(splice_ok);  		return nfserr_resource;  	} -	if (resp->xdr->buf->page_len && -	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) { +	if (resp->xdr->buf->page_len && splice_ok) {  		WARN_ON_ONCE(1);  		return nfserr_resource;  	} @@ -4008,31 +4001,30 @@ nfsd4_encode_read(struct nfsd4_compoundres *resp, __be32 nfserr,  	maxcount = min_t(unsigned long, read->rd_length,  			 (xdr->buf->buflen - xdr->buf->len)); -	if (file->f_op->splice_read && -	    test_bit(RQ_SPLICE_OK, &resp->rqstp->rq_flags)) +	if (file->f_op->splice_read && splice_ok)  		nfserr = nfsd4_encode_splice_read(resp, read, file, maxcount);  	else  		nfserr = nfsd4_encode_readv(resp, read, file, maxcount); - -	if (nfserr) +	if (nfserr) {  		xdr_truncate_encode(xdr, starting_len); +		return nfserr; +	} -	return nfserr; +	p = xdr_encode_bool(p, read->rd_eof); +	*p = cpu_to_be32(read->rd_length); +	return nfs_ok;  }  static __be32  nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd4_readlink *readlink)  { -	int maxcount; -	__be32 wire_count; -	int zero = 0; +	__be32 *p, *maxcount_p, zero = xdr_zero;  	struct xdr_stream *xdr = resp->xdr;  	int length_offset = xdr->buf->len; -	int status; -	__be32 *p; +	int maxcount, status; -	p = xdr_reserve_space(xdr, 4); -	if (!p) +	maxcount_p = xdr_reserve_space(xdr, XDR_UNIT); +	if (!maxcount_p)  		return nfserr_resource;  	maxcount = PAGE_SIZE; @@ -4057,14 +4049,11 @@ nfsd4_encode_readlink(struct nfsd4_compoundres *resp, __be32 nfserr, struct nfsd  		nfserr = nfserrno(status);  		goto out_err;  	} - -	wire_count = htonl(maxcount); -	write_bytes_to_xdr_buf(xdr->buf, length_offset, &wire_count, 4); -	xdr_truncate_encode(xdr, length_offset + 4 + ALIGN(maxcount, 4)); -	if (maxcount & 3) -		write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, -						&zero, 4 - (maxcount&3)); -	return 0; +	*maxcount_p = cpu_to_be32(maxcount); +	xdr_truncate_encode(xdr, length_offset + 4 + xdr_align_size(maxcount)); +	write_bytes_to_xdr_buf(xdr->buf, length_offset + 4 + maxcount, &zero, +			       xdr_pad_size(maxcount)); +	return nfs_ok;  out_err:  	xdr_truncate_encode(xdr, length_offset); @@ -4715,13 +4704,13 @@ nfsd4_encode_copy(struct nfsd4_compoundres *resp, __be32 nfserr,  	__be32 *p;  	nfserr = nfsd42_encode_write_res(resp, ©->cp_res, -					 !!copy->cp_synchronous); +					 nfsd4_copy_is_sync(copy));  	if (nfserr)  		return nfserr;  	p = xdr_reserve_space(resp->xdr, 4 + 4);  	*p++ = xdr_one; /* cr_consecutive */ -	*p++ = cpu_to_be32(copy->cp_synchronous); +	*p = nfsd4_copy_is_sync(copy) ? xdr_one : xdr_zero;  	return 0;  } @@ -4919,7 +4908,8 @@ nfsd4_encode_copy_notify(struct nfsd4_compoundres *resp, __be32 nfserr,  	*p++ = cpu_to_be32(1); -	return nfsd42_encode_nl4_server(resp, &cn->cpn_src); +	nfserr = nfsd42_encode_nl4_server(resp, cn->cpn_src); +	return nfserr;  }  static __be32 @@ -5373,8 +5363,7 @@ nfsd4_encode_operation(struct nfsd4_compoundres *resp, struct nfsd4_op *op)  						so->so_replay.rp_buf, len);  	}  status: -	/* Note that op->status is already in network byte order: */ -	write_bytes_to_xdr_buf(xdr->buf, post_err_offset - 4, &op->status, 4); +	*p = op->status;  }  /*   |