Skip to content
Snippets Groups Projects
nfs4xdr.c 189 KiB
Newer Older
  • Learn to ignore specific revisions
  • 			dprintk("nfs: couldn't resolve uid %d to string\n",
    					iap->ia_uid);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    			/* XXX */
    			strcpy(owner_name, "nobody");
    			owner_namelen = sizeof("nobody") - 1;
    			/* goto out; */
    		}
    		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
    	}
    	if (iap->ia_valid & ATTR_GID) {
    
    		owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		if (owner_grouplen < 0) {
    
    			dprintk("nfs: couldn't resolve gid %d to string\n",
    					iap->ia_gid);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    			strcpy(owner_group, "nobody");
    			owner_grouplen = sizeof("nobody") - 1;
    			/* goto out; */
    		}
    		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
    	}
    	if (iap->ia_valid & ATTR_ATIME_SET)
    		len += 16;
    	else if (iap->ia_valid & ATTR_ATIME)
    		len += 4;
    	if (iap->ia_valid & ATTR_MTIME_SET)
    		len += 16;
    	else if (iap->ia_valid & ATTR_MTIME)
    		len += 4;
    
    	p = reserve_space(xdr, len);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	/*
    	 * We write the bitmap length now, but leave the bitmap and the attribute
    	 * buffer length to be backfilled at the end of this routine.
    	 */
    
    	*p++ = cpu_to_be32(2);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	q = p;
    	p += 3;
    
    	if (iap->ia_valid & ATTR_SIZE) {
    		bmval0 |= FATTR4_WORD0_SIZE;
    
    		p = xdr_encode_hyper(p, iap->ia_size);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	if (iap->ia_valid & ATTR_MODE) {
    		bmval1 |= FATTR4_WORD1_MODE;
    
    		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	if (iap->ia_valid & ATTR_UID) {
    		bmval1 |= FATTR4_WORD1_OWNER;
    
    		p = xdr_encode_opaque(p, owner_name, owner_namelen);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	if (iap->ia_valid & ATTR_GID) {
    		bmval1 |= FATTR4_WORD1_OWNER_GROUP;
    
    		p = xdr_encode_opaque(p, owner_group, owner_grouplen);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	if (iap->ia_valid & ATTR_ATIME_SET) {
    		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
    
    		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
    		*p++ = cpu_to_be32(0);
    
    		*p++ = cpu_to_be32(iap->ia_atime.tv_sec);
    		*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	else if (iap->ia_valid & ATTR_ATIME) {
    		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
    
    		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	if (iap->ia_valid & ATTR_MTIME_SET) {
    		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
    
    		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
    		*p++ = cpu_to_be32(0);
    		*p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
    		*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	else if (iap->ia_valid & ATTR_MTIME) {
    		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
    
    		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	/*
    	 * Now we backfill the bitmap and the attribute buffer length.
    	 */
    	if (len != ((char *)p - (char *)q) + 4) {
    
    		printk(KERN_ERR "NFS: Attr length error, %u != %Zu\n",
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    				len, ((char *)p - (char *)q) + 4);
    		BUG();
    	}
    	len = (char *)p - (char *)q - 12;
    	*q++ = htonl(bmval0);
    	*q++ = htonl(bmval1);
    
    	*q = htonl(len);
    
    static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr);
    	encode_uint32(xdr, access);
    
    static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr);
    
    	encode_nfs4_seqid(xdr, arg->seqid);
    
    	encode_nfs4_stateid(xdr, arg->stateid);
    
    static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
    	p = reserve_space(xdr, 12);
    
    	p = xdr_encode_hyper(p, args->offset);
    
    	*p = cpu_to_be32(args->count);
    
    static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    	encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr);
    	encode_uint32(xdr, create->ftype);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	switch (create->ftype) {
    	case NF4LNK:
    
    		*p = cpu_to_be32(create->u.symlink.len);
    
    		xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		break;
    
    	case NF4BLK: case NF4CHR:
    
    		*p++ = cpu_to_be32(create->u.device.specdata1);
    
    		*p = cpu_to_be32(create->u.device.specdata2);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    		break;
    
    	default:
    		break;
    	}
    
    
    	encode_string(xdr, create->name->len, create->name->name);
    
    	encode_attrs(xdr, create->attrs, create->server);
    
    static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
    	p = reserve_space(xdr, 8);
    
    	*p++ = cpu_to_be32(1);
    
    	*p = cpu_to_be32(bitmap);
    
    static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
    	p = reserve_space(xdr, 12);
    
    	*p++ = cpu_to_be32(2);
    	*p++ = cpu_to_be32(bm0);
    
    	*p = cpu_to_be32(bm1);
    
    static void
    encode_getattr_three(struct xdr_stream *xdr,
    		     uint32_t bm0, uint32_t bm1, uint32_t bm2,
    		     struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    
    	encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
    
    	if (bm2) {
    		p = reserve_space(xdr, 16);
    		*p++ = cpu_to_be32(3);
    		*p++ = cpu_to_be32(bm0);
    		*p++ = cpu_to_be32(bm1);
    		*p = cpu_to_be32(bm2);
    	} else if (bm1) {
    		p = reserve_space(xdr, 12);
    		*p++ = cpu_to_be32(2);
    		*p++ = cpu_to_be32(bm0);
    		*p = cpu_to_be32(bm1);
    	} else {
    		p = reserve_space(xdr, 8);
    		*p++ = cpu_to_be32(1);
    		*p = cpu_to_be32(bm0);
    	}
    }
    
    
    static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
    			   bitmask[1] & nfs4_fattr_bitmap[1], hdr);
    
    static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
    
    				 const u32 *open_bitmap,
    
    				 struct compound_hdr *hdr)
    {
    	encode_getattr_three(xdr,
    
    			     bitmask[0] & open_bitmap[0],
    			     bitmask[1] & open_bitmap[1],
    			     bitmask[2] & open_bitmap[2],
    
    static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_getattr_three(xdr,
    			     bitmask[0] & nfs4_fsinfo_bitmap[0],
    			     bitmask[1] & nfs4_fsinfo_bitmap[1],
    			     bitmask[2] & nfs4_fsinfo_bitmap[2],
    			     hdr);
    
    static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
    
    	encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0],
    			   bitmask[1] & nfs4_fs_locations_bitmap[1], hdr);
    
    static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr);
    
    static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr);
    
    	encode_string(xdr, name->len, name->name);
    
    static inline int nfs4_lock_type(struct file_lock *fl, int block)
    {
    
    	if (fl->fl_type == F_RDLCK)
    
    		return block ? NFS4_READW_LT : NFS4_READ_LT;
    	return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
    }
    
    static inline uint64_t nfs4_lock_length(struct file_lock *fl)
    {
    	if (fl->fl_end == OFFSET_MAX)
    		return ~(uint64_t)0;
    	return fl->fl_end - fl->fl_start + 1;
    }
    
    
    static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
    {
    	__be32 *p;
    
    
    	p = reserve_space(xdr, 32);
    
    	p = xdr_encode_hyper(p, lowner->clientid);
    
    	p = xdr_encode_opaque_fixed(p, "lock id:", 8);
    
    	*p++ = cpu_to_be32(lowner->s_dev);
    
    	xdr_encode_hyper(p, lowner->id);
    }
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    /*
     * opcode,type,reclaim,offset,length,new_lock_owner = 32
     * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
     */
    
    static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr);
    	p = reserve_space(xdr, 28);
    
    	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
    	*p++ = cpu_to_be32(args->reclaim);
    
    	p = xdr_encode_hyper(p, args->fl->fl_start);
    	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
    
    	*p = cpu_to_be32(args->new_lock_owner);
    
    	if (args->new_lock_owner){
    
    		encode_nfs4_seqid(xdr, args->open_seqid);
    
    		encode_nfs4_stateid(xdr, args->open_stateid);
    
    		encode_nfs4_seqid(xdr, args->lock_seqid);
    
    		encode_lockowner(xdr, &args->lock_owner);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    	else {
    
    		encode_nfs4_stateid(xdr, args->lock_stateid);
    
    		encode_nfs4_seqid(xdr, args->lock_seqid);
    
    static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr);
    	p = reserve_space(xdr, 20);
    
    	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
    
    	p = xdr_encode_hyper(p, args->fl->fl_start);
    	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
    
    	encode_lockowner(xdr, &args->lock_owner);
    
    static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr);
    	encode_uint32(xdr, nfs4_lock_type(args->fl, 0));
    
    	encode_nfs4_seqid(xdr, args->seqid);
    
    	encode_nfs4_stateid(xdr, args->stateid);
    	p = reserve_space(xdr, 16);
    
    	p = xdr_encode_hyper(p, args->fl->fl_start);
    
    	xdr_encode_hyper(p, nfs4_lock_length(args->fl));
    
    static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
    {
    
    	encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr);
    
    static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr);
    
    	encode_string(xdr, name->len, name->name);
    
    static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	switch (fmode & (FMODE_READ|FMODE_WRITE)) {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	case FMODE_READ:
    
    		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	case FMODE_WRITE:
    
    		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	case FMODE_READ|FMODE_WRITE:
    
    		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	default:
    
    		*p++ = cpu_to_be32(0);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    
    	*p = cpu_to_be32(0);		/* for linux, share_deny = 0 always */
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
     /*
     * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
     * owner 4 = 32
     */
    
    	encode_nfs4_seqid(xdr, arg->seqid);
    
    	encode_share_access(xdr, arg->fmode);
    
    	p = reserve_space(xdr, 36);
    
    	p = xdr_encode_hyper(p, arg->clientid);
    
    	*p++ = cpu_to_be32(24);
    
    	p = xdr_encode_opaque_fixed(p, "open id:", 8);
    
    	*p++ = cpu_to_be32(arg->server->s_dev);
    
    	*p++ = cpu_to_be32(arg->id.uniquifier);
    	xdr_encode_hyper(p, arg->id.create_time);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	switch(arg->open_flags & O_EXCL) {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	case 0:
    
    		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		encode_attrs(xdr, arg->u.attrs, arg->server);
    		break;
    	default:
    
    		clp = arg->server->nfs_client;
    
    		if (clp->cl_mvops->minor_version > 0) {
    
    			if (nfs4_has_persistent_session(clp)) {
    				*p = cpu_to_be32(NFS4_CREATE_GUARDED);
    				encode_attrs(xdr, arg->u.attrs, arg->server);
    			} else {
    				struct iattr dummy;
    
    				*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
    				encode_nfs4_verifier(xdr, &arg->u.verifier);
    				dummy.ia_valid = 0;
    				encode_attrs(xdr, &dummy, arg->server);
    			}
    		} else {
    			*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
    			encode_nfs4_verifier(xdr, &arg->u.verifier);
    		}
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    }
    
    static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	switch (arg->open_flags & O_CREAT) {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	case 0:
    
    		*p = cpu_to_be32(NFS4_OPEN_NOCREATE);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	default:
    		BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
    
    		*p = cpu_to_be32(NFS4_OPEN_CREATE);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		encode_createmode(xdr, arg);
    
    static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	switch (delegation_type) {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	case 0:
    
    		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	case FMODE_READ:
    
    		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	case FMODE_WRITE|FMODE_READ:
    
    		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
    
    Andy Adamson's avatar
    Andy Adamson committed
    		break;
    	default:
    		BUG();
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	}
    }
    
    static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	*p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	encode_string(xdr, name->len, name->name);
    }
    
    
    static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	*p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	encode_delegation_type(xdr, type);
    }
    
    static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	p = reserve_space(xdr, 4);
    	*p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
    	encode_nfs4_stateid(xdr, stateid);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	encode_string(xdr, name->len, name->name);
    }
    
    
    static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	encode_openhdr(xdr, arg);
    	encode_opentype(xdr, arg);
    	switch (arg->claim) {
    
    Andy Adamson's avatar
    Andy Adamson committed
    	case NFS4_OPEN_CLAIM_NULL:
    		encode_claim_null(xdr, arg->name);
    		break;
    	case NFS4_OPEN_CLAIM_PREVIOUS:
    		encode_claim_previous(xdr, arg->u.delegation_type);
    		break;
    	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
    		encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
    		break;
    	default:
    		BUG();
    
    static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr);
    
    	encode_nfs4_stateid(xdr, arg->stateid);
    
    	encode_nfs4_seqid(xdr, arg->seqid);
    
    static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
    
    	encode_nfs4_stateid(xdr, arg->stateid);
    
    	encode_nfs4_seqid(xdr, arg->seqid);
    
    	encode_share_access(xdr, arg->fmode);
    
    encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr);
    
    	encode_string(xdr, fh->size, fh->data);
    
    static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
    
    static void encode_open_stateid(struct xdr_stream *xdr,
    		const struct nfs_open_context *ctx,
    		const struct nfs_lock_context *l_ctx,
    		fmode_t fmode,
    		int zero_seqid)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    	nfs4_stateid stateid;
    
    	if (ctx->state != NULL) {
    
    		const struct nfs_lockowner *lockowner = NULL;
    
    		if (l_ctx != NULL)
    			lockowner = &l_ctx->lockowner;
    
    		nfs4_select_rw_stateid(&stateid, ctx->state,
    
    			stateid.seqid = 0;
    
    		encode_nfs4_stateid(xdr, &stateid);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	} else
    
    		encode_nfs4_stateid(xdr, &zero_stateid);
    
    static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
    
    	encode_open_stateid(xdr, args->context, args->lock_context,
    
    			FMODE_READ, hdr->minorversion);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	p = reserve_space(xdr, 12);
    
    	p = xdr_encode_hyper(p, args->offset);
    
    	*p = cpu_to_be32(args->count);
    
    static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	uint32_t attrs[2] = {
    		FATTR4_WORD0_RDATTR_ERROR,
    		FATTR4_WORD1_MOUNTED_ON_FILEID,
    	};
    
    	uint32_t dircount = readdir->count >> 1;
    
    	__be32 *p, verf[2];
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    Bryan Schumaker's avatar
    Bryan Schumaker committed
    	if (readdir->plus) {
    		attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
    
    			FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
    
    Bryan Schumaker's avatar
    Bryan Schumaker committed
    		attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
    			FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
    			FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
    			FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
    
    	/* Use mounted_on_fileid only if the server supports it */
    	if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
    		attrs[0] |= FATTR4_WORD0_FILEID;
    
    	encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
    
    	encode_uint64(xdr, readdir->cookie);
    
    	encode_nfs4_verifier(xdr, &readdir->verifier);
    	p = reserve_space(xdr, 20);
    
    	*p++ = cpu_to_be32(dircount);
    
    	*p++ = cpu_to_be32(readdir->count);
    	*p++ = cpu_to_be32(2);
    
    	*p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
    
    	*p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
    
    	memcpy(verf, readdir->verifier.data, sizeof(verf));
    
    	dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
    			__func__,
    
    			(unsigned long long)readdir->cookie,
    
    			verf[0], verf[1],
    
    			attrs[0] & readdir->bitmask[0],
    			attrs[1] & readdir->bitmask[1]);
    
    static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr);
    
    static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr);
    
    	encode_string(xdr, name->len, name->name);
    
    static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr);
    
    	encode_string(xdr, oldname->len, oldname->name);
    	encode_string(xdr, newname->len, newname->name);
    
    static void encode_renew(struct xdr_stream *xdr, clientid4 clid,
    			 struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr);
    
    	encode_uint64(xdr, clid);
    
    encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
    
    	encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr);
    
    encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    	encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr);
    
    	encode_nfs4_stateid(xdr, &zero_stateid);
    
    	p = reserve_space(xdr, 2*4);
    
    	*p++ = cpu_to_be32(1);
    
    	*p = cpu_to_be32(FATTR4_WORD0_ACL);
    
    	BUG_ON(arg->acl_len % 4);
    
    	*p = cpu_to_be32(arg->acl_len);
    
    	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
    }
    
    
    encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr);
    
    static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
    
    	encode_nfs4_stateid(xdr, &arg->stateid);
    
    	encode_attrs(xdr, arg->iap, server);
    
    static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr);
    
    	encode_nfs4_verifier(xdr, setclientid->sc_verifier);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
    
    	*p = cpu_to_be32(setclientid->sc_prog);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
    	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
    
    	*p = cpu_to_be32(setclientid->sc_cb_ident);
    
    static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM,
    			decode_setclientid_confirm_maxsz, hdr);
    
    	encode_uint64(xdr, arg->clientid);
    
    	encode_nfs4_verifier(xdr, &arg->confirm);
    
    static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    Al Viro's avatar
    Al Viro committed
    	__be32 *p;
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
    
    	encode_open_stateid(xdr, args->context, args->lock_context,
    
    			FMODE_WRITE, hdr->minorversion);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    
    	p = reserve_space(xdr, 16);
    
    	p = xdr_encode_hyper(p, args->offset);
    
    	*p++ = cpu_to_be32(args->stable);
    
    	*p = cpu_to_be32(args->count);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    
    	xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
    }
    
    
    static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    {
    
    	encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr);
    
    	encode_nfs4_stateid(xdr, stateid);
    
    Linus Torvalds's avatar
    Linus Torvalds committed
    }
    
    static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
    {
    
    	encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr);
    
    	encode_string(xdr, name->len, name->name);
    
    #if defined(CONFIG_NFS_V4_1)
    
    /* NFSv4.1 operations */
    
    static void encode_bind_conn_to_session(struct xdr_stream *xdr,
    				   struct nfs4_session *session,
    				   struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    	encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
    		decode_bind_conn_to_session_maxsz, hdr);
    	encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
    	p = xdr_reserve_space(xdr, 8);
    	*p++ = cpu_to_be32(NFS4_CDFC4_BACK_OR_BOTH);
    	*p = 0;	/* use_conn_in_rdma_mode = False */
    }
    
    
    static void encode_exchange_id(struct xdr_stream *xdr,
    			       struct nfs41_exchange_id_args *args,
    			       struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    	char impl_name[NFS4_OPAQUE_LIMIT];
    	int len = 0;
    
    	encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
    
    	encode_nfs4_verifier(xdr, args->verifier);
    
    
    	encode_string(xdr, args->id_len, args->id);
    
    
    	p = reserve_space(xdr, 12);
    
    	*p++ = cpu_to_be32(args->flags);
    	*p++ = cpu_to_be32(0);	/* zero length state_protect4_a */
    
    
    	if (send_implementation_id &&
    	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
    	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
    		<= NFS4_OPAQUE_LIMIT + 1)
    		len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
    			       utsname()->sysname, utsname()->release,
    			       utsname()->version, utsname()->machine);
    
    	if (len > 0) {
    		*p = cpu_to_be32(1);	/* implementation id array length=1 */
    
    		encode_string(xdr,
    			sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1,
    			CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN);
    		encode_string(xdr, len, impl_name);
    		/* just send zeros for nii_date - the date is in nii_name */
    		p = reserve_space(xdr, 12);
    		p = xdr_encode_hyper(p, 0);
    		*p = cpu_to_be32(0);
    	} else
    		*p = cpu_to_be32(0);	/* implementation id array length=0 */
    
    
    static void encode_create_session(struct xdr_stream *xdr,
    				  struct nfs41_create_session_args *args,
    				  struct compound_hdr *hdr)
    {
    	__be32 *p;
    	char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
    	uint32_t len;
    	struct nfs_client *clp = args->client;
    
    	struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
    
    	u32 max_resp_sz_cached;
    
    	/*
    	 * Assumes OPEN is the biggest non-idempotent compound.
    	 * 2 is the verifier.
    	 */
    	max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
    			      RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
    
    	len = scnprintf(machine_name, sizeof(machine_name), "%s",
    			clp->cl_ipaddr);
    
    	encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
    	p = reserve_space(xdr, 16 + 2*28 + 20 + len + 12);
    
    	p = xdr_encode_hyper(p, clp->cl_clientid);
    
    	*p++ = cpu_to_be32(clp->cl_seqid);			/*Sequence id */
    	*p++ = cpu_to_be32(args->flags);			/*flags */
    
    
    	/* Fore Channel */
    
    	*p++ = cpu_to_be32(0);				/* header padding size */
    
    	*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz);	/* max req size */
    	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz);	/* max resp size */
    
    	*p++ = cpu_to_be32(max_resp_sz_cached);		/* Max resp sz cached */
    
    	*p++ = cpu_to_be32(args->fc_attrs.max_ops);	/* max operations */
    	*p++ = cpu_to_be32(args->fc_attrs.max_reqs);	/* max requests */
    	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
    
    
    	/* Back Channel */
    
    	*p++ = cpu_to_be32(0);				/* header padding size */
    
    	*p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz);	/* max req size */
    	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz);	/* max resp size */
    	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached);	/* Max resp sz cached */
    	*p++ = cpu_to_be32(args->bc_attrs.max_ops);	/* max operations */
    	*p++ = cpu_to_be32(args->bc_attrs.max_reqs);	/* max requests */
    	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
    
    	*p++ = cpu_to_be32(args->cb_program);		/* cb_program */
    	*p++ = cpu_to_be32(1);
    	*p++ = cpu_to_be32(RPC_AUTH_UNIX);			/* auth_sys */
    
    
    	/* authsys_parms rfc1831 */
    
    	*p++ = (__be32)nn->boot_time.tv_nsec;		/* stamp */
    
    	p = xdr_encode_opaque(p, machine_name, len);
    
    	*p++ = cpu_to_be32(0);				/* UID */
    	*p++ = cpu_to_be32(0);				/* GID */
    
    	*p = cpu_to_be32(0);				/* No more gids */
    
    
    static void encode_destroy_session(struct xdr_stream *xdr,
    				   struct nfs4_session *session,
    				   struct compound_hdr *hdr)
    {
    
    	encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr);
    	encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
    
    static void encode_destroy_clientid(struct xdr_stream *xdr,
    				   uint64_t clientid,
    				   struct compound_hdr *hdr)
    {
    	encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr);
    	encode_uint64(xdr, clientid);
    }
    
    
    static void encode_reclaim_complete(struct xdr_stream *xdr,
    				    struct nfs41_reclaim_complete_args *args,
    				    struct compound_hdr *hdr)
    {
    
    	encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr);
    	encode_uint32(xdr, args->one_fs);
    
    #endif /* CONFIG_NFS_V4_1 */
    
    
    static void encode_sequence(struct xdr_stream *xdr,
    			    const struct nfs4_sequence_args *args,
    			    struct compound_hdr *hdr)
    {
    #if defined(CONFIG_NFS_V4_1)
    	struct nfs4_session *session = args->sa_session;
    
    Andy Adamson's avatar
    Andy Adamson committed
    	struct nfs4_slot_table *tp;
    	struct nfs4_slot *slot;
    	__be32 *p;
    
    Andy Adamson's avatar
    Andy Adamson committed
    	tp = &session->fc_slot_table;
    
    	WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
    	slot = tp->slots + args->sa_slotid;
    
    
    	encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
    
    Andy Adamson's avatar
    Andy Adamson committed
    
    	/*
    	 * Sessionid + seqid + slotid + max slotid + cache_this
    	 */
    	dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
    		"max_slotid=%d cache_this=%d\n",
    		__func__,
    		((u32 *)session->sess_id.data)[0],
    		((u32 *)session->sess_id.data)[1],
    		((u32 *)session->sess_id.data)[2],
    		((u32 *)session->sess_id.data)[3],
    		slot->seq_nr, args->sa_slotid,
    		tp->highest_used_slotid, args->sa_cache_this);
    
    	p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
    
    	p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
    
    	*p++ = cpu_to_be32(slot->seq_nr);
    	*p++ = cpu_to_be32(args->sa_slotid);
    	*p++ = cpu_to_be32(tp->highest_used_slotid);
    
    	*p = cpu_to_be32(args->sa_cache_this);
    
    #endif /* CONFIG_NFS_V4_1 */
    }
    
    
    Andy Adamson's avatar
    Andy Adamson committed
    static void
    encode_getdevicelist(struct xdr_stream *xdr,
    		     const struct nfs4_getdevicelist_args *args,
    		     struct compound_hdr *hdr)
    {
    	__be32 *p;
    	nfs4_verifier dummy = {
    		.data = "dummmmmy",
    	};
    
    
    	encode_op_hdr(xdr, OP_GETDEVICELIST, decode_getdevicelist_maxsz, hdr);
    	p = reserve_space(xdr, 16);
    
    Andy Adamson's avatar
    Andy Adamson committed
    	*p++ = cpu_to_be32(args->layoutclass);
    	*p++ = cpu_to_be32(NFS4_PNFS_GETDEVLIST_MAXNUM);
    	xdr_encode_hyper(p, 0ULL);                          /* cookie */
    	encode_nfs4_verifier(xdr, &dummy);
    }
    
    
    static void
    encode_getdeviceinfo(struct xdr_stream *xdr,
    		     const struct nfs4_getdeviceinfo_args *args,
    		     struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    
    	encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr);
    	p = reserve_space(xdr, 12 + NFS4_DEVICEID4_SIZE);
    
    	p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
    				    NFS4_DEVICEID4_SIZE);
    	*p++ = cpu_to_be32(args->pdev->layout_type);
    	*p++ = cpu_to_be32(args->pdev->pglen);		/* gdia_maxcount */
    	*p++ = cpu_to_be32(0);				/* bitmap length 0 */
    }
    
    static void
    encode_layoutget(struct xdr_stream *xdr,
    		      const struct nfs4_layoutget_args *args,
    		      struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    
    	encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr);
    	p = reserve_space(xdr, 36);
    
    	*p++ = cpu_to_be32(0);     /* Signal layout available */
    	*p++ = cpu_to_be32(args->type);
    	*p++ = cpu_to_be32(args->range.iomode);
    	p = xdr_encode_hyper(p, args->range.offset);
    	p = xdr_encode_hyper(p, args->range.length);
    	p = xdr_encode_hyper(p, args->minlength);
    
    	encode_nfs4_stateid(xdr, &args->stateid);
    
    	encode_uint32(xdr, args->maxcount);
    
    
    	dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
    		__func__,
    		args->type,
    		args->range.iomode,
    		(unsigned long)args->range.offset,
    		(unsigned long)args->range.length,
    		args->maxcount);
    }
    
    Andy Adamson's avatar
    Andy Adamson committed
    
    static int
    encode_layoutcommit(struct xdr_stream *xdr,
    
    Benny Halevy's avatar
    Benny Halevy committed
    		    struct inode *inode,
    
    Andy Adamson's avatar
    Andy Adamson committed
    		    const struct nfs4_layoutcommit_args *args,
    		    struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    	dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,
    		NFS_SERVER(args->inode)->pnfs_curr_ld->id);
    
    
    	encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr);
    	p = reserve_space(xdr, 20);
    
    Andy Adamson's avatar
    Andy Adamson committed
    	/* Only whole file layouts */
    	p = xdr_encode_hyper(p, 0); /* offset */
    
    	p = xdr_encode_hyper(p, args->lastbytewritten + 1);	/* length */
    
    	*p = cpu_to_be32(0); /* reclaim */
    	encode_nfs4_stateid(xdr, &args->stateid);
    	p = reserve_space(xdr, 20);
    
    Andy Adamson's avatar
    Andy Adamson committed
    	*p++ = cpu_to_be32(1); /* newoffset = TRUE */
    	p = xdr_encode_hyper(p, args->lastbytewritten);
    	*p++ = cpu_to_be32(0); /* Never send time_modify_changed */
    	*p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
    
    Benny Halevy's avatar
    Benny Halevy committed
    
    	if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit)
    		NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit(
    			NFS_I(inode)->layout, xdr, args);
    
    	else
    		encode_uint32(xdr, 0); /* no layout-type payload */
    
    Andy Adamson's avatar
    Andy Adamson committed
    
    	return 0;
    }
    
    Benny Halevy's avatar
    Benny Halevy committed
    
    static void
    encode_layoutreturn(struct xdr_stream *xdr,
    		    const struct nfs4_layoutreturn_args *args,
    		    struct compound_hdr *hdr)
    {
    	__be32 *p;
    
    
    	encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr);
    	p = reserve_space(xdr, 16);
    
    Benny Halevy's avatar
    Benny Halevy committed
    	*p++ = cpu_to_be32(0);		/* reclaim. always 0 for now */
    	*p++ = cpu_to_be32(args->layout_type);
    	*p++ = cpu_to_be32(IOMODE_ANY);
    	*p = cpu_to_be32(RETURN_FILE);
    
    	p = reserve_space(xdr, 16);
    
    Benny Halevy's avatar
    Benny Halevy committed
    	p = xdr_encode_hyper(p, 0);
    	p = xdr_encode_hyper(p, NFS4_MAX_UINT64);
    	spin_lock(&args->inode->i_lock);
    
    	encode_nfs4_stateid(xdr, &args->stateid);
    
    Benny Halevy's avatar
    Benny Halevy committed
    	spin_unlock(&args->inode->i_lock);
    
    Andy Adamson's avatar
    Andy Adamson committed
    	if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) {
    		NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn(
    			NFS_I(args->inode)->layout, xdr, args);
    
    	} else
    		encode_uint32(xdr, 0);
    
    Benny Halevy's avatar
    Benny Halevy committed
    }
    
    
    static int
    encode_secinfo_no_name(struct xdr_stream *xdr,
    		       const struct nfs41_secinfo_no_name_args *args,
    		       struct compound_hdr *hdr)
    {
    
    	encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr);