diff options
Diffstat (limited to 'fs/nfs/nfs4xdr.c')
| -rw-r--r-- | fs/nfs/nfs4xdr.c | 90 | 
1 files changed, 32 insertions, 58 deletions
diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index 18fae29b030..ca13483edd6 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -852,12 +852,6 @@ const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +  				    XDR_UNIT);  #endif /* CONFIG_NFS_V4_1 */ -static unsigned short send_implementation_id = 1; - -module_param(send_implementation_id, ushort, 0644); -MODULE_PARM_DESC(send_implementation_id, -		"Send implementation ID with NFSv4.1 exchange_id"); -  static const umode_t nfs_type2fmt[] = {  	[NF4BAD] = 0,  	[NF4REG] = S_IFREG, @@ -1236,7 +1230,7 @@ static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct  static inline int nfs4_lock_type(struct file_lock *fl, int block)  { -	if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK) +	if (fl->fl_type == F_RDLCK)  		return block ? NFS4_READW_LT : NFS4_READ_LT;  	return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;  } @@ -3078,7 +3072,7 @@ out_overflow:  	return -EIO;  } -static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep) +static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep)  {  	__be32 *p; @@ -3086,7 +3080,7 @@ static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen,  	if (unlikely(!p))  		goto out_overflow;  	*attrlen = be32_to_cpup(p); -	*savep = xdr->p; +	*savep = xdr_stream_pos(xdr);  	return 0;  out_overflow:  	print_overflow_msg(__func__, xdr); @@ -4068,10 +4062,10 @@ static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, str  	return status;  } -static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen) +static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen)  {  	unsigned int attrwords = XDR_QUADLEN(attrlen); -	unsigned int nwords = xdr->p - savep; +	unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2;  	if (unlikely(attrwords != nwords)) {  		dprintk("%s: server returned incorrect attribute length: " @@ -4158,13 +4152,18 @@ static int decode_verifier(struct xdr_stream *xdr, void *verifier)  	return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);  } +static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier) +{ +	return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE); +} +  static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)  {  	int status;  	status = decode_op_hdr(xdr, OP_COMMIT);  	if (!status) -		status = decode_verifier(xdr, res->verf->verifier); +		status = decode_write_verifier(xdr, &res->verf->verifier);  	return status;  } @@ -4193,7 +4192,7 @@ out_overflow:  static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)  { -	__be32 *savep; +	unsigned int savep;  	uint32_t attrlen, bitmap[3] = {0};  	int status; @@ -4222,7 +4221,7 @@ xdr_error:  static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)  { -	__be32 *savep; +	unsigned int savep;  	uint32_t attrlen, bitmap[3] = {0};  	int status; @@ -4254,7 +4253,7 @@ xdr_error:  static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)  { -	__be32 *savep; +	unsigned int savep;  	uint32_t attrlen, bitmap[3] = {0};  	int status; @@ -4299,7 +4298,8 @@ out_overflow:  static int decode_first_threshold_item4(struct xdr_stream *xdr,  					struct nfs4_threshold *res)  { -	__be32 *p, *savep; +	__be32 *p; +	unsigned int savep;  	uint32_t bitmap[3] = {0,}, attrlen;  	int status; @@ -4503,7 +4503,7 @@ static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fat  		struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,  		const struct nfs_server *server)  { -	__be32 *savep; +	unsigned int savep;  	uint32_t attrlen,  		 bitmap[3] = {0};  	int status; @@ -4615,7 +4615,7 @@ static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,  static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)  { -	__be32 *savep; +	unsigned int savep;  	uint32_t attrlen, bitmap[3];  	int status; @@ -4920,9 +4920,8 @@ static int decode_putrootfh(struct xdr_stream *xdr)  static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)  { -	struct kvec *iov = req->rq_rcv_buf.head;  	__be32 *p; -	uint32_t count, eof, recvd, hdrlen; +	uint32_t count, eof, recvd;  	int status;  	status = decode_op_hdr(xdr, OP_READ); @@ -4933,15 +4932,13 @@ static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_  		goto out_overflow;  	eof = be32_to_cpup(p++);  	count = be32_to_cpup(p); -	hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; -	recvd = req->rq_rcv_buf.len - hdrlen; +	recvd = xdr_read_pages(xdr, count);  	if (count > recvd) {  		dprintk("NFS: server cheating in read reply: "  				"count %u > recvd %u\n", count, recvd);  		count = recvd;  		eof = 0;  	} -	xdr_read_pages(xdr, count);  	res->eof = eof;  	res->count = count;  	return 0; @@ -4952,10 +4949,6 @@ out_overflow:  static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)  { -	struct xdr_buf	*rcvbuf = &req->rq_rcv_buf; -	struct kvec	*iov = rcvbuf->head; -	size_t		hdrlen; -	u32		recvd, pglen = rcvbuf->page_len;  	int		status;  	__be32		verf[2]; @@ -4967,22 +4960,12 @@ static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct n  	memcpy(verf, readdir->verifier.data, sizeof(verf));  	dprintk("%s: verifier = %08x:%08x\n",  			__func__, verf[0], verf[1]); - -	hdrlen = (char *) xdr->p - (char *) iov->iov_base; -	recvd = rcvbuf->len - hdrlen; -	if (pglen > recvd) -		pglen = recvd; -	xdr_read_pages(xdr, pglen); - - -	return pglen; +	return xdr_read_pages(xdr, xdr->buf->page_len);  }  static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)  {  	struct xdr_buf *rcvbuf = &req->rq_rcv_buf; -	struct kvec *iov = rcvbuf->head; -	size_t hdrlen;  	u32 len, recvd;  	__be32 *p;  	int status; @@ -5000,14 +4983,12 @@ static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)  		dprintk("nfs: server returned giant symlink!\n");  		return -ENAMETOOLONG;  	} -	hdrlen = (char *) xdr->p - (char *) iov->iov_base; -	recvd = req->rq_rcv_buf.len - hdrlen; +	recvd = xdr_read_pages(xdr, len);  	if (recvd < len) {  		dprintk("NFS: server cheating in readlink reply: "  				"count %u > recvd %u\n", len, recvd);  		return -EIO;  	} -	xdr_read_pages(xdr, len);  	/*  	 * The XDR encode routine has set things up so that  	 * the link text will be copied directly into the @@ -5063,10 +5044,10 @@ decode_restorefh(struct xdr_stream *xdr)  static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  			 struct nfs_getaclres *res)  { -	__be32 *savep, *bm_p; +	unsigned int savep; +	__be32 *bm_p;  	uint32_t attrlen,  		 bitmap[3] = {0}; -	struct kvec *iov = req->rq_rcv_buf.head;  	int status;  	size_t page_len = xdr->buf->page_len; @@ -5089,7 +5070,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))  		return -EIO;  	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) { -		size_t hdrlen;  		/* The bitmap (xdr len + bitmaps) and the attr xdr len words  		 * are stored with the acl data to handle the problem of @@ -5098,7 +5078,6 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,  		/* We ignore &savep and don't do consistency checks on  		 * the attr length.  Let userspace figure it out.... */ -		hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;  		attrlen += res->acl_data_offset;  		if (attrlen > page_len) {  			if (res->acl_flags & NFS4_ACL_LEN_REQUEST) { @@ -5212,13 +5191,12 @@ static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)  	if (status)  		return status; -	p = xdr_inline_decode(xdr, 16); +	p = xdr_inline_decode(xdr, 8);  	if (unlikely(!p))  		goto out_overflow;  	res->count = be32_to_cpup(p++);  	res->verf->committed = be32_to_cpup(p++); -	memcpy(res->verf->verifier, p, NFS4_VERIFIER_SIZE); -	return 0; +	return decode_write_verifier(xdr, &res->verf->verifier);  out_overflow:  	print_overflow_msg(__func__, xdr);  	return -EIO; @@ -5599,7 +5577,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr,  {  	__be32 *p;  	int status, i; -	struct nfs_writeverf verftemp; +	nfs4_verifier verftemp;  	status = decode_op_hdr(xdr, OP_GETDEVICELIST);  	if (status) @@ -5613,7 +5591,7 @@ static int decode_getdevicelist(struct xdr_stream *xdr,  	p += 2;  	/* Read verifier */ -	p = xdr_decode_opaque_fixed(p, verftemp.verifier, NFS4_VERIFIER_SIZE); +	p = xdr_decode_opaque_fixed(p, verftemp.data, NFS4_VERIFIER_SIZE);  	res->num_devs = be32_to_cpup(p); @@ -5707,9 +5685,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,  	__be32 *p;  	int status;  	u32 layout_count; -	struct xdr_buf *rcvbuf = &req->rq_rcv_buf; -	struct kvec *iov = rcvbuf->head; -	u32 hdrlen, recvd; +	u32 recvd;  	status = decode_op_hdr(xdr, OP_LAYOUTGET);  	if (status) @@ -5746,8 +5722,7 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,  		res->type,  		res->layoutp->len); -	hdrlen = (u8 *) xdr->p - (u8 *) iov->iov_base; -	recvd = req->rq_rcv_buf.len - hdrlen; +	recvd = xdr_read_pages(xdr, res->layoutp->len);  	if (res->layoutp->len > recvd) {  		dprintk("NFS: server cheating in layoutget reply: "  				"layout len %u > recvd %u\n", @@ -5755,8 +5730,6 @@ static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,  		return -EINVAL;  	} -	xdr_read_pages(xdr, res->layoutp->len); -  	if (layout_count > 1) {  		/* We only handle a length one array at the moment.  Any  		 * further entries are just ignored.  Note that this means @@ -7103,6 +7076,7 @@ out:  int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,  		       int plus)  { +	unsigned int savep;  	uint32_t bitmap[3] = {0};  	uint32_t len;  	__be32 *p = xdr_inline_decode(xdr, 4); @@ -7141,7 +7115,7 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,  	if (decode_attr_bitmap(xdr, bitmap) < 0)  		goto out_overflow; -	if (decode_attr_length(xdr, &len, &p) < 0) +	if (decode_attr_length(xdr, &len, &savep) < 0)  		goto out_overflow;  	if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,  |