xref: /openbmc/linux/fs/nfs/nfs4xdr.c (revision 9af8c222)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  *  fs/nfs/nfs4xdr.c
31da177e4SLinus Torvalds  *
41da177e4SLinus Torvalds  *  Client-side XDR for NFSv4.
51da177e4SLinus Torvalds  *
61da177e4SLinus Torvalds  *  Copyright (c) 2002 The Regents of the University of Michigan.
71da177e4SLinus Torvalds  *  All rights reserved.
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  *  Kendrick Smith <kmsmith@umich.edu>
101da177e4SLinus Torvalds  *  Andy Adamson   <andros@umich.edu>
111da177e4SLinus Torvalds  *
121da177e4SLinus Torvalds  *  Redistribution and use in source and binary forms, with or without
131da177e4SLinus Torvalds  *  modification, are permitted provided that the following conditions
141da177e4SLinus Torvalds  *  are met:
151da177e4SLinus Torvalds  *
161da177e4SLinus Torvalds  *  1. Redistributions of source code must retain the above copyright
171da177e4SLinus Torvalds  *     notice, this list of conditions and the following disclaimer.
181da177e4SLinus Torvalds  *  2. Redistributions in binary form must reproduce the above copyright
191da177e4SLinus Torvalds  *     notice, this list of conditions and the following disclaimer in the
201da177e4SLinus Torvalds  *     documentation and/or other materials provided with the distribution.
211da177e4SLinus Torvalds  *  3. Neither the name of the University nor the names of its
221da177e4SLinus Torvalds  *     contributors may be used to endorse or promote products derived
231da177e4SLinus Torvalds  *     from this software without specific prior written permission.
241da177e4SLinus Torvalds  *
251da177e4SLinus Torvalds  *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
261da177e4SLinus Torvalds  *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
271da177e4SLinus Torvalds  *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
281da177e4SLinus Torvalds  *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
291da177e4SLinus Torvalds  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
301da177e4SLinus Torvalds  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
311da177e4SLinus Torvalds  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
321da177e4SLinus Torvalds  *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
331da177e4SLinus Torvalds  *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
341da177e4SLinus Torvalds  *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
351da177e4SLinus Torvalds  *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
361da177e4SLinus Torvalds  */
371da177e4SLinus Torvalds 
381da177e4SLinus Torvalds #include <linux/param.h>
391da177e4SLinus Torvalds #include <linux/time.h>
401da177e4SLinus Torvalds #include <linux/mm.h>
411da177e4SLinus Torvalds #include <linux/errno.h>
421da177e4SLinus Torvalds #include <linux/string.h>
431da177e4SLinus Torvalds #include <linux/in.h>
441da177e4SLinus Torvalds #include <linux/pagemap.h>
451da177e4SLinus Torvalds #include <linux/proc_fs.h>
461da177e4SLinus Torvalds #include <linux/kdev_t.h>
471da177e4SLinus Torvalds #include <linux/sunrpc/clnt.h>
482449ea2eSAlexandros Batsakis #include <linux/sunrpc/msg_prot.h>
491da177e4SLinus Torvalds #include <linux/nfs.h>
501da177e4SLinus Torvalds #include <linux/nfs4.h>
511da177e4SLinus Torvalds #include <linux/nfs_fs.h>
521da177e4SLinus Torvalds #include <linux/nfs_idmap.h>
534ce79717STrond Myklebust #include "nfs4_fs.h"
544882ef72SAlexandros Batsakis #include "internal.h"
551da177e4SLinus Torvalds 
561da177e4SLinus Torvalds #define NFSDBG_FACILITY		NFSDBG_XDR
571da177e4SLinus Torvalds 
581da177e4SLinus Torvalds /* Mapping from NFS error code to "errno" error code. */
591da177e4SLinus Torvalds #define errno_NFSERR_IO		EIO
601da177e4SLinus Torvalds 
610a8ea437SDavid Howells static int nfs4_stat_to_errno(int);
621da177e4SLinus Torvalds 
631da177e4SLinus Torvalds /* NFSv4 COMPOUND tags are only wanted for debugging purposes */
641da177e4SLinus Torvalds #ifdef DEBUG
651da177e4SLinus Torvalds #define NFS4_MAXTAGLEN		20
661da177e4SLinus Torvalds #else
671da177e4SLinus Torvalds #define NFS4_MAXTAGLEN		0
681da177e4SLinus Torvalds #endif
691da177e4SLinus Torvalds 
701da177e4SLinus Torvalds /* lock,open owner id:
719f958ab8STrond Myklebust  * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
721da177e4SLinus Torvalds  */
739f958ab8STrond Myklebust #define open_owner_id_maxsz	(1 + 4)
749f958ab8STrond Myklebust #define lock_owner_id_maxsz	(1 + 4)
759104a55dSTrond Myklebust #define decode_lockowner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
761da177e4SLinus Torvalds #define compound_encode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
771da177e4SLinus Torvalds #define compound_decode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
781da177e4SLinus Torvalds #define op_encode_hdr_maxsz	(1)
791da177e4SLinus Torvalds #define op_decode_hdr_maxsz	(2)
809104a55dSTrond Myklebust #define encode_stateid_maxsz	(XDR_QUADLEN(NFS4_STATEID_SIZE))
819104a55dSTrond Myklebust #define decode_stateid_maxsz	(XDR_QUADLEN(NFS4_STATEID_SIZE))
829104a55dSTrond Myklebust #define encode_verifier_maxsz	(XDR_QUADLEN(NFS4_VERIFIER_SIZE))
839104a55dSTrond Myklebust #define decode_verifier_maxsz	(XDR_QUADLEN(NFS4_VERIFIER_SIZE))
841da177e4SLinus Torvalds #define encode_putfh_maxsz	(op_encode_hdr_maxsz + 1 + \
851da177e4SLinus Torvalds 				(NFS4_FHSIZE >> 2))
861da177e4SLinus Torvalds #define decode_putfh_maxsz	(op_decode_hdr_maxsz)
871da177e4SLinus Torvalds #define encode_putrootfh_maxsz	(op_encode_hdr_maxsz)
881da177e4SLinus Torvalds #define decode_putrootfh_maxsz	(op_decode_hdr_maxsz)
891da177e4SLinus Torvalds #define encode_getfh_maxsz      (op_encode_hdr_maxsz)
901da177e4SLinus Torvalds #define decode_getfh_maxsz      (op_decode_hdr_maxsz + 1 + \
911da177e4SLinus Torvalds 				((3+NFS4_FHSIZE) >> 2))
9296928206SJ. Bruce Fields #define nfs4_fattr_bitmap_maxsz 3
9396928206SJ. Bruce Fields #define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
941da177e4SLinus Torvalds #define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
951da177e4SLinus Torvalds #define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
96bd625ba8STrond Myklebust #define nfs4_owner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
97bd625ba8STrond Myklebust #define nfs4_group_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
9896928206SJ. Bruce Fields /* This is based on getfattr, which uses the most attributes: */
9996928206SJ. Bruce Fields #define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
100bd625ba8STrond Myklebust 				3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
10196928206SJ. Bruce Fields #define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
10296928206SJ. Bruce Fields 				nfs4_fattr_value_maxsz)
10396928206SJ. Bruce Fields #define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
1049104a55dSTrond Myklebust #define encode_attrs_maxsz	(nfs4_fattr_bitmap_maxsz + \
1059104a55dSTrond Myklebust 				 1 + 2 + 1 + \
1069104a55dSTrond Myklebust 				nfs4_owner_maxsz + \
1079104a55dSTrond Myklebust 				nfs4_group_maxsz + \
1089104a55dSTrond Myklebust 				4 + 4)
1091da177e4SLinus Torvalds #define encode_savefh_maxsz     (op_encode_hdr_maxsz)
1101da177e4SLinus Torvalds #define decode_savefh_maxsz     (op_decode_hdr_maxsz)
11156ae19f3STrond Myklebust #define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
11256ae19f3STrond Myklebust #define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
1132f42b5d0SFred Isaman #define encode_fsinfo_maxsz	(encode_getattr_maxsz)
1141da177e4SLinus Torvalds #define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + 11)
1151da177e4SLinus Torvalds #define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
1161da177e4SLinus Torvalds #define decode_renew_maxsz	(op_decode_hdr_maxsz)
1171da177e4SLinus Torvalds #define encode_setclientid_maxsz \
1181da177e4SLinus Torvalds 				(op_encode_hdr_maxsz + \
119cc38bac3SChuck Lever 				XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
120cc38bac3SChuck Lever 				XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \
121cc38bac3SChuck Lever 				1 /* sc_prog */ + \
122cc38bac3SChuck Lever 				XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
123cc38bac3SChuck Lever 				XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
124cc38bac3SChuck Lever 				1) /* sc_cb_ident */
1251da177e4SLinus Torvalds #define decode_setclientid_maxsz \
1261da177e4SLinus Torvalds 				(op_decode_hdr_maxsz + \
1271da177e4SLinus Torvalds 				2 + \
1281da177e4SLinus Torvalds 				1024) /* large value for CLID_INUSE */
1291da177e4SLinus Torvalds #define encode_setclientid_confirm_maxsz \
1301da177e4SLinus Torvalds 				(op_encode_hdr_maxsz + \
1311da177e4SLinus Torvalds 				3 + (NFS4_VERIFIER_SIZE >> 2))
1321da177e4SLinus Torvalds #define decode_setclientid_confirm_maxsz \
1331da177e4SLinus Torvalds 				(op_decode_hdr_maxsz)
134e6889620STrond Myklebust #define encode_lookup_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
135e6889620STrond Myklebust #define decode_lookup_maxsz	(op_decode_hdr_maxsz)
1362cebf828STrond Myklebust #define encode_share_access_maxsz \
1372cebf828STrond Myklebust 				(2)
1384882ef72SAlexandros Batsakis #define encode_createmode_maxsz	(1 + encode_attrs_maxsz + encode_verifier_maxsz)
1392cebf828STrond Myklebust #define encode_opentype_maxsz	(1 + encode_createmode_maxsz)
1402cebf828STrond Myklebust #define encode_claim_null_maxsz	(1 + nfs4_name_maxsz)
1412cebf828STrond Myklebust #define encode_open_maxsz	(op_encode_hdr_maxsz + \
1422cebf828STrond Myklebust 				2 + encode_share_access_maxsz + 2 + \
1432cebf828STrond Myklebust 				open_owner_id_maxsz + \
1442cebf828STrond Myklebust 				encode_opentype_maxsz + \
1452cebf828STrond Myklebust 				encode_claim_null_maxsz)
1462cebf828STrond Myklebust #define decode_ace_maxsz	(3 + nfs4_owner_maxsz)
1479104a55dSTrond Myklebust #define decode_delegation_maxsz	(1 + decode_stateid_maxsz + 1 + \
1482cebf828STrond Myklebust 				decode_ace_maxsz)
1492cebf828STrond Myklebust #define decode_change_info_maxsz	(5)
1502cebf828STrond Myklebust #define decode_open_maxsz	(op_decode_hdr_maxsz + \
1519104a55dSTrond Myklebust 				decode_stateid_maxsz + \
1522cebf828STrond Myklebust 				decode_change_info_maxsz + 1 + \
1532cebf828STrond Myklebust 				nfs4_fattr_bitmap_maxsz + \
1542cebf828STrond Myklebust 				decode_delegation_maxsz)
1559104a55dSTrond Myklebust #define encode_open_confirm_maxsz \
1569104a55dSTrond Myklebust 				(op_encode_hdr_maxsz + \
1579104a55dSTrond Myklebust 				 encode_stateid_maxsz + 1)
1589104a55dSTrond Myklebust #define decode_open_confirm_maxsz \
1599104a55dSTrond Myklebust 				(op_decode_hdr_maxsz + \
1609104a55dSTrond Myklebust 				 decode_stateid_maxsz)
1619104a55dSTrond Myklebust #define encode_open_downgrade_maxsz \
1629104a55dSTrond Myklebust 				(op_encode_hdr_maxsz + \
1639104a55dSTrond Myklebust 				 encode_stateid_maxsz + 1 + \
1649104a55dSTrond Myklebust 				 encode_share_access_maxsz)
1659104a55dSTrond Myklebust #define decode_open_downgrade_maxsz \
1669104a55dSTrond Myklebust 				(op_decode_hdr_maxsz + \
1679104a55dSTrond Myklebust 				 decode_stateid_maxsz)
1689104a55dSTrond Myklebust #define encode_close_maxsz	(op_encode_hdr_maxsz + \
1699104a55dSTrond Myklebust 				 1 + encode_stateid_maxsz)
1709104a55dSTrond Myklebust #define decode_close_maxsz	(op_decode_hdr_maxsz + \
1719104a55dSTrond Myklebust 				 decode_stateid_maxsz)
1729104a55dSTrond Myklebust #define encode_setattr_maxsz	(op_encode_hdr_maxsz + \
1739104a55dSTrond Myklebust 				 encode_stateid_maxsz + \
1749104a55dSTrond Myklebust 				 encode_attrs_maxsz)
1759104a55dSTrond Myklebust #define decode_setattr_maxsz	(op_decode_hdr_maxsz + \
1769104a55dSTrond Myklebust 				 nfs4_fattr_bitmap_maxsz)
1779104a55dSTrond Myklebust #define encode_read_maxsz	(op_encode_hdr_maxsz + \
1789104a55dSTrond Myklebust 				 encode_stateid_maxsz + 3)
1799104a55dSTrond Myklebust #define decode_read_maxsz	(op_decode_hdr_maxsz + 2)
1809104a55dSTrond Myklebust #define encode_readdir_maxsz	(op_encode_hdr_maxsz + \
1819104a55dSTrond Myklebust 				 2 + encode_verifier_maxsz + 5)
1829104a55dSTrond Myklebust #define decode_readdir_maxsz	(op_decode_hdr_maxsz + \
1839104a55dSTrond Myklebust 				 decode_verifier_maxsz)
1849104a55dSTrond Myklebust #define encode_readlink_maxsz	(op_encode_hdr_maxsz)
1859104a55dSTrond Myklebust #define decode_readlink_maxsz	(op_decode_hdr_maxsz + 1)
1869104a55dSTrond Myklebust #define encode_write_maxsz	(op_encode_hdr_maxsz + \
1879104a55dSTrond Myklebust 				 encode_stateid_maxsz + 4)
1889104a55dSTrond Myklebust #define decode_write_maxsz	(op_decode_hdr_maxsz + \
1899104a55dSTrond Myklebust 				 2 + decode_verifier_maxsz)
1909104a55dSTrond Myklebust #define encode_commit_maxsz	(op_encode_hdr_maxsz + 3)
1919104a55dSTrond Myklebust #define decode_commit_maxsz	(op_decode_hdr_maxsz + \
1929104a55dSTrond Myklebust 				 decode_verifier_maxsz)
1931da177e4SLinus Torvalds #define encode_remove_maxsz	(op_encode_hdr_maxsz + \
1941da177e4SLinus Torvalds 				nfs4_name_maxsz)
1956ce18391SBenny Halevy #define decode_remove_maxsz	(op_decode_hdr_maxsz + \
1966ce18391SBenny Halevy 				 decode_change_info_maxsz)
1971da177e4SLinus Torvalds #define encode_rename_maxsz	(op_encode_hdr_maxsz + \
1981da177e4SLinus Torvalds 				2 * nfs4_name_maxsz)
1996ce18391SBenny Halevy #define decode_rename_maxsz	(op_decode_hdr_maxsz + \
2006ce18391SBenny Halevy 				 decode_change_info_maxsz + \
2016ce18391SBenny Halevy 				 decode_change_info_maxsz)
2021da177e4SLinus Torvalds #define encode_link_maxsz	(op_encode_hdr_maxsz + \
2031da177e4SLinus Torvalds 				nfs4_name_maxsz)
2046ce18391SBenny Halevy #define decode_link_maxsz	(op_decode_hdr_maxsz + decode_change_info_maxsz)
205daccbdedSTrond Myklebust #define encode_lockowner_maxsz	(7)
2069104a55dSTrond Myklebust #define encode_lock_maxsz	(op_encode_hdr_maxsz + \
2079104a55dSTrond Myklebust 				 7 + \
208daccbdedSTrond Myklebust 				 1 + encode_stateid_maxsz + 1 + \
209daccbdedSTrond Myklebust 				 encode_lockowner_maxsz)
2109104a55dSTrond Myklebust #define decode_lock_denied_maxsz \
2119104a55dSTrond Myklebust 				(8 + decode_lockowner_maxsz)
2129104a55dSTrond Myklebust #define decode_lock_maxsz	(op_decode_hdr_maxsz + \
2139104a55dSTrond Myklebust 				 decode_lock_denied_maxsz)
214daccbdedSTrond Myklebust #define encode_lockt_maxsz	(op_encode_hdr_maxsz + 5 + \
215daccbdedSTrond Myklebust 				encode_lockowner_maxsz)
2169104a55dSTrond Myklebust #define decode_lockt_maxsz	(op_decode_hdr_maxsz + \
2179104a55dSTrond Myklebust 				 decode_lock_denied_maxsz)
2189104a55dSTrond Myklebust #define encode_locku_maxsz	(op_encode_hdr_maxsz + 3 + \
2199104a55dSTrond Myklebust 				 encode_stateid_maxsz + \
2209104a55dSTrond Myklebust 				 4)
2219104a55dSTrond Myklebust #define decode_locku_maxsz	(op_decode_hdr_maxsz + \
2229104a55dSTrond Myklebust 				 decode_stateid_maxsz)
223d3c7b7ccSTrond Myklebust #define encode_release_lockowner_maxsz \
224d3c7b7ccSTrond Myklebust 				(op_encode_hdr_maxsz + \
225d3c7b7ccSTrond Myklebust 				 encode_lockowner_maxsz)
226d3c7b7ccSTrond Myklebust #define decode_release_lockowner_maxsz \
227d3c7b7ccSTrond Myklebust 				(op_decode_hdr_maxsz)
2289104a55dSTrond Myklebust #define encode_access_maxsz	(op_encode_hdr_maxsz + 1)
2299104a55dSTrond Myklebust #define decode_access_maxsz	(op_decode_hdr_maxsz + 2)
2301da177e4SLinus Torvalds #define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
2311da177e4SLinus Torvalds 				1 + nfs4_name_maxsz + \
23294a6d753SChuck Lever 				1 + \
23396928206SJ. Bruce Fields 				nfs4_fattr_maxsz)
2341da177e4SLinus Torvalds #define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
2351da177e4SLinus Torvalds #define encode_create_maxsz	(op_encode_hdr_maxsz + \
2369104a55dSTrond Myklebust 				1 + 2 + nfs4_name_maxsz + \
2379104a55dSTrond Myklebust 				encode_attrs_maxsz)
2382cebf828STrond Myklebust #define decode_create_maxsz	(op_decode_hdr_maxsz + \
2392cebf828STrond Myklebust 				decode_change_info_maxsz + \
2402cebf828STrond Myklebust 				nfs4_fattr_bitmap_maxsz)
2419104a55dSTrond Myklebust #define encode_statfs_maxsz	(encode_getattr_maxsz)
2429104a55dSTrond Myklebust #define decode_statfs_maxsz	(decode_getattr_maxsz)
2431da177e4SLinus Torvalds #define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
2441da177e4SLinus Torvalds #define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
2459104a55dSTrond Myklebust #define encode_getacl_maxsz	(encode_getattr_maxsz)
2469104a55dSTrond Myklebust #define decode_getacl_maxsz	(op_decode_hdr_maxsz + \
2479104a55dSTrond Myklebust 				 nfs4_fattr_bitmap_maxsz + 1)
2489104a55dSTrond Myklebust #define encode_setacl_maxsz	(op_encode_hdr_maxsz + \
2499104a55dSTrond Myklebust 				 encode_stateid_maxsz + 3)
2509104a55dSTrond Myklebust #define decode_setacl_maxsz	(decode_setattr_maxsz)
251e6889620STrond Myklebust #define encode_fs_locations_maxsz \
252e6889620STrond Myklebust 				(encode_getattr_maxsz)
253e6889620STrond Myklebust #define decode_fs_locations_maxsz \
254e6889620STrond Myklebust 				(0)
2559b7b9fccSAndy Adamson 
2569b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1)
257fc931582SAndy Adamson #define NFS4_MAX_MACHINE_NAME_LEN (64)
258fc931582SAndy Adamson 
25999fe60d0SBenny Halevy #define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
26099fe60d0SBenny Halevy 				encode_verifier_maxsz + \
26199fe60d0SBenny Halevy 				1 /* co_ownerid.len */ + \
26299fe60d0SBenny Halevy 				XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
26399fe60d0SBenny Halevy 				1 /* flags */ + \
26499fe60d0SBenny Halevy 				1 /* spa_how */ + \
26599fe60d0SBenny Halevy 				0 /* SP4_NONE (for now) */ + \
26699fe60d0SBenny Halevy 				1 /* zero implemetation id array */)
26799fe60d0SBenny Halevy #define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
26899fe60d0SBenny Halevy 				2 /* eir_clientid */ + \
26999fe60d0SBenny Halevy 				1 /* eir_sequenceid */ + \
27099fe60d0SBenny Halevy 				1 /* eir_flags */ + \
27199fe60d0SBenny Halevy 				1 /* spr_how */ + \
27299fe60d0SBenny Halevy 				0 /* SP4_NONE (for now) */ + \
27399fe60d0SBenny Halevy 				2 /* eir_server_owner.so_minor_id */ + \
27499fe60d0SBenny Halevy 				/* eir_server_owner.so_major_id<> */ \
27599fe60d0SBenny Halevy 				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
27699fe60d0SBenny Halevy 				/* eir_server_scope<> */ \
27799fe60d0SBenny Halevy 				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
27899fe60d0SBenny Halevy 				1 /* eir_server_impl_id array length */ + \
27999fe60d0SBenny Halevy 				0 /* ignored eir_server_impl_id contents */)
280fc931582SAndy Adamson #define encode_channel_attrs_maxsz  (6 + 1 /* ca_rdma_ird.len (0) */)
281fc931582SAndy Adamson #define decode_channel_attrs_maxsz  (6 + \
282fc931582SAndy Adamson 				     1 /* ca_rdma_ird.len */ + \
283fc931582SAndy Adamson 				     1 /* ca_rdma_ird */)
284fc931582SAndy Adamson #define encode_create_session_maxsz  (op_encode_hdr_maxsz + \
285fc931582SAndy Adamson 				     2 /* csa_clientid */ + \
286fc931582SAndy Adamson 				     1 /* csa_sequence */ + \
287fc931582SAndy Adamson 				     1 /* csa_flags */ + \
288fc931582SAndy Adamson 				     encode_channel_attrs_maxsz + \
289fc931582SAndy Adamson 				     encode_channel_attrs_maxsz + \
290fc931582SAndy Adamson 				     1 /* csa_cb_program */ + \
291fc931582SAndy Adamson 				     1 /* csa_sec_parms.len (1) */ + \
292fc931582SAndy Adamson 				     1 /* cb_secflavor (AUTH_SYS) */ + \
293fc931582SAndy Adamson 				     1 /* stamp */ + \
294fc931582SAndy Adamson 				     1 /* machinename.len */ + \
295fc931582SAndy Adamson 				     XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
296fc931582SAndy Adamson 				     1 /* uid */ + \
297fc931582SAndy Adamson 				     1 /* gid */ + \
298fc931582SAndy Adamson 				     1 /* gids.len (0) */)
299fc931582SAndy Adamson #define decode_create_session_maxsz  (op_decode_hdr_maxsz +	\
300fc931582SAndy Adamson 				     XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
301fc931582SAndy Adamson 				     1 /* csr_sequence */ + \
302fc931582SAndy Adamson 				     1 /* csr_flags */ + \
303fc931582SAndy Adamson 				     decode_channel_attrs_maxsz + \
304fc931582SAndy Adamson 				     decode_channel_attrs_maxsz)
3050f3e66c6SAndy Adamson #define encode_destroy_session_maxsz    (op_encode_hdr_maxsz + 4)
3060f3e66c6SAndy Adamson #define decode_destroy_session_maxsz    (op_decode_hdr_maxsz)
307fc01cea9SAndy Adamson #define encode_sequence_maxsz	(op_encode_hdr_maxsz + \
308fc01cea9SAndy Adamson 				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
309fc01cea9SAndy Adamson #define decode_sequence_maxsz	(op_decode_hdr_maxsz + \
310fc01cea9SAndy Adamson 				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
31118019753SRicardo Labiaga #define encode_reclaim_complete_maxsz	(op_encode_hdr_maxsz + 4)
31218019753SRicardo Labiaga #define decode_reclaim_complete_maxsz	(op_decode_hdr_maxsz + 4)
3139b7b9fccSAndy Adamson #else /* CONFIG_NFS_V4_1 */
3149b7b9fccSAndy Adamson #define encode_sequence_maxsz	0
3159b7b9fccSAndy Adamson #define decode_sequence_maxsz	0
3169b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */
3179b7b9fccSAndy Adamson 
3181da177e4SLinus Torvalds #define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
3191da177e4SLinus Torvalds #define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
3201da177e4SLinus Torvalds #define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
3219b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3221da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3239104a55dSTrond Myklebust 				encode_read_maxsz)
3241da177e4SLinus Torvalds #define NFS4_dec_read_sz	(compound_decode_hdr_maxsz + \
3259b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3261da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3279104a55dSTrond Myklebust 				decode_read_maxsz)
3281da177e4SLinus Torvalds #define NFS4_enc_readlink_sz	(compound_encode_hdr_maxsz + \
3299b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3301da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3319104a55dSTrond Myklebust 				encode_readlink_maxsz)
3321da177e4SLinus Torvalds #define NFS4_dec_readlink_sz	(compound_decode_hdr_maxsz + \
3339b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3341da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3359104a55dSTrond Myklebust 				decode_readlink_maxsz)
3361da177e4SLinus Torvalds #define NFS4_enc_readdir_sz	(compound_encode_hdr_maxsz + \
3379b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3381da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3399104a55dSTrond Myklebust 				encode_readdir_maxsz)
3401da177e4SLinus Torvalds #define NFS4_dec_readdir_sz	(compound_decode_hdr_maxsz + \
3419b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3421da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3439104a55dSTrond Myklebust 				decode_readdir_maxsz)
3441da177e4SLinus Torvalds #define NFS4_enc_write_sz	(compound_encode_hdr_maxsz + \
3459b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3461da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3479104a55dSTrond Myklebust 				encode_write_maxsz + \
3484f9838c7STrond Myklebust 				encode_getattr_maxsz)
3491da177e4SLinus Torvalds #define NFS4_dec_write_sz	(compound_decode_hdr_maxsz + \
3509b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3511da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3529104a55dSTrond Myklebust 				decode_write_maxsz + \
3534f9838c7STrond Myklebust 				decode_getattr_maxsz)
3541da177e4SLinus Torvalds #define NFS4_enc_commit_sz	(compound_encode_hdr_maxsz + \
3559b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3561da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3579104a55dSTrond Myklebust 				encode_commit_maxsz + \
3584f9838c7STrond Myklebust 				encode_getattr_maxsz)
3591da177e4SLinus Torvalds #define NFS4_dec_commit_sz	(compound_decode_hdr_maxsz + \
3609b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3611da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3629104a55dSTrond Myklebust 				decode_commit_maxsz + \
3634f9838c7STrond Myklebust 				decode_getattr_maxsz)
3641da177e4SLinus Torvalds #define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
3659b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
3661da177e4SLinus Torvalds 				encode_putfh_maxsz + \
3672cebf828STrond Myklebust 				encode_savefh_maxsz + \
3682cebf828STrond Myklebust 				encode_open_maxsz + \
3692cebf828STrond Myklebust 				encode_getfh_maxsz + \
3701da177e4SLinus Torvalds 				encode_getattr_maxsz + \
3712cebf828STrond Myklebust 				encode_restorefh_maxsz + \
3722cebf828STrond Myklebust 				encode_getattr_maxsz)
3731da177e4SLinus Torvalds #define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
3749b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
3751da177e4SLinus Torvalds 				decode_putfh_maxsz + \
3762cebf828STrond Myklebust 				decode_savefh_maxsz + \
3772cebf828STrond Myklebust 				decode_open_maxsz + \
3782cebf828STrond Myklebust 				decode_getfh_maxsz + \
3791da177e4SLinus Torvalds 				decode_getattr_maxsz + \
3802cebf828STrond Myklebust 				decode_restorefh_maxsz + \
3812cebf828STrond Myklebust 				decode_getattr_maxsz)
3821da177e4SLinus Torvalds #define NFS4_enc_open_confirm_sz \
3831da177e4SLinus Torvalds 				(compound_encode_hdr_maxsz + \
3841da177e4SLinus Torvalds 				 encode_putfh_maxsz + \
3859104a55dSTrond Myklebust 				 encode_open_confirm_maxsz)
3869104a55dSTrond Myklebust #define NFS4_dec_open_confirm_sz \
3879104a55dSTrond Myklebust 				(compound_decode_hdr_maxsz + \
3881da177e4SLinus Torvalds 				 decode_putfh_maxsz + \
3899104a55dSTrond Myklebust 				 decode_open_confirm_maxsz)
3901da177e4SLinus Torvalds #define NFS4_enc_open_noattr_sz	(compound_encode_hdr_maxsz + \
3919b7b9fccSAndy Adamson 					encode_sequence_maxsz + \
3921da177e4SLinus Torvalds 					encode_putfh_maxsz + \
3932cebf828STrond Myklebust 					encode_open_maxsz + \
3942cebf828STrond Myklebust 					encode_getattr_maxsz)
3951da177e4SLinus Torvalds #define NFS4_dec_open_noattr_sz	(compound_decode_hdr_maxsz + \
3969b7b9fccSAndy Adamson 					decode_sequence_maxsz + \
3971da177e4SLinus Torvalds 					decode_putfh_maxsz + \
3982cebf828STrond Myklebust 					decode_open_maxsz + \
3992cebf828STrond Myklebust 					decode_getattr_maxsz)
4001da177e4SLinus Torvalds #define NFS4_enc_open_downgrade_sz \
4011da177e4SLinus Torvalds 				(compound_encode_hdr_maxsz + \
4029b7b9fccSAndy Adamson 				 encode_sequence_maxsz + \
4031da177e4SLinus Torvalds 				 encode_putfh_maxsz + \
4049104a55dSTrond Myklebust 				 encode_open_downgrade_maxsz + \
405516a6af6STrond Myklebust 				 encode_getattr_maxsz)
4061da177e4SLinus Torvalds #define NFS4_dec_open_downgrade_sz \
4071da177e4SLinus Torvalds 				(compound_decode_hdr_maxsz + \
4089b7b9fccSAndy Adamson 				 decode_sequence_maxsz + \
4091da177e4SLinus Torvalds 				 decode_putfh_maxsz + \
4109104a55dSTrond Myklebust 				 decode_open_downgrade_maxsz + \
411516a6af6STrond Myklebust 				 decode_getattr_maxsz)
4121da177e4SLinus Torvalds #define NFS4_enc_close_sz	(compound_encode_hdr_maxsz + \
4139b7b9fccSAndy Adamson 				 encode_sequence_maxsz + \
4141da177e4SLinus Torvalds 				 encode_putfh_maxsz + \
4159104a55dSTrond Myklebust 				 encode_close_maxsz + \
416516a6af6STrond Myklebust 				 encode_getattr_maxsz)
4171da177e4SLinus Torvalds #define NFS4_dec_close_sz	(compound_decode_hdr_maxsz + \
4189b7b9fccSAndy Adamson 				 decode_sequence_maxsz + \
4191da177e4SLinus Torvalds 				 decode_putfh_maxsz + \
4209104a55dSTrond Myklebust 				 decode_close_maxsz + \
421516a6af6STrond Myklebust 				 decode_getattr_maxsz)
4221da177e4SLinus Torvalds #define NFS4_enc_setattr_sz	(compound_encode_hdr_maxsz + \
4239b7b9fccSAndy Adamson 				 encode_sequence_maxsz + \
4241da177e4SLinus Torvalds 				 encode_putfh_maxsz + \
4259104a55dSTrond Myklebust 				 encode_setattr_maxsz + \
4261da177e4SLinus Torvalds 				 encode_getattr_maxsz)
4271da177e4SLinus Torvalds #define NFS4_dec_setattr_sz	(compound_decode_hdr_maxsz + \
4289b7b9fccSAndy Adamson 				 decode_sequence_maxsz + \
4291da177e4SLinus Torvalds 				 decode_putfh_maxsz + \
4309104a55dSTrond Myklebust 				 decode_setattr_maxsz + \
4319104a55dSTrond Myklebust 				 decode_getattr_maxsz)
4321da177e4SLinus Torvalds #define NFS4_enc_fsinfo_sz	(compound_encode_hdr_maxsz + \
4339b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
4341da177e4SLinus Torvalds 				encode_putfh_maxsz + \
4351da177e4SLinus Torvalds 				encode_fsinfo_maxsz)
4361da177e4SLinus Torvalds #define NFS4_dec_fsinfo_sz	(compound_decode_hdr_maxsz + \
4379b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
4381da177e4SLinus Torvalds 				decode_putfh_maxsz + \
4391da177e4SLinus Torvalds 				decode_fsinfo_maxsz)
4401da177e4SLinus Torvalds #define NFS4_enc_renew_sz	(compound_encode_hdr_maxsz + \
4411da177e4SLinus Torvalds 				encode_renew_maxsz)
4421da177e4SLinus Torvalds #define NFS4_dec_renew_sz	(compound_decode_hdr_maxsz + \
4431da177e4SLinus Torvalds 				decode_renew_maxsz)
4441da177e4SLinus Torvalds #define NFS4_enc_setclientid_sz	(compound_encode_hdr_maxsz + \
4451da177e4SLinus Torvalds 				encode_setclientid_maxsz)
4461da177e4SLinus Torvalds #define NFS4_dec_setclientid_sz	(compound_decode_hdr_maxsz + \
4471da177e4SLinus Torvalds 				decode_setclientid_maxsz)
4481da177e4SLinus Torvalds #define NFS4_enc_setclientid_confirm_sz \
4491da177e4SLinus Torvalds 				(compound_encode_hdr_maxsz + \
4501da177e4SLinus Torvalds 				encode_setclientid_confirm_maxsz + \
4511da177e4SLinus Torvalds 				encode_putrootfh_maxsz + \
4521da177e4SLinus Torvalds 				encode_fsinfo_maxsz)
4531da177e4SLinus Torvalds #define NFS4_dec_setclientid_confirm_sz \
4541da177e4SLinus Torvalds 				(compound_decode_hdr_maxsz + \
4551da177e4SLinus Torvalds 				decode_setclientid_confirm_maxsz + \
4561da177e4SLinus Torvalds 				decode_putrootfh_maxsz + \
4571da177e4SLinus Torvalds 				decode_fsinfo_maxsz)
4581da177e4SLinus Torvalds #define NFS4_enc_lock_sz        (compound_encode_hdr_maxsz + \
4599b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
4601da177e4SLinus Torvalds 				encode_putfh_maxsz + \
4619104a55dSTrond Myklebust 				encode_lock_maxsz)
4621da177e4SLinus Torvalds #define NFS4_dec_lock_sz        (compound_decode_hdr_maxsz + \
4639b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
4641da177e4SLinus Torvalds 				decode_putfh_maxsz + \
4659104a55dSTrond Myklebust 				decode_lock_maxsz)
4661da177e4SLinus Torvalds #define NFS4_enc_lockt_sz       (compound_encode_hdr_maxsz + \
4679b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
4681da177e4SLinus Torvalds 				encode_putfh_maxsz + \
4699104a55dSTrond Myklebust 				encode_lockt_maxsz)
4709104a55dSTrond Myklebust #define NFS4_dec_lockt_sz       (compound_decode_hdr_maxsz + \
4719b7b9fccSAndy Adamson 				 decode_sequence_maxsz + \
4729104a55dSTrond Myklebust 				 decode_putfh_maxsz + \
4739104a55dSTrond Myklebust 				 decode_lockt_maxsz)
4741da177e4SLinus Torvalds #define NFS4_enc_locku_sz       (compound_encode_hdr_maxsz + \
4759b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
4761da177e4SLinus Torvalds 				encode_putfh_maxsz + \
4779104a55dSTrond Myklebust 				encode_locku_maxsz)
4781da177e4SLinus Torvalds #define NFS4_dec_locku_sz       (compound_decode_hdr_maxsz + \
4799b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
4801da177e4SLinus Torvalds 				decode_putfh_maxsz + \
4819104a55dSTrond Myklebust 				decode_locku_maxsz)
482d3c7b7ccSTrond Myklebust #define NFS4_enc_release_lockowner_sz \
483d3c7b7ccSTrond Myklebust 				(compound_encode_hdr_maxsz + \
484d3c7b7ccSTrond Myklebust 				 encode_lockowner_maxsz)
485d3c7b7ccSTrond Myklebust #define NFS4_dec_release_lockowner_sz \
486d3c7b7ccSTrond Myklebust 				(compound_decode_hdr_maxsz + \
487d3c7b7ccSTrond Myklebust 				 decode_lockowner_maxsz)
4881da177e4SLinus Torvalds #define NFS4_enc_access_sz	(compound_encode_hdr_maxsz + \
4899b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
4901da177e4SLinus Torvalds 				encode_putfh_maxsz + \
49176b32999STrond Myklebust 				encode_access_maxsz + \
49276b32999STrond Myklebust 				encode_getattr_maxsz)
4931da177e4SLinus Torvalds #define NFS4_dec_access_sz	(compound_decode_hdr_maxsz + \
4949b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
4951da177e4SLinus Torvalds 				decode_putfh_maxsz + \
49676b32999STrond Myklebust 				decode_access_maxsz + \
49776b32999STrond Myklebust 				decode_getattr_maxsz)
4981da177e4SLinus Torvalds #define NFS4_enc_getattr_sz	(compound_encode_hdr_maxsz + \
4999b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5001da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5011da177e4SLinus Torvalds 				encode_getattr_maxsz)
5021da177e4SLinus Torvalds #define NFS4_dec_getattr_sz	(compound_decode_hdr_maxsz + \
5039b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5041da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5051da177e4SLinus Torvalds 				decode_getattr_maxsz)
5061da177e4SLinus Torvalds #define NFS4_enc_lookup_sz	(compound_encode_hdr_maxsz + \
5079b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5081da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5091da177e4SLinus Torvalds 				encode_lookup_maxsz + \
5101da177e4SLinus Torvalds 				encode_getattr_maxsz + \
5111da177e4SLinus Torvalds 				encode_getfh_maxsz)
5121da177e4SLinus Torvalds #define NFS4_dec_lookup_sz	(compound_decode_hdr_maxsz + \
5139b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5141da177e4SLinus Torvalds 				decode_putfh_maxsz + \
515e6889620STrond Myklebust 				decode_lookup_maxsz + \
5161da177e4SLinus Torvalds 				decode_getattr_maxsz + \
5171da177e4SLinus Torvalds 				decode_getfh_maxsz)
5181da177e4SLinus Torvalds #define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
5199b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5201da177e4SLinus Torvalds 				encode_putrootfh_maxsz + \
5211da177e4SLinus Torvalds 				encode_getattr_maxsz + \
5221da177e4SLinus Torvalds 				encode_getfh_maxsz)
5231da177e4SLinus Torvalds #define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
5249b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5251da177e4SLinus Torvalds 				decode_putrootfh_maxsz + \
5261da177e4SLinus Torvalds 				decode_getattr_maxsz + \
5271da177e4SLinus Torvalds 				decode_getfh_maxsz)
5281da177e4SLinus Torvalds #define NFS4_enc_remove_sz	(compound_encode_hdr_maxsz + \
5299b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5301da177e4SLinus Torvalds 				encode_putfh_maxsz + \
53116e42959STrond Myklebust 				encode_remove_maxsz + \
53216e42959STrond Myklebust 				encode_getattr_maxsz)
5331da177e4SLinus Torvalds #define NFS4_dec_remove_sz	(compound_decode_hdr_maxsz + \
5349b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5351da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5366ce18391SBenny Halevy 				decode_remove_maxsz + \
53716e42959STrond Myklebust 				decode_getattr_maxsz)
5381da177e4SLinus Torvalds #define NFS4_enc_rename_sz	(compound_encode_hdr_maxsz + \
5399b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5401da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5411da177e4SLinus Torvalds 				encode_savefh_maxsz + \
5421da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5436caf2c82STrond Myklebust 				encode_rename_maxsz + \
5446caf2c82STrond Myklebust 				encode_getattr_maxsz + \
5456caf2c82STrond Myklebust 				encode_restorefh_maxsz + \
5466caf2c82STrond Myklebust 				encode_getattr_maxsz)
5471da177e4SLinus Torvalds #define NFS4_dec_rename_sz	(compound_decode_hdr_maxsz + \
5489b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5491da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5501da177e4SLinus Torvalds 				decode_savefh_maxsz + \
5511da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5526caf2c82STrond Myklebust 				decode_rename_maxsz + \
5536caf2c82STrond Myklebust 				decode_getattr_maxsz + \
5546caf2c82STrond Myklebust 				decode_restorefh_maxsz + \
5556caf2c82STrond Myklebust 				decode_getattr_maxsz)
5561da177e4SLinus Torvalds #define NFS4_enc_link_sz	(compound_encode_hdr_maxsz + \
5579b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5581da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5591da177e4SLinus Torvalds 				encode_savefh_maxsz + \
5601da177e4SLinus Torvalds 				encode_putfh_maxsz + \
56191ba2eeeSTrond Myklebust 				encode_link_maxsz + \
56291ba2eeeSTrond Myklebust 				decode_getattr_maxsz + \
56391ba2eeeSTrond Myklebust 				encode_restorefh_maxsz + \
56491ba2eeeSTrond Myklebust 				decode_getattr_maxsz)
5651da177e4SLinus Torvalds #define NFS4_dec_link_sz	(compound_decode_hdr_maxsz + \
5669b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5671da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5681da177e4SLinus Torvalds 				decode_savefh_maxsz + \
5691da177e4SLinus Torvalds 				decode_putfh_maxsz + \
57091ba2eeeSTrond Myklebust 				decode_link_maxsz + \
57191ba2eeeSTrond Myklebust 				decode_getattr_maxsz + \
57291ba2eeeSTrond Myklebust 				decode_restorefh_maxsz + \
57391ba2eeeSTrond Myklebust 				decode_getattr_maxsz)
5741da177e4SLinus Torvalds #define NFS4_enc_symlink_sz	(compound_encode_hdr_maxsz + \
5759b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5761da177e4SLinus Torvalds 				encode_putfh_maxsz + \
5771da177e4SLinus Torvalds 				encode_symlink_maxsz + \
5781da177e4SLinus Torvalds 				encode_getattr_maxsz + \
5791da177e4SLinus Torvalds 				encode_getfh_maxsz)
5801da177e4SLinus Torvalds #define NFS4_dec_symlink_sz	(compound_decode_hdr_maxsz + \
5819b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5821da177e4SLinus Torvalds 				decode_putfh_maxsz + \
5831da177e4SLinus Torvalds 				decode_symlink_maxsz + \
5841da177e4SLinus Torvalds 				decode_getattr_maxsz + \
5851da177e4SLinus Torvalds 				decode_getfh_maxsz)
5861da177e4SLinus Torvalds #define NFS4_enc_create_sz	(compound_encode_hdr_maxsz + \
5879b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
5881da177e4SLinus Torvalds 				encode_putfh_maxsz + \
58956ae19f3STrond Myklebust 				encode_savefh_maxsz + \
5901da177e4SLinus Torvalds 				encode_create_maxsz + \
59156ae19f3STrond Myklebust 				encode_getfh_maxsz + \
5921da177e4SLinus Torvalds 				encode_getattr_maxsz + \
59356ae19f3STrond Myklebust 				encode_restorefh_maxsz + \
59456ae19f3STrond Myklebust 				encode_getattr_maxsz)
5951da177e4SLinus Torvalds #define NFS4_dec_create_sz	(compound_decode_hdr_maxsz + \
5969b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
5971da177e4SLinus Torvalds 				decode_putfh_maxsz + \
59856ae19f3STrond Myklebust 				decode_savefh_maxsz + \
5991da177e4SLinus Torvalds 				decode_create_maxsz + \
60056ae19f3STrond Myklebust 				decode_getfh_maxsz + \
6011da177e4SLinus Torvalds 				decode_getattr_maxsz + \
60256ae19f3STrond Myklebust 				decode_restorefh_maxsz + \
60356ae19f3STrond Myklebust 				decode_getattr_maxsz)
6041da177e4SLinus Torvalds #define NFS4_enc_pathconf_sz	(compound_encode_hdr_maxsz + \
6059b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
6061da177e4SLinus Torvalds 				encode_putfh_maxsz + \
6071da177e4SLinus Torvalds 				encode_getattr_maxsz)
6081da177e4SLinus Torvalds #define NFS4_dec_pathconf_sz	(compound_decode_hdr_maxsz + \
6099b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
6101da177e4SLinus Torvalds 				decode_putfh_maxsz + \
6111da177e4SLinus Torvalds 				decode_getattr_maxsz)
6121da177e4SLinus Torvalds #define NFS4_enc_statfs_sz	(compound_encode_hdr_maxsz + \
6139b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
6141da177e4SLinus Torvalds 				encode_putfh_maxsz + \
6159104a55dSTrond Myklebust 				encode_statfs_maxsz)
6161da177e4SLinus Torvalds #define NFS4_dec_statfs_sz	(compound_decode_hdr_maxsz + \
6179b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
6181da177e4SLinus Torvalds 				decode_putfh_maxsz + \
6199104a55dSTrond Myklebust 				decode_statfs_maxsz)
6201da177e4SLinus Torvalds #define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
6219b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
622ab91f264STrond Myklebust 				encode_putfh_maxsz + \
6231da177e4SLinus Torvalds 				encode_getattr_maxsz)
6241da177e4SLinus Torvalds #define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
6259b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
626ab91f264STrond Myklebust 				decode_putfh_maxsz + \
6271da177e4SLinus Torvalds 				decode_getattr_maxsz)
6281da177e4SLinus Torvalds #define NFS4_enc_delegreturn_sz	(compound_encode_hdr_maxsz + \
6299b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
6301da177e4SLinus Torvalds 				encode_putfh_maxsz + \
631fa178f29STrond Myklebust 				encode_delegreturn_maxsz + \
632fa178f29STrond Myklebust 				encode_getattr_maxsz)
6331da177e4SLinus Torvalds #define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
6349b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
635fa178f29STrond Myklebust 				decode_delegreturn_maxsz + \
636fa178f29STrond Myklebust 				decode_getattr_maxsz)
637029d105eSJ. Bruce Fields #define NFS4_enc_getacl_sz	(compound_encode_hdr_maxsz + \
6389b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
639029d105eSJ. Bruce Fields 				encode_putfh_maxsz + \
6409104a55dSTrond Myklebust 				encode_getacl_maxsz)
641029d105eSJ. Bruce Fields #define NFS4_dec_getacl_sz	(compound_decode_hdr_maxsz + \
6429b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
643029d105eSJ. Bruce Fields 				decode_putfh_maxsz + \
6449104a55dSTrond Myklebust 				decode_getacl_maxsz)
64523ec6965SJ. Bruce Fields #define NFS4_enc_setacl_sz	(compound_encode_hdr_maxsz + \
6469b7b9fccSAndy Adamson 				encode_sequence_maxsz + \
64723ec6965SJ. Bruce Fields 				encode_putfh_maxsz + \
6489104a55dSTrond Myklebust 				encode_setacl_maxsz)
64923ec6965SJ. Bruce Fields #define NFS4_dec_setacl_sz	(compound_decode_hdr_maxsz + \
6509b7b9fccSAndy Adamson 				decode_sequence_maxsz + \
65123ec6965SJ. Bruce Fields 				decode_putfh_maxsz + \
6529104a55dSTrond Myklebust 				decode_setacl_maxsz)
653683b57b4STrond Myklebust #define NFS4_enc_fs_locations_sz \
654683b57b4STrond Myklebust 				(compound_encode_hdr_maxsz + \
6559b7b9fccSAndy Adamson 				 encode_sequence_maxsz + \
656683b57b4STrond Myklebust 				 encode_putfh_maxsz + \
657e6889620STrond Myklebust 				 encode_lookup_maxsz + \
658e6889620STrond Myklebust 				 encode_fs_locations_maxsz)
659683b57b4STrond Myklebust #define NFS4_dec_fs_locations_sz \
660683b57b4STrond Myklebust 				(compound_decode_hdr_maxsz + \
6619b7b9fccSAndy Adamson 				 decode_sequence_maxsz + \
662683b57b4STrond Myklebust 				 decode_putfh_maxsz + \
663e6889620STrond Myklebust 				 decode_lookup_maxsz + \
664e6889620STrond Myklebust 				 decode_fs_locations_maxsz)
66599fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
66699fe60d0SBenny Halevy #define NFS4_enc_exchange_id_sz \
66799fe60d0SBenny Halevy 				(compound_encode_hdr_maxsz + \
66899fe60d0SBenny Halevy 				 encode_exchange_id_maxsz)
66999fe60d0SBenny Halevy #define NFS4_dec_exchange_id_sz \
67099fe60d0SBenny Halevy 				(compound_decode_hdr_maxsz + \
67199fe60d0SBenny Halevy 				 decode_exchange_id_maxsz)
672fc931582SAndy Adamson #define NFS4_enc_create_session_sz \
673fc931582SAndy Adamson 				(compound_encode_hdr_maxsz + \
674fc931582SAndy Adamson 				 encode_create_session_maxsz)
675fc931582SAndy Adamson #define NFS4_dec_create_session_sz \
676fc931582SAndy Adamson 				(compound_decode_hdr_maxsz + \
677fc931582SAndy Adamson 				 decode_create_session_maxsz)
6780f3e66c6SAndy Adamson #define NFS4_enc_destroy_session_sz	(compound_encode_hdr_maxsz + \
6790f3e66c6SAndy Adamson 					 encode_destroy_session_maxsz)
6800f3e66c6SAndy Adamson #define NFS4_dec_destroy_session_sz	(compound_decode_hdr_maxsz + \
6810f3e66c6SAndy Adamson 					 decode_destroy_session_maxsz)
682fc01cea9SAndy Adamson #define NFS4_enc_sequence_sz \
683fc01cea9SAndy Adamson 				(compound_decode_hdr_maxsz + \
684fc01cea9SAndy Adamson 				 encode_sequence_maxsz)
685fc01cea9SAndy Adamson #define NFS4_dec_sequence_sz \
686fc01cea9SAndy Adamson 				(compound_decode_hdr_maxsz + \
687fc01cea9SAndy Adamson 				 decode_sequence_maxsz)
6882050f0ccSAndy Adamson #define NFS4_enc_get_lease_time_sz	(compound_encode_hdr_maxsz + \
6892050f0ccSAndy Adamson 					 encode_sequence_maxsz + \
6902050f0ccSAndy Adamson 					 encode_putrootfh_maxsz + \
6912050f0ccSAndy Adamson 					 encode_fsinfo_maxsz)
6922050f0ccSAndy Adamson #define NFS4_dec_get_lease_time_sz	(compound_decode_hdr_maxsz + \
6932050f0ccSAndy Adamson 					 decode_sequence_maxsz + \
6942050f0ccSAndy Adamson 					 decode_putrootfh_maxsz + \
6952050f0ccSAndy Adamson 					 decode_fsinfo_maxsz)
69618019753SRicardo Labiaga #define NFS4_enc_reclaim_complete_sz	(compound_encode_hdr_maxsz + \
69718019753SRicardo Labiaga 					 encode_sequence_maxsz + \
69818019753SRicardo Labiaga 					 encode_reclaim_complete_maxsz)
69918019753SRicardo Labiaga #define NFS4_dec_reclaim_complete_sz	(compound_decode_hdr_maxsz + \
70018019753SRicardo Labiaga 					 decode_sequence_maxsz + \
70118019753SRicardo Labiaga 					 decode_reclaim_complete_maxsz)
7022449ea2eSAlexandros Batsakis 
7032449ea2eSAlexandros Batsakis const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
7042449ea2eSAlexandros Batsakis 				      compound_encode_hdr_maxsz +
7052449ea2eSAlexandros Batsakis 				      encode_sequence_maxsz +
7062449ea2eSAlexandros Batsakis 				      encode_putfh_maxsz +
7072449ea2eSAlexandros Batsakis 				      encode_getattr_maxsz) *
7082449ea2eSAlexandros Batsakis 				     XDR_UNIT);
7092449ea2eSAlexandros Batsakis 
7102449ea2eSAlexandros Batsakis const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
7112449ea2eSAlexandros Batsakis 				     compound_decode_hdr_maxsz +
7122449ea2eSAlexandros Batsakis 				     decode_sequence_maxsz +
7132449ea2eSAlexandros Batsakis 				     decode_putfh_maxsz) *
7142449ea2eSAlexandros Batsakis 				    XDR_UNIT);
71599fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
7161da177e4SLinus Torvalds 
717bca79478STrond Myklebust static const umode_t nfs_type2fmt[] = {
718bca79478STrond Myklebust 	[NF4BAD] = 0,
719bca79478STrond Myklebust 	[NF4REG] = S_IFREG,
720bca79478STrond Myklebust 	[NF4DIR] = S_IFDIR,
721bca79478STrond Myklebust 	[NF4BLK] = S_IFBLK,
722bca79478STrond Myklebust 	[NF4CHR] = S_IFCHR,
723bca79478STrond Myklebust 	[NF4LNK] = S_IFLNK,
724bca79478STrond Myklebust 	[NF4SOCK] = S_IFSOCK,
725bca79478STrond Myklebust 	[NF4FIFO] = S_IFIFO,
726bca79478STrond Myklebust 	[NF4ATTRDIR] = 0,
727bca79478STrond Myklebust 	[NF4NAMEDATTR] = 0,
7281da177e4SLinus Torvalds };
7291da177e4SLinus Torvalds 
7301da177e4SLinus Torvalds struct compound_hdr {
7311da177e4SLinus Torvalds 	int32_t		status;
7321da177e4SLinus Torvalds 	uint32_t	nops;
733d017931cSAndy Adamson 	__be32 *	nops_p;
7341da177e4SLinus Torvalds 	uint32_t	taglen;
7351da177e4SLinus Torvalds 	char *		tag;
7360c4e8c18SBenny Halevy 	uint32_t	replen;		/* expected reply words */
73766cc0429SBenny Halevy 	u32		minorversion;
7381da177e4SLinus Torvalds };
7391da177e4SLinus Torvalds 
74013c65ce9SBenny Halevy static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
74113c65ce9SBenny Halevy {
74213c65ce9SBenny Halevy 	__be32 *p = xdr_reserve_space(xdr, nbytes);
74313c65ce9SBenny Halevy 	BUG_ON(!p);
74413c65ce9SBenny Halevy 	return p;
74513c65ce9SBenny Halevy }
7461da177e4SLinus Torvalds 
7471da177e4SLinus Torvalds static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
7481da177e4SLinus Torvalds {
7498687b63aSAl Viro 	__be32 *p;
7501da177e4SLinus Torvalds 
7511da177e4SLinus Torvalds 	p = xdr_reserve_space(xdr, 4 + len);
7521da177e4SLinus Torvalds 	BUG_ON(p == NULL);
7531da177e4SLinus Torvalds 	xdr_encode_opaque(p, str, len);
7541da177e4SLinus Torvalds }
7551da177e4SLinus Torvalds 
7560c4e8c18SBenny Halevy static void encode_compound_hdr(struct xdr_stream *xdr,
7570c4e8c18SBenny Halevy 				struct rpc_rqst *req,
7580c4e8c18SBenny Halevy 				struct compound_hdr *hdr)
7591da177e4SLinus Torvalds {
7608687b63aSAl Viro 	__be32 *p;
761a17c2153STrond Myklebust 	struct rpc_auth *auth = req->rq_cred->cr_auth;
7620c4e8c18SBenny Halevy 
7630c4e8c18SBenny Halevy 	/* initialize running count of expected bytes in reply.
7640c4e8c18SBenny Halevy 	 * NOTE: the replied tag SHOULD be the same is the one sent,
7650c4e8c18SBenny Halevy 	 * but this is not required as a MUST for the server to do so. */
7660c4e8c18SBenny Halevy 	hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
7671da177e4SLinus Torvalds 
7681da177e4SLinus Torvalds 	dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
7691da177e4SLinus Torvalds 	BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
770811652bdSBenny Halevy 	p = reserve_space(xdr, 4 + hdr->taglen + 8);
771811652bdSBenny Halevy 	p = xdr_encode_opaque(p, hdr->tag, hdr->taglen);
772e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(hdr->minorversion);
773d017931cSAndy Adamson 	hdr->nops_p = p;
77434558513SBenny Halevy 	*p = cpu_to_be32(hdr->nops);
775d017931cSAndy Adamson }
776d017931cSAndy Adamson 
777d017931cSAndy Adamson static void encode_nops(struct compound_hdr *hdr)
778d017931cSAndy Adamson {
779fc931582SAndy Adamson 	BUG_ON(hdr->nops > NFS4_MAX_OPS);
780d017931cSAndy Adamson 	*hdr->nops_p = htonl(hdr->nops);
7811da177e4SLinus Torvalds }
7821da177e4SLinus Torvalds 
7831da177e4SLinus Torvalds static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
7841da177e4SLinus Torvalds {
7858687b63aSAl Viro 	__be32 *p;
7861da177e4SLinus Torvalds 
7871da177e4SLinus Torvalds 	p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
7881da177e4SLinus Torvalds 	BUG_ON(p == NULL);
7891da177e4SLinus Torvalds 	xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
7901da177e4SLinus Torvalds }
7911da177e4SLinus Torvalds 
792cf8cdbe5SAndy Adamson static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
7931da177e4SLinus Torvalds {
7941da177e4SLinus Torvalds 	char owner_name[IDMAP_NAMESZ];
7951da177e4SLinus Torvalds 	char owner_group[IDMAP_NAMESZ];
7961da177e4SLinus Torvalds 	int owner_namelen = 0;
7971da177e4SLinus Torvalds 	int owner_grouplen = 0;
7988687b63aSAl Viro 	__be32 *p;
7998687b63aSAl Viro 	__be32 *q;
8001da177e4SLinus Torvalds 	int len;
8011da177e4SLinus Torvalds 	uint32_t bmval0 = 0;
8021da177e4SLinus Torvalds 	uint32_t bmval1 = 0;
8031da177e4SLinus Torvalds 
8041da177e4SLinus Torvalds 	/*
8051da177e4SLinus Torvalds 	 * We reserve enough space to write the entire attribute buffer at once.
8061da177e4SLinus Torvalds 	 * In the worst-case, this would be
8071da177e4SLinus Torvalds 	 *   12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
8081da177e4SLinus Torvalds 	 *          = 36 bytes, plus any contribution from variable-length fields
80923ec6965SJ. Bruce Fields 	 *            such as owner/group.
8101da177e4SLinus Torvalds 	 */
8111da177e4SLinus Torvalds 	len = 16;
8121da177e4SLinus Torvalds 
8131da177e4SLinus Torvalds 	/* Sigh */
8141da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_SIZE)
8151da177e4SLinus Torvalds 		len += 8;
8161da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_MODE)
8171da177e4SLinus Torvalds 		len += 4;
8181da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_UID) {
819955a857eSBryan Schumaker 		owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name, IDMAP_NAMESZ);
8201da177e4SLinus Torvalds 		if (owner_namelen < 0) {
821fe82a183SChuck Lever 			dprintk("nfs: couldn't resolve uid %d to string\n",
8221da177e4SLinus Torvalds 					iap->ia_uid);
8231da177e4SLinus Torvalds 			/* XXX */
8241da177e4SLinus Torvalds 			strcpy(owner_name, "nobody");
8251da177e4SLinus Torvalds 			owner_namelen = sizeof("nobody") - 1;
8261da177e4SLinus Torvalds 			/* goto out; */
8271da177e4SLinus Torvalds 		}
8281da177e4SLinus Torvalds 		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
8291da177e4SLinus Torvalds 	}
8301da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_GID) {
831955a857eSBryan Schumaker 		owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group, IDMAP_NAMESZ);
8321da177e4SLinus Torvalds 		if (owner_grouplen < 0) {
833fe82a183SChuck Lever 			dprintk("nfs: couldn't resolve gid %d to string\n",
8341da177e4SLinus Torvalds 					iap->ia_gid);
8351da177e4SLinus Torvalds 			strcpy(owner_group, "nobody");
8361da177e4SLinus Torvalds 			owner_grouplen = sizeof("nobody") - 1;
8371da177e4SLinus Torvalds 			/* goto out; */
8381da177e4SLinus Torvalds 		}
8391da177e4SLinus Torvalds 		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
8401da177e4SLinus Torvalds 	}
8411da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_ATIME_SET)
8421da177e4SLinus Torvalds 		len += 16;
8431da177e4SLinus Torvalds 	else if (iap->ia_valid & ATTR_ATIME)
8441da177e4SLinus Torvalds 		len += 4;
8451da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_MTIME_SET)
8461da177e4SLinus Torvalds 		len += 16;
8471da177e4SLinus Torvalds 	else if (iap->ia_valid & ATTR_MTIME)
8481da177e4SLinus Torvalds 		len += 4;
84913c65ce9SBenny Halevy 	p = reserve_space(xdr, len);
8501da177e4SLinus Torvalds 
8511da177e4SLinus Torvalds 	/*
8521da177e4SLinus Torvalds 	 * We write the bitmap length now, but leave the bitmap and the attribute
8531da177e4SLinus Torvalds 	 * buffer length to be backfilled at the end of this routine.
8541da177e4SLinus Torvalds 	 */
855e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(2);
8561da177e4SLinus Torvalds 	q = p;
8571da177e4SLinus Torvalds 	p += 3;
8581da177e4SLinus Torvalds 
8591da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_SIZE) {
8601da177e4SLinus Torvalds 		bmval0 |= FATTR4_WORD0_SIZE;
861b95be5a9SBenny Halevy 		p = xdr_encode_hyper(p, iap->ia_size);
8621da177e4SLinus Torvalds 	}
8631da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_MODE) {
8641da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_MODE;
865e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
8661da177e4SLinus Torvalds 	}
8671da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_UID) {
8681da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_OWNER;
869811652bdSBenny Halevy 		p = xdr_encode_opaque(p, owner_name, owner_namelen);
8701da177e4SLinus Torvalds 	}
8711da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_GID) {
8721da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_OWNER_GROUP;
873811652bdSBenny Halevy 		p = xdr_encode_opaque(p, owner_group, owner_grouplen);
8741da177e4SLinus Torvalds 	}
8751da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_ATIME_SET) {
8761da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
877e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
878e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(0);
879d3f6baaaSTrond Myklebust 		*p++ = cpu_to_be32(iap->ia_atime.tv_sec);
880d3f6baaaSTrond Myklebust 		*p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
8811da177e4SLinus Torvalds 	}
8821da177e4SLinus Torvalds 	else if (iap->ia_valid & ATTR_ATIME) {
8831da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
884e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
8851da177e4SLinus Torvalds 	}
8861da177e4SLinus Torvalds 	if (iap->ia_valid & ATTR_MTIME_SET) {
8871da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
888e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
889e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(0);
890e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
891e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
8921da177e4SLinus Torvalds 	}
8931da177e4SLinus Torvalds 	else if (iap->ia_valid & ATTR_MTIME) {
8941da177e4SLinus Torvalds 		bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
895e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
8961da177e4SLinus Torvalds 	}
8971da177e4SLinus Torvalds 
8981da177e4SLinus Torvalds 	/*
8991da177e4SLinus Torvalds 	 * Now we backfill the bitmap and the attribute buffer length.
9001da177e4SLinus Torvalds 	 */
9011da177e4SLinus Torvalds 	if (len != ((char *)p - (char *)q) + 4) {
902fe82a183SChuck Lever 		printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n",
9031da177e4SLinus Torvalds 				len, ((char *)p - (char *)q) + 4);
9041da177e4SLinus Torvalds 		BUG();
9051da177e4SLinus Torvalds 	}
9061da177e4SLinus Torvalds 	len = (char *)p - (char *)q - 12;
9071da177e4SLinus Torvalds 	*q++ = htonl(bmval0);
9081da177e4SLinus Torvalds 	*q++ = htonl(bmval1);
90934558513SBenny Halevy 	*q = htonl(len);
9101da177e4SLinus Torvalds 
9111da177e4SLinus Torvalds /* out: */
9121da177e4SLinus Torvalds }
9131da177e4SLinus Torvalds 
914cf8cdbe5SAndy Adamson static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
9151da177e4SLinus Torvalds {
9168687b63aSAl Viro 	__be32 *p;
9171da177e4SLinus Torvalds 
91813c65ce9SBenny Halevy 	p = reserve_space(xdr, 8);
919e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_ACCESS);
92034558513SBenny Halevy 	*p = cpu_to_be32(access);
921d017931cSAndy Adamson 	hdr->nops++;
922dadf0c27SBenny Halevy 	hdr->replen += decode_access_maxsz;
9231da177e4SLinus Torvalds }
9241da177e4SLinus Torvalds 
925cf8cdbe5SAndy Adamson static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
9261da177e4SLinus Torvalds {
9278687b63aSAl Viro 	__be32 *p;
9281da177e4SLinus Torvalds 
92913c65ce9SBenny Halevy 	p = reserve_space(xdr, 8+NFS4_STATEID_SIZE);
930e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_CLOSE);
931e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(arg->seqid->sequence->counter);
93234558513SBenny Halevy 	xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
933d017931cSAndy Adamson 	hdr->nops++;
934dadf0c27SBenny Halevy 	hdr->replen += decode_close_maxsz;
9351da177e4SLinus Torvalds }
9361da177e4SLinus Torvalds 
937cf8cdbe5SAndy Adamson static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
9381da177e4SLinus Torvalds {
9398687b63aSAl Viro 	__be32 *p;
9401da177e4SLinus Torvalds 
94113c65ce9SBenny Halevy 	p = reserve_space(xdr, 16);
942e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_COMMIT);
943b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->offset);
94434558513SBenny Halevy 	*p = cpu_to_be32(args->count);
945d017931cSAndy Adamson 	hdr->nops++;
946dadf0c27SBenny Halevy 	hdr->replen += decode_commit_maxsz;
9471da177e4SLinus Torvalds }
9481da177e4SLinus Torvalds 
949cf8cdbe5SAndy Adamson static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
9501da177e4SLinus Torvalds {
9518687b63aSAl Viro 	__be32 *p;
9521da177e4SLinus Torvalds 
95313c65ce9SBenny Halevy 	p = reserve_space(xdr, 8);
954e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_CREATE);
95534558513SBenny Halevy 	*p = cpu_to_be32(create->ftype);
9561da177e4SLinus Torvalds 
9571da177e4SLinus Torvalds 	switch (create->ftype) {
9581da177e4SLinus Torvalds 	case NF4LNK:
95913c65ce9SBenny Halevy 		p = reserve_space(xdr, 4);
96034558513SBenny Halevy 		*p = cpu_to_be32(create->u.symlink.len);
96194a6d753SChuck Lever 		xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len);
9621da177e4SLinus Torvalds 		break;
9631da177e4SLinus Torvalds 
9641da177e4SLinus Torvalds 	case NF4BLK: case NF4CHR:
96513c65ce9SBenny Halevy 		p = reserve_space(xdr, 8);
966e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(create->u.device.specdata1);
96734558513SBenny Halevy 		*p = cpu_to_be32(create->u.device.specdata2);
9681da177e4SLinus Torvalds 		break;
9691da177e4SLinus Torvalds 
9701da177e4SLinus Torvalds 	default:
9711da177e4SLinus Torvalds 		break;
9721da177e4SLinus Torvalds 	}
9731da177e4SLinus Torvalds 
974811652bdSBenny Halevy 	encode_string(xdr, create->name->len, create->name->name);
975d017931cSAndy Adamson 	hdr->nops++;
976dadf0c27SBenny Halevy 	hdr->replen += decode_create_maxsz;
9771da177e4SLinus Torvalds 
978cf8cdbe5SAndy Adamson 	encode_attrs(xdr, create->attrs, create->server);
9791da177e4SLinus Torvalds }
9801da177e4SLinus Torvalds 
981cf8cdbe5SAndy Adamson static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
9821da177e4SLinus Torvalds {
9838687b63aSAl Viro 	__be32 *p;
9841da177e4SLinus Torvalds 
98513c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
986e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_GETATTR);
987e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(1);
98834558513SBenny Halevy 	*p = cpu_to_be32(bitmap);
989d017931cSAndy Adamson 	hdr->nops++;
990dadf0c27SBenny Halevy 	hdr->replen += decode_getattr_maxsz;
9911da177e4SLinus Torvalds }
9921da177e4SLinus Torvalds 
993cf8cdbe5SAndy Adamson static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr)
9941da177e4SLinus Torvalds {
9958687b63aSAl Viro 	__be32 *p;
9961da177e4SLinus Torvalds 
99713c65ce9SBenny Halevy 	p = reserve_space(xdr, 16);
998e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_GETATTR);
999e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(2);
1000e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(bm0);
100134558513SBenny Halevy 	*p = cpu_to_be32(bm1);
1002d017931cSAndy Adamson 	hdr->nops++;
1003dadf0c27SBenny Halevy 	hdr->replen += decode_getattr_maxsz;
10041da177e4SLinus Torvalds }
10051da177e4SLinus Torvalds 
1006cf8cdbe5SAndy Adamson static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
10071da177e4SLinus Torvalds {
1008cf8cdbe5SAndy Adamson 	encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
1009d017931cSAndy Adamson 			   bitmask[1] & nfs4_fattr_bitmap[1], hdr);
10101da177e4SLinus Torvalds }
10111da177e4SLinus Torvalds 
1012cf8cdbe5SAndy Adamson static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
10131da177e4SLinus Torvalds {
1014cf8cdbe5SAndy Adamson 	encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
1015d017931cSAndy Adamson 			   bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
10161da177e4SLinus Torvalds }
10171da177e4SLinus Torvalds 
1018cf8cdbe5SAndy Adamson static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
1019830b8e33SManoj Naik {
1020cf8cdbe5SAndy Adamson 	encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0],
1021cf8cdbe5SAndy Adamson 			   bitmask[1] & nfs4_fs_locations_bitmap[1], hdr);
1022830b8e33SManoj Naik }
1023830b8e33SManoj Naik 
1024cf8cdbe5SAndy Adamson static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
10251da177e4SLinus Torvalds {
10268687b63aSAl Viro 	__be32 *p;
10271da177e4SLinus Torvalds 
102813c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
102934558513SBenny Halevy 	*p = cpu_to_be32(OP_GETFH);
1030d017931cSAndy Adamson 	hdr->nops++;
1031dadf0c27SBenny Halevy 	hdr->replen += decode_getfh_maxsz;
10321da177e4SLinus Torvalds }
10331da177e4SLinus Torvalds 
1034cf8cdbe5SAndy Adamson static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
10351da177e4SLinus Torvalds {
10368687b63aSAl Viro 	__be32 *p;
10371da177e4SLinus Torvalds 
103813c65ce9SBenny Halevy 	p = reserve_space(xdr, 8 + name->len);
1039e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_LINK);
1040811652bdSBenny Halevy 	xdr_encode_opaque(p, name->name, name->len);
1041d017931cSAndy Adamson 	hdr->nops++;
1042dadf0c27SBenny Halevy 	hdr->replen += decode_link_maxsz;
10431da177e4SLinus Torvalds }
10441da177e4SLinus Torvalds 
1045911d1aafSTrond Myklebust static inline int nfs4_lock_type(struct file_lock *fl, int block)
1046911d1aafSTrond Myklebust {
1047911d1aafSTrond Myklebust 	if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK)
1048911d1aafSTrond Myklebust 		return block ? NFS4_READW_LT : NFS4_READ_LT;
1049911d1aafSTrond Myklebust 	return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
1050911d1aafSTrond Myklebust }
1051911d1aafSTrond Myklebust 
1052911d1aafSTrond Myklebust static inline uint64_t nfs4_lock_length(struct file_lock *fl)
1053911d1aafSTrond Myklebust {
1054911d1aafSTrond Myklebust 	if (fl->fl_end == OFFSET_MAX)
1055911d1aafSTrond Myklebust 		return ~(uint64_t)0;
1056911d1aafSTrond Myklebust 	return fl->fl_end - fl->fl_start + 1;
1057911d1aafSTrond Myklebust }
1058911d1aafSTrond Myklebust 
1059daccbdedSTrond Myklebust static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
1060daccbdedSTrond Myklebust {
1061daccbdedSTrond Myklebust 	__be32 *p;
1062daccbdedSTrond Myklebust 
1063daccbdedSTrond Myklebust 	p = reserve_space(xdr, 28);
1064daccbdedSTrond Myklebust 	p = xdr_encode_hyper(p, lowner->clientid);
1065daccbdedSTrond Myklebust 	*p++ = cpu_to_be32(16);
1066daccbdedSTrond Myklebust 	p = xdr_encode_opaque_fixed(p, "lock id:", 8);
1067daccbdedSTrond Myklebust 	xdr_encode_hyper(p, lowner->id);
1068daccbdedSTrond Myklebust }
1069daccbdedSTrond Myklebust 
10701da177e4SLinus Torvalds /*
10711da177e4SLinus Torvalds  * opcode,type,reclaim,offset,length,new_lock_owner = 32
10721da177e4SLinus Torvalds  * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
10731da177e4SLinus Torvalds  */
1074cf8cdbe5SAndy Adamson static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
10751da177e4SLinus Torvalds {
10768687b63aSAl Viro 	__be32 *p;
10771da177e4SLinus Torvalds 
107813c65ce9SBenny Halevy 	p = reserve_space(xdr, 32);
1079e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_LOCK);
1080e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
1081e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->reclaim);
1082b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->fl->fl_start);
1083b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
108434558513SBenny Halevy 	*p = cpu_to_be32(args->new_lock_owner);
1085911d1aafSTrond Myklebust 	if (args->new_lock_owner){
1086daccbdedSTrond Myklebust 		p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
1087e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(args->open_seqid->sequence->counter);
108893f0cf25SBenny Halevy 		p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE);
1089e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(args->lock_seqid->sequence->counter);
1090daccbdedSTrond Myklebust 		encode_lockowner(xdr, &args->lock_owner);
10911da177e4SLinus Torvalds 	}
10921da177e4SLinus Torvalds 	else {
109313c65ce9SBenny Halevy 		p = reserve_space(xdr, NFS4_STATEID_SIZE+4);
109493f0cf25SBenny Halevy 		p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE);
109534558513SBenny Halevy 		*p = cpu_to_be32(args->lock_seqid->sequence->counter);
10961da177e4SLinus Torvalds 	}
1097d017931cSAndy Adamson 	hdr->nops++;
1098dadf0c27SBenny Halevy 	hdr->replen += decode_lock_maxsz;
10991da177e4SLinus Torvalds }
11001da177e4SLinus Torvalds 
1101cf8cdbe5SAndy Adamson static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
11021da177e4SLinus Torvalds {
11038687b63aSAl Viro 	__be32 *p;
11041da177e4SLinus Torvalds 
1105daccbdedSTrond Myklebust 	p = reserve_space(xdr, 24);
1106e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_LOCKT);
1107e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
1108b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->fl->fl_start);
1109b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
1110daccbdedSTrond Myklebust 	encode_lockowner(xdr, &args->lock_owner);
1111d017931cSAndy Adamson 	hdr->nops++;
1112dadf0c27SBenny Halevy 	hdr->replen += decode_lockt_maxsz;
11131da177e4SLinus Torvalds }
11141da177e4SLinus Torvalds 
1115cf8cdbe5SAndy Adamson static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
11161da177e4SLinus Torvalds {
11178687b63aSAl Viro 	__be32 *p;
11181da177e4SLinus Torvalds 
111913c65ce9SBenny Halevy 	p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16);
1120e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_LOCKU);
1121e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
1122e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->seqid->sequence->counter);
112393f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE);
1124b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->fl->fl_start);
112534558513SBenny Halevy 	xdr_encode_hyper(p, nfs4_lock_length(args->fl));
1126d017931cSAndy Adamson 	hdr->nops++;
1127dadf0c27SBenny Halevy 	hdr->replen += decode_locku_maxsz;
11281da177e4SLinus Torvalds }
11291da177e4SLinus Torvalds 
1130d3c7b7ccSTrond Myklebust static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
1131d3c7b7ccSTrond Myklebust {
1132d3c7b7ccSTrond Myklebust 	__be32 *p;
1133d3c7b7ccSTrond Myklebust 
1134d3c7b7ccSTrond Myklebust 	p = reserve_space(xdr, 4);
1135d3c7b7ccSTrond Myklebust 	*p = cpu_to_be32(OP_RELEASE_LOCKOWNER);
1136d3c7b7ccSTrond Myklebust 	encode_lockowner(xdr, lowner);
1137d3c7b7ccSTrond Myklebust 	hdr->nops++;
1138d3c7b7ccSTrond Myklebust 	hdr->replen += decode_release_lockowner_maxsz;
1139d3c7b7ccSTrond Myklebust }
1140d3c7b7ccSTrond Myklebust 
1141cf8cdbe5SAndy Adamson static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
11421da177e4SLinus Torvalds {
11431da177e4SLinus Torvalds 	int len = name->len;
11448687b63aSAl Viro 	__be32 *p;
11451da177e4SLinus Torvalds 
114613c65ce9SBenny Halevy 	p = reserve_space(xdr, 8 + len);
1147e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_LOOKUP);
1148811652bdSBenny Halevy 	xdr_encode_opaque(p, name->name, len);
1149d017931cSAndy Adamson 	hdr->nops++;
1150dadf0c27SBenny Halevy 	hdr->replen += decode_lookup_maxsz;
11511da177e4SLinus Torvalds }
11521da177e4SLinus Torvalds 
1153dc0b027dSTrond Myklebust static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
11541da177e4SLinus Torvalds {
11558687b63aSAl Viro 	__be32 *p;
11561da177e4SLinus Torvalds 
115713c65ce9SBenny Halevy 	p = reserve_space(xdr, 8);
1158dc0b027dSTrond Myklebust 	switch (fmode & (FMODE_READ|FMODE_WRITE)) {
11591da177e4SLinus Torvalds 	case FMODE_READ:
1160e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
11611da177e4SLinus Torvalds 		break;
11621da177e4SLinus Torvalds 	case FMODE_WRITE:
1163e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
11641da177e4SLinus Torvalds 		break;
11651da177e4SLinus Torvalds 	case FMODE_READ|FMODE_WRITE:
1166e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
11671da177e4SLinus Torvalds 		break;
11681da177e4SLinus Torvalds 	default:
1169e75bc1c8SBenny Halevy 		*p++ = cpu_to_be32(0);
11701da177e4SLinus Torvalds 	}
117134558513SBenny Halevy 	*p = cpu_to_be32(0);		/* for linux, share_deny = 0 always */
11721da177e4SLinus Torvalds }
11731da177e4SLinus Torvalds 
11741da177e4SLinus Torvalds static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
11751da177e4SLinus Torvalds {
11768687b63aSAl Viro 	__be32 *p;
11771da177e4SLinus Torvalds  /*
11781da177e4SLinus Torvalds  * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
11791da177e4SLinus Torvalds  * owner 4 = 32
11801da177e4SLinus Torvalds  */
118113c65ce9SBenny Halevy 	p = reserve_space(xdr, 8);
1182e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_OPEN);
118334558513SBenny Halevy 	*p = cpu_to_be32(arg->seqid->sequence->counter);
1184dc0b027dSTrond Myklebust 	encode_share_access(xdr, arg->fmode);
118513c65ce9SBenny Halevy 	p = reserve_space(xdr, 28);
1186b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, arg->clientid);
1187e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(16);
118893f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, "open id:", 8);
118934558513SBenny Halevy 	xdr_encode_hyper(p, arg->id);
11901da177e4SLinus Torvalds }
11911da177e4SLinus Torvalds 
11921da177e4SLinus Torvalds static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
11931da177e4SLinus Torvalds {
11948687b63aSAl Viro 	__be32 *p;
11954882ef72SAlexandros Batsakis 	struct nfs_client *clp;
11961da177e4SLinus Torvalds 
119713c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
11981da177e4SLinus Torvalds 	switch(arg->open_flags & O_EXCL) {
11991da177e4SLinus Torvalds 	case 0:
120034558513SBenny Halevy 		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
12011da177e4SLinus Torvalds 		encode_attrs(xdr, arg->u.attrs, arg->server);
12021da177e4SLinus Torvalds 		break;
12031da177e4SLinus Torvalds 	default:
12044882ef72SAlexandros Batsakis 		clp = arg->server->nfs_client;
1205a4432345STrond Myklebust 		if (clp->cl_mvops->minor_version > 0) {
12064882ef72SAlexandros Batsakis 			if (nfs4_has_persistent_session(clp)) {
12074882ef72SAlexandros Batsakis 				*p = cpu_to_be32(NFS4_CREATE_GUARDED);
12084882ef72SAlexandros Batsakis 				encode_attrs(xdr, arg->u.attrs, arg->server);
12094882ef72SAlexandros Batsakis 			} else {
12104882ef72SAlexandros Batsakis 				struct iattr dummy;
12114882ef72SAlexandros Batsakis 
12124882ef72SAlexandros Batsakis 				*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
12134882ef72SAlexandros Batsakis 				encode_nfs4_verifier(xdr, &arg->u.verifier);
12144882ef72SAlexandros Batsakis 				dummy.ia_valid = 0;
12154882ef72SAlexandros Batsakis 				encode_attrs(xdr, &dummy, arg->server);
12164882ef72SAlexandros Batsakis 			}
12174882ef72SAlexandros Batsakis 		} else {
121834558513SBenny Halevy 			*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
12191da177e4SLinus Torvalds 			encode_nfs4_verifier(xdr, &arg->u.verifier);
12201da177e4SLinus Torvalds 		}
12211da177e4SLinus Torvalds 	}
12224882ef72SAlexandros Batsakis }
12231da177e4SLinus Torvalds 
12241da177e4SLinus Torvalds static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
12251da177e4SLinus Torvalds {
12268687b63aSAl Viro 	__be32 *p;
12271da177e4SLinus Torvalds 
122813c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
12291da177e4SLinus Torvalds 	switch (arg->open_flags & O_CREAT) {
12301da177e4SLinus Torvalds 	case 0:
123134558513SBenny Halevy 		*p = cpu_to_be32(NFS4_OPEN_NOCREATE);
12321da177e4SLinus Torvalds 		break;
12331da177e4SLinus Torvalds 	default:
12341da177e4SLinus Torvalds 		BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
123534558513SBenny Halevy 		*p = cpu_to_be32(NFS4_OPEN_CREATE);
12361da177e4SLinus Torvalds 		encode_createmode(xdr, arg);
12371da177e4SLinus Torvalds 	}
12381da177e4SLinus Torvalds }
12391da177e4SLinus Torvalds 
1240bd7bf9d5STrond Myklebust static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
12411da177e4SLinus Torvalds {
12428687b63aSAl Viro 	__be32 *p;
12431da177e4SLinus Torvalds 
124413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
12451da177e4SLinus Torvalds 	switch (delegation_type) {
12461da177e4SLinus Torvalds 	case 0:
124734558513SBenny Halevy 		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
12481da177e4SLinus Torvalds 		break;
12491da177e4SLinus Torvalds 	case FMODE_READ:
125034558513SBenny Halevy 		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
12511da177e4SLinus Torvalds 		break;
12521da177e4SLinus Torvalds 	case FMODE_WRITE|FMODE_READ:
125334558513SBenny Halevy 		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
12541da177e4SLinus Torvalds 		break;
12551da177e4SLinus Torvalds 	default:
12561da177e4SLinus Torvalds 		BUG();
12571da177e4SLinus Torvalds 	}
12581da177e4SLinus Torvalds }
12591da177e4SLinus Torvalds 
12601da177e4SLinus Torvalds static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
12611da177e4SLinus Torvalds {
12628687b63aSAl Viro 	__be32 *p;
12631da177e4SLinus Torvalds 
126413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
126534558513SBenny Halevy 	*p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
12661da177e4SLinus Torvalds 	encode_string(xdr, name->len, name->name);
12671da177e4SLinus Torvalds }
12681da177e4SLinus Torvalds 
1269bd7bf9d5STrond Myklebust static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
12701da177e4SLinus Torvalds {
12718687b63aSAl Viro 	__be32 *p;
12721da177e4SLinus Torvalds 
127313c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
127434558513SBenny Halevy 	*p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
12751da177e4SLinus Torvalds 	encode_delegation_type(xdr, type);
12761da177e4SLinus Torvalds }
12771da177e4SLinus Torvalds 
12781da177e4SLinus Torvalds static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
12791da177e4SLinus Torvalds {
12808687b63aSAl Viro 	__be32 *p;
12811da177e4SLinus Torvalds 
128213c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
1283e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
128434558513SBenny Halevy 	xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
12851da177e4SLinus Torvalds 	encode_string(xdr, name->len, name->name);
12861da177e4SLinus Torvalds }
12871da177e4SLinus Torvalds 
1288cf8cdbe5SAndy Adamson static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
12891da177e4SLinus Torvalds {
12901da177e4SLinus Torvalds 	encode_openhdr(xdr, arg);
12911da177e4SLinus Torvalds 	encode_opentype(xdr, arg);
12921da177e4SLinus Torvalds 	switch (arg->claim) {
12931da177e4SLinus Torvalds 	case NFS4_OPEN_CLAIM_NULL:
12941da177e4SLinus Torvalds 		encode_claim_null(xdr, arg->name);
12951da177e4SLinus Torvalds 		break;
12961da177e4SLinus Torvalds 	case NFS4_OPEN_CLAIM_PREVIOUS:
12971da177e4SLinus Torvalds 		encode_claim_previous(xdr, arg->u.delegation_type);
12981da177e4SLinus Torvalds 		break;
12991da177e4SLinus Torvalds 	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
13001da177e4SLinus Torvalds 		encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
13011da177e4SLinus Torvalds 		break;
13021da177e4SLinus Torvalds 	default:
13031da177e4SLinus Torvalds 		BUG();
13041da177e4SLinus Torvalds 	}
1305d017931cSAndy Adamson 	hdr->nops++;
1306dadf0c27SBenny Halevy 	hdr->replen += decode_open_maxsz;
13071da177e4SLinus Torvalds }
13081da177e4SLinus Torvalds 
1309cf8cdbe5SAndy Adamson static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
13101da177e4SLinus Torvalds {
13118687b63aSAl Viro 	__be32 *p;
13121da177e4SLinus Torvalds 
131313c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
1314e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_OPEN_CONFIRM);
131593f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
131634558513SBenny Halevy 	*p = cpu_to_be32(arg->seqid->sequence->counter);
1317d017931cSAndy Adamson 	hdr->nops++;
1318dadf0c27SBenny Halevy 	hdr->replen += decode_open_confirm_maxsz;
13191da177e4SLinus Torvalds }
13201da177e4SLinus Torvalds 
1321cf8cdbe5SAndy Adamson static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
13221da177e4SLinus Torvalds {
13238687b63aSAl Viro 	__be32 *p;
13241da177e4SLinus Torvalds 
132513c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
1326e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_OPEN_DOWNGRADE);
132793f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
132834558513SBenny Halevy 	*p = cpu_to_be32(arg->seqid->sequence->counter);
1329dc0b027dSTrond Myklebust 	encode_share_access(xdr, arg->fmode);
1330d017931cSAndy Adamson 	hdr->nops++;
1331dadf0c27SBenny Halevy 	hdr->replen += decode_open_downgrade_maxsz;
13321da177e4SLinus Torvalds }
13331da177e4SLinus Torvalds 
1334cf8cdbe5SAndy Adamson static void
1335d017931cSAndy Adamson encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
13361da177e4SLinus Torvalds {
13371da177e4SLinus Torvalds 	int len = fh->size;
13388687b63aSAl Viro 	__be32 *p;
13391da177e4SLinus Torvalds 
134013c65ce9SBenny Halevy 	p = reserve_space(xdr, 8 + len);
1341e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_PUTFH);
1342811652bdSBenny Halevy 	xdr_encode_opaque(p, fh->data, len);
1343d017931cSAndy Adamson 	hdr->nops++;
1344dadf0c27SBenny Halevy 	hdr->replen += decode_putfh_maxsz;
13451da177e4SLinus Torvalds }
13461da177e4SLinus Torvalds 
1347cf8cdbe5SAndy Adamson static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
13481da177e4SLinus Torvalds {
13498687b63aSAl Viro 	__be32 *p;
13501da177e4SLinus Torvalds 
135113c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
135234558513SBenny Halevy 	*p = cpu_to_be32(OP_PUTROOTFH);
1353d017931cSAndy Adamson 	hdr->nops++;
1354dadf0c27SBenny Halevy 	hdr->replen += decode_putrootfh_maxsz;
13551da177e4SLinus Torvalds }
13561da177e4SLinus Torvalds 
1357f11ac8dbSTrond Myklebust static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx, const struct nfs_lock_context *l_ctx)
13581da177e4SLinus Torvalds {
13591da177e4SLinus Torvalds 	nfs4_stateid stateid;
13608687b63aSAl Viro 	__be32 *p;
13611da177e4SLinus Torvalds 
136213c65ce9SBenny Halevy 	p = reserve_space(xdr, NFS4_STATEID_SIZE);
13631da177e4SLinus Torvalds 	if (ctx->state != NULL) {
136477041ed9STrond Myklebust 		nfs4_copy_stateid(&stateid, ctx->state, l_ctx->lockowner, l_ctx->pid);
136534558513SBenny Halevy 		xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
13661da177e4SLinus Torvalds 	} else
136734558513SBenny Halevy 		xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
13681da177e4SLinus Torvalds }
13691da177e4SLinus Torvalds 
1370cf8cdbe5SAndy Adamson static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
13711da177e4SLinus Torvalds {
13728687b63aSAl Viro 	__be32 *p;
13731da177e4SLinus Torvalds 
137413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
137534558513SBenny Halevy 	*p = cpu_to_be32(OP_READ);
13761da177e4SLinus Torvalds 
1377f11ac8dbSTrond Myklebust 	encode_stateid(xdr, args->context, args->lock_context);
13781da177e4SLinus Torvalds 
137913c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
1380b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->offset);
138134558513SBenny Halevy 	*p = cpu_to_be32(args->count);
1382d017931cSAndy Adamson 	hdr->nops++;
1383dadf0c27SBenny Halevy 	hdr->replen += decode_read_maxsz;
13841da177e4SLinus Torvalds }
13851da177e4SLinus Torvalds 
1386cf8cdbe5SAndy Adamson static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
13871da177e4SLinus Torvalds {
138882f2e547SBryan Schumaker 	uint32_t attrs[2] = {0, 0};
13898687b63aSAl Viro 	__be32 *p;
13901da177e4SLinus Torvalds 
139182f2e547SBryan Schumaker 	if (readdir->plus) {
139282f2e547SBryan Schumaker 		attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
139382f2e547SBryan Schumaker 			FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE;
139482f2e547SBryan Schumaker 		attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
139582f2e547SBryan Schumaker 			FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
139682f2e547SBryan Schumaker 			FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
139782f2e547SBryan Schumaker 			FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
139882f2e547SBryan Schumaker 	}
139982f2e547SBryan Schumaker 	attrs[0] |= FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID;
140082f2e547SBryan Schumaker 	attrs[1] |= FATTR4_WORD1_MOUNTED_ON_FILEID;
140182f2e547SBryan Schumaker 
140213c65ce9SBenny Halevy 	p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
1403e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_READDIR);
1404b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, readdir->cookie);
140593f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
1406e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(readdir->count >> 1);  /* We're not doing readdirplus */
1407e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(readdir->count);
1408e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(2);
140982f2e547SBryan Schumaker 
141082f2e547SBryan Schumaker 	if (!readdir->plus) {
141197d312d0SManoj Naik 		/* Switch to mounted_on_fileid if the server supports it */
141297d312d0SManoj Naik 		if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
141397d312d0SManoj Naik 			attrs[0] &= ~FATTR4_WORD0_FILEID;
141497d312d0SManoj Naik 		else
141597d312d0SManoj Naik 			attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
141682f2e547SBryan Schumaker 	}
141782f2e547SBryan Schumaker 
1418e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
141934558513SBenny Halevy 	*p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
1420d017931cSAndy Adamson 	hdr->nops++;
1421dadf0c27SBenny Halevy 	hdr->replen += decode_readdir_maxsz;
142244109241SFred Isaman 	dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
142344109241SFred Isaman 			__func__,
1424eadf4598STrond Myklebust 			(unsigned long long)readdir->cookie,
1425eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[0],
1426eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[1],
1427eadf4598STrond Myklebust 			attrs[0] & readdir->bitmask[0],
1428eadf4598STrond Myklebust 			attrs[1] & readdir->bitmask[1]);
14291da177e4SLinus Torvalds }
14301da177e4SLinus Torvalds 
1431cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
14321da177e4SLinus Torvalds {
14338687b63aSAl Viro 	__be32 *p;
14341da177e4SLinus Torvalds 
143513c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
143634558513SBenny Halevy 	*p = cpu_to_be32(OP_READLINK);
1437d017931cSAndy Adamson 	hdr->nops++;
1438dadf0c27SBenny Halevy 	hdr->replen += decode_readlink_maxsz;
14391da177e4SLinus Torvalds }
14401da177e4SLinus Torvalds 
1441cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
14421da177e4SLinus Torvalds {
14438687b63aSAl Viro 	__be32 *p;
14441da177e4SLinus Torvalds 
144513c65ce9SBenny Halevy 	p = reserve_space(xdr, 8 + name->len);
1446e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_REMOVE);
1447811652bdSBenny Halevy 	xdr_encode_opaque(p, name->name, name->len);
1448d017931cSAndy Adamson 	hdr->nops++;
1449dadf0c27SBenny Halevy 	hdr->replen += decode_remove_maxsz;
14501da177e4SLinus Torvalds }
14511da177e4SLinus Torvalds 
1452cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
14531da177e4SLinus Torvalds {
14548687b63aSAl Viro 	__be32 *p;
14551da177e4SLinus Torvalds 
1456811652bdSBenny Halevy 	p = reserve_space(xdr, 4);
1457811652bdSBenny Halevy 	*p = cpu_to_be32(OP_RENAME);
1458811652bdSBenny Halevy 	encode_string(xdr, oldname->len, oldname->name);
1459811652bdSBenny Halevy 	encode_string(xdr, newname->len, newname->name);
1460d017931cSAndy Adamson 	hdr->nops++;
1461dadf0c27SBenny Halevy 	hdr->replen += decode_rename_maxsz;
14621da177e4SLinus Torvalds }
14631da177e4SLinus Torvalds 
1464cf8cdbe5SAndy Adamson static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr)
14651da177e4SLinus Torvalds {
14668687b63aSAl Viro 	__be32 *p;
14671da177e4SLinus Torvalds 
146813c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
1469e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_RENEW);
147034558513SBenny Halevy 	xdr_encode_hyper(p, client_stateid->cl_clientid);
1471d017931cSAndy Adamson 	hdr->nops++;
1472dadf0c27SBenny Halevy 	hdr->replen += decode_renew_maxsz;
14731da177e4SLinus Torvalds }
14741da177e4SLinus Torvalds 
1475cf8cdbe5SAndy Adamson static void
1476d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
147756ae19f3STrond Myklebust {
14788687b63aSAl Viro 	__be32 *p;
147956ae19f3STrond Myklebust 
148013c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
148134558513SBenny Halevy 	*p = cpu_to_be32(OP_RESTOREFH);
1482d017931cSAndy Adamson 	hdr->nops++;
1483dadf0c27SBenny Halevy 	hdr->replen += decode_restorefh_maxsz;
148456ae19f3STrond Myklebust }
148556ae19f3STrond Myklebust 
148656ae19f3STrond Myklebust static int
1487d017931cSAndy Adamson encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
148823ec6965SJ. Bruce Fields {
14898687b63aSAl Viro 	__be32 *p;
149023ec6965SJ. Bruce Fields 
149113c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
1492e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETATTR);
149334558513SBenny Halevy 	xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
149413c65ce9SBenny Halevy 	p = reserve_space(xdr, 2*4);
1495e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(1);
149634558513SBenny Halevy 	*p = cpu_to_be32(FATTR4_WORD0_ACL);
149723ec6965SJ. Bruce Fields 	if (arg->acl_len % 4)
149823ec6965SJ. Bruce Fields 		return -EINVAL;
149913c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
150034558513SBenny Halevy 	*p = cpu_to_be32(arg->acl_len);
150123ec6965SJ. Bruce Fields 	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
1502d017931cSAndy Adamson 	hdr->nops++;
1503dadf0c27SBenny Halevy 	hdr->replen += decode_setacl_maxsz;
150423ec6965SJ. Bruce Fields 	return 0;
150523ec6965SJ. Bruce Fields }
150623ec6965SJ. Bruce Fields 
1507cf8cdbe5SAndy Adamson static void
1508d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
15091da177e4SLinus Torvalds {
15108687b63aSAl Viro 	__be32 *p;
15111da177e4SLinus Torvalds 
151213c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
151334558513SBenny Halevy 	*p = cpu_to_be32(OP_SAVEFH);
1514d017931cSAndy Adamson 	hdr->nops++;
1515dadf0c27SBenny Halevy 	hdr->replen += decode_savefh_maxsz;
15161da177e4SLinus Torvalds }
15171da177e4SLinus Torvalds 
1518cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
15191da177e4SLinus Torvalds {
15208687b63aSAl Viro 	__be32 *p;
15211da177e4SLinus Torvalds 
152213c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
1523e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETATTR);
152434558513SBenny Halevy 	xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
1525d017931cSAndy Adamson 	hdr->nops++;
1526dadf0c27SBenny Halevy 	hdr->replen += decode_setattr_maxsz;
1527cf8cdbe5SAndy Adamson 	encode_attrs(xdr, arg->iap, server);
15281da177e4SLinus Torvalds }
15291da177e4SLinus Torvalds 
1530cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
15311da177e4SLinus Torvalds {
15328687b63aSAl Viro 	__be32 *p;
15331da177e4SLinus Torvalds 
153413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE);
1535e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETCLIENTID);
153634558513SBenny Halevy 	xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE);
15371da177e4SLinus Torvalds 
15381da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
153913c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
154034558513SBenny Halevy 	*p = cpu_to_be32(setclientid->sc_prog);
15411da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
15421da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
154313c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
154434558513SBenny Halevy 	*p = cpu_to_be32(setclientid->sc_cb_ident);
1545d017931cSAndy Adamson 	hdr->nops++;
1546dadf0c27SBenny Halevy 	hdr->replen += decode_setclientid_maxsz;
15471da177e4SLinus Torvalds }
15481da177e4SLinus Torvalds 
1549bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr)
15501da177e4SLinus Torvalds {
15518687b63aSAl Viro 	__be32 *p;
15521da177e4SLinus Torvalds 
155313c65ce9SBenny Halevy 	p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE);
1554e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM);
1555bb8b27e5STrond Myklebust 	p = xdr_encode_hyper(p, arg->clientid);
1556bb8b27e5STrond Myklebust 	xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE);
1557d017931cSAndy Adamson 	hdr->nops++;
1558dadf0c27SBenny Halevy 	hdr->replen += decode_setclientid_confirm_maxsz;
15591da177e4SLinus Torvalds }
15601da177e4SLinus Torvalds 
1561cf8cdbe5SAndy Adamson static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
15621da177e4SLinus Torvalds {
15638687b63aSAl Viro 	__be32 *p;
15641da177e4SLinus Torvalds 
156513c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
156634558513SBenny Halevy 	*p = cpu_to_be32(OP_WRITE);
15671da177e4SLinus Torvalds 
1568f11ac8dbSTrond Myklebust 	encode_stateid(xdr, args->context, args->lock_context);
15691da177e4SLinus Torvalds 
157013c65ce9SBenny Halevy 	p = reserve_space(xdr, 16);
1571b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->offset);
1572e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->stable);
157334558513SBenny Halevy 	*p = cpu_to_be32(args->count);
15741da177e4SLinus Torvalds 
15751da177e4SLinus Torvalds 	xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1576d017931cSAndy Adamson 	hdr->nops++;
1577dadf0c27SBenny Halevy 	hdr->replen += decode_write_maxsz;
15781da177e4SLinus Torvalds }
15791da177e4SLinus Torvalds 
1580cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
15811da177e4SLinus Torvalds {
15828687b63aSAl Viro 	__be32 *p;
15831da177e4SLinus Torvalds 
158413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
15851da177e4SLinus Torvalds 
1586e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_DELEGRETURN);
158734558513SBenny Halevy 	xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
1588d017931cSAndy Adamson 	hdr->nops++;
1589dadf0c27SBenny Halevy 	hdr->replen += decode_delegreturn_maxsz;
15901da177e4SLinus Torvalds }
15919b7b9fccSAndy Adamson 
159299fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
15939b7b9fccSAndy Adamson /* NFSv4.1 operations */
159499fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr,
159599fe60d0SBenny Halevy 			       struct nfs41_exchange_id_args *args,
159699fe60d0SBenny Halevy 			       struct compound_hdr *hdr)
159799fe60d0SBenny Halevy {
159899fe60d0SBenny Halevy 	__be32 *p;
159999fe60d0SBenny Halevy 
160013c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + sizeof(args->verifier->data));
1601e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_EXCHANGE_ID);
160234558513SBenny Halevy 	xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data));
160399fe60d0SBenny Halevy 
160499fe60d0SBenny Halevy 	encode_string(xdr, args->id_len, args->id);
160599fe60d0SBenny Halevy 
160613c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
1607e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->flags);
1608e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);	/* zero length state_protect4_a */
160934558513SBenny Halevy 	*p = cpu_to_be32(0);	/* zero length implementation id array */
161099fe60d0SBenny Halevy 	hdr->nops++;
161199fe60d0SBenny Halevy 	hdr->replen += decode_exchange_id_maxsz;
161299fe60d0SBenny Halevy }
1613fc931582SAndy Adamson 
1614fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr,
1615fc931582SAndy Adamson 				  struct nfs41_create_session_args *args,
1616fc931582SAndy Adamson 				  struct compound_hdr *hdr)
1617fc931582SAndy Adamson {
1618fc931582SAndy Adamson 	__be32 *p;
1619fc931582SAndy Adamson 	char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
1620fc931582SAndy Adamson 	uint32_t len;
1621fc931582SAndy Adamson 	struct nfs_client *clp = args->client;
16228e0d46e1SMike Sager 	u32 max_resp_sz_cached;
16238e0d46e1SMike Sager 
16248e0d46e1SMike Sager 	/*
16258e0d46e1SMike Sager 	 * Assumes OPEN is the biggest non-idempotent compound.
16268e0d46e1SMike Sager 	 * 2 is the verifier.
16278e0d46e1SMike Sager 	 */
16288e0d46e1SMike Sager 	max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
16298e0d46e1SMike Sager 			      RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
1630fc931582SAndy Adamson 
1631fc931582SAndy Adamson 	len = scnprintf(machine_name, sizeof(machine_name), "%s",
1632fc931582SAndy Adamson 			clp->cl_ipaddr);
163342edd698SBenny Halevy 
163413c65ce9SBenny Halevy 	p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12);
1635e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_CREATE_SESSION);
1636b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, clp->cl_ex_clid);
1637e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(clp->cl_seqid);			/*Sequence id */
1638e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->flags);			/*flags */
1639fc931582SAndy Adamson 
1640fc931582SAndy Adamson 	/* Fore Channel */
1641e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.headerpadsz);	/* header padding size */
1642e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz);	/* max req size */
1643e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz);	/* max resp size */
16448e0d46e1SMike Sager 	*p++ = cpu_to_be32(max_resp_sz_cached);		/* Max resp sz cached */
1645e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_ops);	/* max operations */
1646e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_reqs);	/* max requests */
1647e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
1648fc931582SAndy Adamson 
1649fc931582SAndy Adamson 	/* Back Channel */
1650e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.headerpadsz);	/* header padding size */
1651e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz);	/* max req size */
1652e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz);	/* max resp size */
1653e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached);	/* Max resp sz cached */
1654e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_ops);	/* max operations */
1655e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_reqs);	/* max requests */
1656e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
1657fc931582SAndy Adamson 
1658e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->cb_program);		/* cb_program */
1659e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(1);
1660e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(RPC_AUTH_UNIX);			/* auth_sys */
1661fc931582SAndy Adamson 
1662fc931582SAndy Adamson 	/* authsys_parms rfc1831 */
1663e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec);	/* stamp */
1664811652bdSBenny Halevy 	p = xdr_encode_opaque(p, machine_name, len);
1665e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* UID */
1666e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* GID */
166734558513SBenny Halevy 	*p = cpu_to_be32(0);				/* No more gids */
1668fc931582SAndy Adamson 	hdr->nops++;
1669fc931582SAndy Adamson 	hdr->replen += decode_create_session_maxsz;
1670fc931582SAndy Adamson }
16710f3e66c6SAndy Adamson 
16720f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr,
16730f3e66c6SAndy Adamson 				   struct nfs4_session *session,
16740f3e66c6SAndy Adamson 				   struct compound_hdr *hdr)
16750f3e66c6SAndy Adamson {
16760f3e66c6SAndy Adamson 	__be32 *p;
167713c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN);
1678e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_DESTROY_SESSION);
167934558513SBenny Halevy 	xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
16800f3e66c6SAndy Adamson 	hdr->nops++;
16810f3e66c6SAndy Adamson 	hdr->replen += decode_destroy_session_maxsz;
16820f3e66c6SAndy Adamson }
168318019753SRicardo Labiaga 
168418019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr,
168518019753SRicardo Labiaga 				    struct nfs41_reclaim_complete_args *args,
168618019753SRicardo Labiaga 				    struct compound_hdr *hdr)
168718019753SRicardo Labiaga {
168818019753SRicardo Labiaga 	__be32 *p;
168918019753SRicardo Labiaga 
169018019753SRicardo Labiaga 	p = reserve_space(xdr, 8);
169118019753SRicardo Labiaga 	*p++ = cpu_to_be32(OP_RECLAIM_COMPLETE);
169218019753SRicardo Labiaga 	*p++ = cpu_to_be32(args->one_fs);
169318019753SRicardo Labiaga 	hdr->nops++;
169418019753SRicardo Labiaga 	hdr->replen += decode_reclaim_complete_maxsz;
169518019753SRicardo Labiaga }
169699fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
169799fe60d0SBenny Halevy 
16989b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr,
16999b7b9fccSAndy Adamson 			    const struct nfs4_sequence_args *args,
17009b7b9fccSAndy Adamson 			    struct compound_hdr *hdr)
17019b7b9fccSAndy Adamson {
17029b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1)
17039b7b9fccSAndy Adamson 	struct nfs4_session *session = args->sa_session;
1704fc01cea9SAndy Adamson 	struct nfs4_slot_table *tp;
1705fc01cea9SAndy Adamson 	struct nfs4_slot *slot;
1706fc01cea9SAndy Adamson 	__be32 *p;
17079b7b9fccSAndy Adamson 
17089b7b9fccSAndy Adamson 	if (!session)
17099b7b9fccSAndy Adamson 		return;
17109b7b9fccSAndy Adamson 
1711fc01cea9SAndy Adamson 	tp = &session->fc_slot_table;
1712fc01cea9SAndy Adamson 
1713fc01cea9SAndy Adamson 	WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
1714fc01cea9SAndy Adamson 	slot = tp->slots + args->sa_slotid;
1715fc01cea9SAndy Adamson 
171613c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16);
1717e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SEQUENCE);
1718fc01cea9SAndy Adamson 
1719fc01cea9SAndy Adamson 	/*
1720fc01cea9SAndy Adamson 	 * Sessionid + seqid + slotid + max slotid + cache_this
1721fc01cea9SAndy Adamson 	 */
1722fc01cea9SAndy Adamson 	dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1723fc01cea9SAndy Adamson 		"max_slotid=%d cache_this=%d\n",
1724fc01cea9SAndy Adamson 		__func__,
1725fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[0],
1726fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[1],
1727fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[2],
1728fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[3],
1729fc01cea9SAndy Adamson 		slot->seq_nr, args->sa_slotid,
1730fc01cea9SAndy Adamson 		tp->highest_used_slotid, args->sa_cache_this);
173193f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
1732e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(slot->seq_nr);
1733e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->sa_slotid);
1734e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(tp->highest_used_slotid);
173534558513SBenny Halevy 	*p = cpu_to_be32(args->sa_cache_this);
17369b7b9fccSAndy Adamson 	hdr->nops++;
17379b7b9fccSAndy Adamson 	hdr->replen += decode_sequence_maxsz;
17389b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */
17399b7b9fccSAndy Adamson }
17409b7b9fccSAndy Adamson 
17411da177e4SLinus Torvalds /*
17421da177e4SLinus Torvalds  * END OF "GENERIC" ENCODE ROUTINES.
17431da177e4SLinus Torvalds  */
17441da177e4SLinus Torvalds 
174566cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
174666cc0429SBenny Halevy {
174766cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1)
174866cc0429SBenny Halevy 	if (args->sa_session)
1749a4432345STrond Myklebust 		return args->sa_session->clp->cl_mvops->minor_version;
175066cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
175166cc0429SBenny Halevy 	return 0;
175266cc0429SBenny Halevy }
175366cc0429SBenny Halevy 
17541da177e4SLinus Torvalds /*
17551da177e4SLinus Torvalds  * Encode an ACCESS request
17561da177e4SLinus Torvalds  */
17578687b63aSAl Viro static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
17581da177e4SLinus Torvalds {
17591da177e4SLinus Torvalds 	struct xdr_stream xdr;
17601da177e4SLinus Torvalds 	struct compound_hdr hdr = {
176166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
17621da177e4SLinus Torvalds 	};
17631da177e4SLinus Torvalds 
17641da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
17650c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
17669b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1767cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1768cf8cdbe5SAndy Adamson 	encode_access(&xdr, args->access, &hdr);
1769cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1770d017931cSAndy Adamson 	encode_nops(&hdr);
1771cf8cdbe5SAndy Adamson 	return 0;
17721da177e4SLinus Torvalds }
17731da177e4SLinus Torvalds 
17741da177e4SLinus Torvalds /*
17751da177e4SLinus Torvalds  * Encode LOOKUP request
17761da177e4SLinus Torvalds  */
17778687b63aSAl Viro static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
17781da177e4SLinus Torvalds {
17791da177e4SLinus Torvalds 	struct xdr_stream xdr;
17801da177e4SLinus Torvalds 	struct compound_hdr hdr = {
178166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
17821da177e4SLinus Torvalds 	};
17831da177e4SLinus Torvalds 
17841da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
17850c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
17869b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1787cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1788cf8cdbe5SAndy Adamson 	encode_lookup(&xdr, args->name, &hdr);
1789cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1790cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1791d017931cSAndy Adamson 	encode_nops(&hdr);
1792cf8cdbe5SAndy Adamson 	return 0;
17931da177e4SLinus Torvalds }
17941da177e4SLinus Torvalds 
17951da177e4SLinus Torvalds /*
17961da177e4SLinus Torvalds  * Encode LOOKUP_ROOT request
17971da177e4SLinus Torvalds  */
17988687b63aSAl Viro static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
17991da177e4SLinus Torvalds {
18001da177e4SLinus Torvalds 	struct xdr_stream xdr;
18011da177e4SLinus Torvalds 	struct compound_hdr hdr = {
180266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18031da177e4SLinus Torvalds 	};
18041da177e4SLinus Torvalds 
18051da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18060c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18079b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1808cf8cdbe5SAndy Adamson 	encode_putrootfh(&xdr, &hdr);
1809cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1810cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1811d017931cSAndy Adamson 	encode_nops(&hdr);
1812cf8cdbe5SAndy Adamson 	return 0;
18131da177e4SLinus Torvalds }
18141da177e4SLinus Torvalds 
18151da177e4SLinus Torvalds /*
18161da177e4SLinus Torvalds  * Encode REMOVE request
18171da177e4SLinus Torvalds  */
18184fdc17b2STrond Myklebust static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
18191da177e4SLinus Torvalds {
18201da177e4SLinus Torvalds 	struct xdr_stream xdr;
18211da177e4SLinus Torvalds 	struct compound_hdr hdr = {
182266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18231da177e4SLinus Torvalds 	};
18241da177e4SLinus Torvalds 
18251da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18260c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18279b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1828cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1829cf8cdbe5SAndy Adamson 	encode_remove(&xdr, &args->name, &hdr);
1830cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1831d017931cSAndy Adamson 	encode_nops(&hdr);
1832cf8cdbe5SAndy Adamson 	return 0;
18331da177e4SLinus Torvalds }
18341da177e4SLinus Torvalds 
18351da177e4SLinus Torvalds /*
18361da177e4SLinus Torvalds  * Encode RENAME request
18371da177e4SLinus Torvalds  */
1838920769f0SJeff Layton static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs_renameargs *args)
18391da177e4SLinus Torvalds {
18401da177e4SLinus Torvalds 	struct xdr_stream xdr;
18411da177e4SLinus Torvalds 	struct compound_hdr hdr = {
184266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18431da177e4SLinus Torvalds 	};
18441da177e4SLinus Torvalds 
18451da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18460c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18479b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1848cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->old_dir, &hdr);
1849cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1850cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->new_dir, &hdr);
1851cf8cdbe5SAndy Adamson 	encode_rename(&xdr, args->old_name, args->new_name, &hdr);
1852cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1853cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1854cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1855d017931cSAndy Adamson 	encode_nops(&hdr);
1856cf8cdbe5SAndy Adamson 	return 0;
18571da177e4SLinus Torvalds }
18581da177e4SLinus Torvalds 
18591da177e4SLinus Torvalds /*
18601da177e4SLinus Torvalds  * Encode LINK request
18611da177e4SLinus Torvalds  */
18628687b63aSAl Viro static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
18631da177e4SLinus Torvalds {
18641da177e4SLinus Torvalds 	struct xdr_stream xdr;
18651da177e4SLinus Torvalds 	struct compound_hdr hdr = {
186666cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18671da177e4SLinus Torvalds 	};
18681da177e4SLinus Torvalds 
18691da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18700c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18719b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1872cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1873cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1874cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1875cf8cdbe5SAndy Adamson 	encode_link(&xdr, args->name, &hdr);
1876cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1877cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1878cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1879d017931cSAndy Adamson 	encode_nops(&hdr);
1880cf8cdbe5SAndy Adamson 	return 0;
18811da177e4SLinus Torvalds }
18821da177e4SLinus Torvalds 
18831da177e4SLinus Torvalds /*
18841da177e4SLinus Torvalds  * Encode CREATE request
18851da177e4SLinus Torvalds  */
18868687b63aSAl Viro static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
18871da177e4SLinus Torvalds {
18881da177e4SLinus Torvalds 	struct xdr_stream xdr;
18891da177e4SLinus Torvalds 	struct compound_hdr hdr = {
189066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18911da177e4SLinus Torvalds 	};
18921da177e4SLinus Torvalds 
18931da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18940c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18959b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1896cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1897cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1898cf8cdbe5SAndy Adamson 	encode_create(&xdr, args, &hdr);
1899cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1900cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1901cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1902cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1903d017931cSAndy Adamson 	encode_nops(&hdr);
1904cf8cdbe5SAndy Adamson 	return 0;
19051da177e4SLinus Torvalds }
19061da177e4SLinus Torvalds 
19071da177e4SLinus Torvalds /*
19081da177e4SLinus Torvalds  * Encode SYMLINK request
19091da177e4SLinus Torvalds  */
19108687b63aSAl Viro static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
19111da177e4SLinus Torvalds {
19121da177e4SLinus Torvalds 	return nfs4_xdr_enc_create(req, p, args);
19131da177e4SLinus Torvalds }
19141da177e4SLinus Torvalds 
19151da177e4SLinus Torvalds /*
19161da177e4SLinus Torvalds  * Encode GETATTR request
19171da177e4SLinus Torvalds  */
19188687b63aSAl Viro static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
19191da177e4SLinus Torvalds {
19201da177e4SLinus Torvalds 	struct xdr_stream xdr;
19211da177e4SLinus Torvalds 	struct compound_hdr hdr = {
192266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19231da177e4SLinus Torvalds 	};
19241da177e4SLinus Torvalds 
19251da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19260c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19279b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1928cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1929cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1930d017931cSAndy Adamson 	encode_nops(&hdr);
1931cf8cdbe5SAndy Adamson 	return 0;
19321da177e4SLinus Torvalds }
19331da177e4SLinus Torvalds 
19341da177e4SLinus Torvalds /*
19351da177e4SLinus Torvalds  * Encode a CLOSE request
19361da177e4SLinus Torvalds  */
19378687b63aSAl Viro static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
19381da177e4SLinus Torvalds {
19391da177e4SLinus Torvalds 	struct xdr_stream xdr;
19401da177e4SLinus Torvalds 	struct compound_hdr hdr = {
194166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19421da177e4SLinus Torvalds 	};
19431da177e4SLinus Torvalds 
19441da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19450c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19469b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1947cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1948cf8cdbe5SAndy Adamson 	encode_close(&xdr, args, &hdr);
1949cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1950d017931cSAndy Adamson 	encode_nops(&hdr);
1951cf8cdbe5SAndy Adamson 	return 0;
19521da177e4SLinus Torvalds }
19531da177e4SLinus Torvalds 
19541da177e4SLinus Torvalds /*
19551da177e4SLinus Torvalds  * Encode an OPEN request
19561da177e4SLinus Torvalds  */
19578687b63aSAl Viro static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
19581da177e4SLinus Torvalds {
19591da177e4SLinus Torvalds 	struct xdr_stream xdr;
19601da177e4SLinus Torvalds 	struct compound_hdr hdr = {
196166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19621da177e4SLinus Torvalds 	};
19631da177e4SLinus Torvalds 
19641da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19650c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19669b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1967cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1968cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1969cf8cdbe5SAndy Adamson 	encode_open(&xdr, args, &hdr);
1970cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1971cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1972cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1973cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1974d017931cSAndy Adamson 	encode_nops(&hdr);
1975cf8cdbe5SAndy Adamson 	return 0;
19761da177e4SLinus Torvalds }
19771da177e4SLinus Torvalds 
19781da177e4SLinus Torvalds /*
19791da177e4SLinus Torvalds  * Encode an OPEN_CONFIRM request
19801da177e4SLinus Torvalds  */
19818687b63aSAl Viro static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_open_confirmargs *args)
19821da177e4SLinus Torvalds {
19831da177e4SLinus Torvalds 	struct xdr_stream xdr;
19841da177e4SLinus Torvalds 	struct compound_hdr hdr = {
1985d017931cSAndy Adamson 		.nops   = 0,
19861da177e4SLinus Torvalds 	};
19871da177e4SLinus Torvalds 
19881da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19890c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
1990cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1991cf8cdbe5SAndy Adamson 	encode_open_confirm(&xdr, args, &hdr);
1992d017931cSAndy Adamson 	encode_nops(&hdr);
1993cf8cdbe5SAndy Adamson 	return 0;
19941da177e4SLinus Torvalds }
19951da177e4SLinus Torvalds 
19961da177e4SLinus Torvalds /*
19971da177e4SLinus Torvalds  * Encode an OPEN request with no attributes.
19981da177e4SLinus Torvalds  */
19998687b63aSAl Viro static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
20001da177e4SLinus Torvalds {
20011da177e4SLinus Torvalds 	struct xdr_stream xdr;
20021da177e4SLinus Torvalds 	struct compound_hdr hdr = {
200366cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20041da177e4SLinus Torvalds 	};
20051da177e4SLinus Torvalds 
20061da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20070c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20089b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2009cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2010cf8cdbe5SAndy Adamson 	encode_open(&xdr, args, &hdr);
2011cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2012d017931cSAndy Adamson 	encode_nops(&hdr);
2013cf8cdbe5SAndy Adamson 	return 0;
20141da177e4SLinus Torvalds }
20151da177e4SLinus Torvalds 
20161da177e4SLinus Torvalds /*
20171da177e4SLinus Torvalds  * Encode an OPEN_DOWNGRADE request
20181da177e4SLinus Torvalds  */
20198687b63aSAl Viro static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
20201da177e4SLinus Torvalds {
20211da177e4SLinus Torvalds 	struct xdr_stream xdr;
20221da177e4SLinus Torvalds 	struct compound_hdr hdr = {
202366cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20241da177e4SLinus Torvalds 	};
20251da177e4SLinus Torvalds 
20261da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20270c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20289b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2029cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2030cf8cdbe5SAndy Adamson 	encode_open_downgrade(&xdr, args, &hdr);
2031cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2032d017931cSAndy Adamson 	encode_nops(&hdr);
2033cf8cdbe5SAndy Adamson 	return 0;
20341da177e4SLinus Torvalds }
20351da177e4SLinus Torvalds 
20361da177e4SLinus Torvalds /*
20371da177e4SLinus Torvalds  * Encode a LOCK request
20381da177e4SLinus Torvalds  */
20398687b63aSAl Viro static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
20401da177e4SLinus Torvalds {
20411da177e4SLinus Torvalds 	struct xdr_stream xdr;
20421da177e4SLinus Torvalds 	struct compound_hdr hdr = {
204366cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20441da177e4SLinus Torvalds 	};
20451da177e4SLinus Torvalds 
20461da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20470c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20489b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2049cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2050cf8cdbe5SAndy Adamson 	encode_lock(&xdr, args, &hdr);
2051d017931cSAndy Adamson 	encode_nops(&hdr);
2052cf8cdbe5SAndy Adamson 	return 0;
20531da177e4SLinus Torvalds }
20541da177e4SLinus Torvalds 
20551da177e4SLinus Torvalds /*
20561da177e4SLinus Torvalds  * Encode a LOCKT request
20571da177e4SLinus Torvalds  */
20588687b63aSAl Viro static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
20591da177e4SLinus Torvalds {
20601da177e4SLinus Torvalds 	struct xdr_stream xdr;
20611da177e4SLinus Torvalds 	struct compound_hdr hdr = {
206266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20631da177e4SLinus Torvalds 	};
20641da177e4SLinus Torvalds 
20651da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20660c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20679b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2068cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2069cf8cdbe5SAndy Adamson 	encode_lockt(&xdr, args, &hdr);
2070d017931cSAndy Adamson 	encode_nops(&hdr);
2071cf8cdbe5SAndy Adamson 	return 0;
20721da177e4SLinus Torvalds }
20731da177e4SLinus Torvalds 
20741da177e4SLinus Torvalds /*
20751da177e4SLinus Torvalds  * Encode a LOCKU request
20761da177e4SLinus Torvalds  */
20778687b63aSAl Viro static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
20781da177e4SLinus Torvalds {
20791da177e4SLinus Torvalds 	struct xdr_stream xdr;
20801da177e4SLinus Torvalds 	struct compound_hdr hdr = {
208166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20821da177e4SLinus Torvalds 	};
20831da177e4SLinus Torvalds 
20841da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20850c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20869b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2087cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2088cf8cdbe5SAndy Adamson 	encode_locku(&xdr, args, &hdr);
2089d017931cSAndy Adamson 	encode_nops(&hdr);
2090cf8cdbe5SAndy Adamson 	return 0;
20911da177e4SLinus Torvalds }
20921da177e4SLinus Torvalds 
2093d3c7b7ccSTrond Myklebust static int nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, __be32 *p, struct nfs_release_lockowner_args *args)
2094d3c7b7ccSTrond Myklebust {
2095d3c7b7ccSTrond Myklebust 	struct xdr_stream xdr;
2096d3c7b7ccSTrond Myklebust 	struct compound_hdr hdr = {
2097d3c7b7ccSTrond Myklebust 		.minorversion = 0,
2098d3c7b7ccSTrond Myklebust 	};
2099d3c7b7ccSTrond Myklebust 
2100d3c7b7ccSTrond Myklebust 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2101d3c7b7ccSTrond Myklebust 	encode_compound_hdr(&xdr, req, &hdr);
2102d3c7b7ccSTrond Myklebust 	encode_release_lockowner(&xdr, &args->lock_owner, &hdr);
2103d3c7b7ccSTrond Myklebust 	encode_nops(&hdr);
2104d3c7b7ccSTrond Myklebust 	return 0;
2105d3c7b7ccSTrond Myklebust }
2106d3c7b7ccSTrond Myklebust 
21071da177e4SLinus Torvalds /*
21081da177e4SLinus Torvalds  * Encode a READLINK request
21091da177e4SLinus Torvalds  */
21108687b63aSAl Viro static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
21111da177e4SLinus Torvalds {
21121da177e4SLinus Torvalds 	struct xdr_stream xdr;
21131da177e4SLinus Torvalds 	struct compound_hdr hdr = {
211466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21151da177e4SLinus Torvalds 	};
21161da177e4SLinus Torvalds 
21171da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21180c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21199b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2120cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2121cf8cdbe5SAndy Adamson 	encode_readlink(&xdr, args, req, &hdr);
2122e3a535e1STrond Myklebust 
212328f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2124e3a535e1STrond Myklebust 			args->pgbase, args->pglen);
2125d017931cSAndy Adamson 	encode_nops(&hdr);
2126cf8cdbe5SAndy Adamson 	return 0;
21271da177e4SLinus Torvalds }
21281da177e4SLinus Torvalds 
21291da177e4SLinus Torvalds /*
21301da177e4SLinus Torvalds  * Encode a READDIR request
21311da177e4SLinus Torvalds  */
21328687b63aSAl Viro static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
21331da177e4SLinus Torvalds {
21341da177e4SLinus Torvalds 	struct xdr_stream xdr;
21351da177e4SLinus Torvalds 	struct compound_hdr hdr = {
213666cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21371da177e4SLinus Torvalds 	};
21381da177e4SLinus Torvalds 
21391da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21400c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21419b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2142cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2143cf8cdbe5SAndy Adamson 	encode_readdir(&xdr, args, req, &hdr);
2144d6ac02dfSTrond Myklebust 
214528f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2146d6ac02dfSTrond Myklebust 			 args->pgbase, args->count);
2147d6ac02dfSTrond Myklebust 	dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
214828f56694SBenny Halevy 			__func__, hdr.replen << 2, args->pages,
2149d6ac02dfSTrond Myklebust 			args->pgbase, args->count);
2150d017931cSAndy Adamson 	encode_nops(&hdr);
2151cf8cdbe5SAndy Adamson 	return 0;
21521da177e4SLinus Torvalds }
21531da177e4SLinus Torvalds 
21541da177e4SLinus Torvalds /*
21551da177e4SLinus Torvalds  * Encode a READ request
21561da177e4SLinus Torvalds  */
21578687b63aSAl Viro static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
21581da177e4SLinus Torvalds {
21591da177e4SLinus Torvalds 	struct xdr_stream xdr;
21601da177e4SLinus Torvalds 	struct compound_hdr hdr = {
216166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21621da177e4SLinus Torvalds 	};
21631da177e4SLinus Torvalds 
21641da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21650c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21669b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2167cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2168cf8cdbe5SAndy Adamson 	encode_read(&xdr, args, &hdr);
21691da177e4SLinus Torvalds 
217028f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
21711da177e4SLinus Torvalds 			 args->pages, args->pgbase, args->count);
21724f22ccc3S\"Talpey, Thomas\ 	req->rq_rcv_buf.flags |= XDRBUF_READ;
2173d017931cSAndy Adamson 	encode_nops(&hdr);
2174cf8cdbe5SAndy Adamson 	return 0;
21751da177e4SLinus Torvalds }
21761da177e4SLinus Torvalds 
21771da177e4SLinus Torvalds /*
21781da177e4SLinus Torvalds  * Encode an SETATTR request
21791da177e4SLinus Torvalds  */
21808687b63aSAl Viro static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
21811da177e4SLinus Torvalds {
21821da177e4SLinus Torvalds 	struct xdr_stream xdr;
21831da177e4SLinus Torvalds 	struct compound_hdr hdr = {
218466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21851da177e4SLinus Torvalds 	};
21861da177e4SLinus Torvalds 
21871da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21880c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21899b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2190cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2191cf8cdbe5SAndy Adamson 	encode_setattr(&xdr, args, args->server, &hdr);
2192cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2193d017931cSAndy Adamson 	encode_nops(&hdr);
2194cf8cdbe5SAndy Adamson 	return 0;
21951da177e4SLinus Torvalds }
21961da177e4SLinus Torvalds 
21971da177e4SLinus Torvalds /*
2198029d105eSJ. Bruce Fields  * Encode a GETACL request
2199029d105eSJ. Bruce Fields  */
2200029d105eSJ. Bruce Fields static int
22018687b63aSAl Viro nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
2202029d105eSJ. Bruce Fields 		struct nfs_getaclargs *args)
2203029d105eSJ. Bruce Fields {
2204029d105eSJ. Bruce Fields 	struct xdr_stream xdr;
2205029d105eSJ. Bruce Fields 	struct compound_hdr hdr = {
220666cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
2207029d105eSJ. Bruce Fields 	};
220828f56694SBenny Halevy 	uint32_t replen;
2209029d105eSJ. Bruce Fields 
2210029d105eSJ. Bruce Fields 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22110c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22129b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2213cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2214d327cf74SJ. Bruce Fields 	replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
2215cf8cdbe5SAndy Adamson 	encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
2216cf8cdbe5SAndy Adamson 
221728f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
2218029d105eSJ. Bruce Fields 		args->acl_pages, args->acl_pgbase, args->acl_len);
2219d017931cSAndy Adamson 	encode_nops(&hdr);
2220cf8cdbe5SAndy Adamson 	return 0;
2221029d105eSJ. Bruce Fields }
2222029d105eSJ. Bruce Fields 
2223029d105eSJ. Bruce Fields /*
22241da177e4SLinus Torvalds  * Encode a WRITE request
22251da177e4SLinus Torvalds  */
22268687b63aSAl Viro static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
22271da177e4SLinus Torvalds {
22281da177e4SLinus Torvalds 	struct xdr_stream xdr;
22291da177e4SLinus Torvalds 	struct compound_hdr hdr = {
223066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22311da177e4SLinus Torvalds 	};
22321da177e4SLinus Torvalds 
22331da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22340c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22359b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2236cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2237cf8cdbe5SAndy Adamson 	encode_write(&xdr, args, &hdr);
22384f22ccc3S\"Talpey, Thomas\ 	req->rq_snd_buf.flags |= XDRBUF_WRITE;
2239cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2240d017931cSAndy Adamson 	encode_nops(&hdr);
2241cf8cdbe5SAndy Adamson 	return 0;
22421da177e4SLinus Torvalds }
22431da177e4SLinus Torvalds 
22441da177e4SLinus Torvalds /*
22451da177e4SLinus Torvalds  *  a COMMIT request
22461da177e4SLinus Torvalds  */
22478687b63aSAl Viro static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
22481da177e4SLinus Torvalds {
22491da177e4SLinus Torvalds 	struct xdr_stream xdr;
22501da177e4SLinus Torvalds 	struct compound_hdr hdr = {
225166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22521da177e4SLinus Torvalds 	};
22531da177e4SLinus Torvalds 
22541da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22550c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22569b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2257cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2258cf8cdbe5SAndy Adamson 	encode_commit(&xdr, args, &hdr);
2259cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2260d017931cSAndy Adamson 	encode_nops(&hdr);
2261cf8cdbe5SAndy Adamson 	return 0;
22621da177e4SLinus Torvalds }
22631da177e4SLinus Torvalds 
22641da177e4SLinus Torvalds /*
22651da177e4SLinus Torvalds  * FSINFO request
22661da177e4SLinus Torvalds  */
22678687b63aSAl Viro static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
22681da177e4SLinus Torvalds {
22691da177e4SLinus Torvalds 	struct xdr_stream xdr;
22701da177e4SLinus Torvalds 	struct compound_hdr hdr = {
227166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22721da177e4SLinus Torvalds 	};
22731da177e4SLinus Torvalds 
22741da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22750c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22769b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2277cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2278cf8cdbe5SAndy Adamson 	encode_fsinfo(&xdr, args->bitmask, &hdr);
2279d017931cSAndy Adamson 	encode_nops(&hdr);
2280cf8cdbe5SAndy Adamson 	return 0;
22811da177e4SLinus Torvalds }
22821da177e4SLinus Torvalds 
22831da177e4SLinus Torvalds /*
22841da177e4SLinus Torvalds  * a PATHCONF request
22851da177e4SLinus Torvalds  */
22868687b63aSAl Viro static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
22871da177e4SLinus Torvalds {
22881da177e4SLinus Torvalds 	struct xdr_stream xdr;
22891da177e4SLinus Torvalds 	struct compound_hdr hdr = {
229066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22911da177e4SLinus Torvalds 	};
22921da177e4SLinus Torvalds 
22931da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22940c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22959b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2296cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2297cf8cdbe5SAndy Adamson 	encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
2298d017931cSAndy Adamson 			   &hdr);
2299d017931cSAndy Adamson 	encode_nops(&hdr);
2300cf8cdbe5SAndy Adamson 	return 0;
23011da177e4SLinus Torvalds }
23021da177e4SLinus Torvalds 
23031da177e4SLinus Torvalds /*
23041da177e4SLinus Torvalds  * a STATFS request
23051da177e4SLinus Torvalds  */
23068687b63aSAl Viro static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
23071da177e4SLinus Torvalds {
23081da177e4SLinus Torvalds 	struct xdr_stream xdr;
23091da177e4SLinus Torvalds 	struct compound_hdr hdr = {
231066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
23111da177e4SLinus Torvalds 	};
23121da177e4SLinus Torvalds 
23131da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23140c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
23159b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2316cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2317cf8cdbe5SAndy Adamson 	encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
2318d017931cSAndy Adamson 			   args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
2319d017931cSAndy Adamson 	encode_nops(&hdr);
2320cf8cdbe5SAndy Adamson 	return 0;
23211da177e4SLinus Torvalds }
23221da177e4SLinus Torvalds 
23231da177e4SLinus Torvalds /*
23241da177e4SLinus Torvalds  * GETATTR_BITMAP request
23251da177e4SLinus Torvalds  */
232643652ad5SBenny Halevy static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
232743652ad5SBenny Halevy 				    struct nfs4_server_caps_arg *args)
23281da177e4SLinus Torvalds {
23291da177e4SLinus Torvalds 	struct xdr_stream xdr;
23301da177e4SLinus Torvalds 	struct compound_hdr hdr = {
233166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
23321da177e4SLinus Torvalds 	};
23331da177e4SLinus Torvalds 
23341da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23350c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
23369b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
233743652ad5SBenny Halevy 	encode_putfh(&xdr, args->fhandle, &hdr);
2338cf8cdbe5SAndy Adamson 	encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
23391da177e4SLinus Torvalds 			   FATTR4_WORD0_LINK_SUPPORT|
23401da177e4SLinus Torvalds 			   FATTR4_WORD0_SYMLINK_SUPPORT|
2341d017931cSAndy Adamson 			   FATTR4_WORD0_ACLSUPPORT, &hdr);
2342d017931cSAndy Adamson 	encode_nops(&hdr);
2343cf8cdbe5SAndy Adamson 	return 0;
23441da177e4SLinus Torvalds }
23451da177e4SLinus Torvalds 
23461da177e4SLinus Torvalds /*
23471da177e4SLinus Torvalds  * a RENEW request
23481da177e4SLinus Torvalds  */
23498687b63aSAl Viro static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
23501da177e4SLinus Torvalds {
23511da177e4SLinus Torvalds 	struct xdr_stream xdr;
23521da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2353d017931cSAndy Adamson 		.nops	= 0,
23541da177e4SLinus Torvalds 	};
23551da177e4SLinus Torvalds 
23561da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23570c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2358cf8cdbe5SAndy Adamson 	encode_renew(&xdr, clp, &hdr);
2359d017931cSAndy Adamson 	encode_nops(&hdr);
2360cf8cdbe5SAndy Adamson 	return 0;
23611da177e4SLinus Torvalds }
23621da177e4SLinus Torvalds 
23631da177e4SLinus Torvalds /*
23641da177e4SLinus Torvalds  * a SETCLIENTID request
23651da177e4SLinus Torvalds  */
23668687b63aSAl Viro static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid *sc)
23671da177e4SLinus Torvalds {
23681da177e4SLinus Torvalds 	struct xdr_stream xdr;
23691da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2370d017931cSAndy Adamson 		.nops	= 0,
23711da177e4SLinus Torvalds 	};
23721da177e4SLinus Torvalds 
23731da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23740c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2375cf8cdbe5SAndy Adamson 	encode_setclientid(&xdr, sc, &hdr);
2376d017931cSAndy Adamson 	encode_nops(&hdr);
2377cf8cdbe5SAndy Adamson 	return 0;
23781da177e4SLinus Torvalds }
23791da177e4SLinus Torvalds 
23801da177e4SLinus Torvalds /*
23811da177e4SLinus Torvalds  * a SETCLIENTID_CONFIRM request
23821da177e4SLinus Torvalds  */
2383bb8b27e5STrond Myklebust static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid_res *arg)
23841da177e4SLinus Torvalds {
23851da177e4SLinus Torvalds 	struct xdr_stream xdr;
23861da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2387d017931cSAndy Adamson 		.nops	= 0,
23881da177e4SLinus Torvalds 	};
23891da177e4SLinus Torvalds 	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
23901da177e4SLinus Torvalds 
23911da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23920c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2393bb8b27e5STrond Myklebust 	encode_setclientid_confirm(&xdr, arg, &hdr);
2394cf8cdbe5SAndy Adamson 	encode_putrootfh(&xdr, &hdr);
2395cf8cdbe5SAndy Adamson 	encode_fsinfo(&xdr, lease_bitmap, &hdr);
2396d017931cSAndy Adamson 	encode_nops(&hdr);
2397cf8cdbe5SAndy Adamson 	return 0;
23981da177e4SLinus Torvalds }
23991da177e4SLinus Torvalds 
24001da177e4SLinus Torvalds /*
24011da177e4SLinus Torvalds  * DELEGRETURN request
24021da177e4SLinus Torvalds  */
24038687b63aSAl Viro static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
24041da177e4SLinus Torvalds {
24051da177e4SLinus Torvalds 	struct xdr_stream xdr;
24061da177e4SLinus Torvalds 	struct compound_hdr hdr = {
240766cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
24081da177e4SLinus Torvalds 	};
24091da177e4SLinus Torvalds 
24101da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
24110c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
24129b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2413cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fhandle, &hdr);
2414cf8cdbe5SAndy Adamson 	encode_delegreturn(&xdr, args->stateid, &hdr);
2415cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2416d017931cSAndy Adamson 	encode_nops(&hdr);
2417cf8cdbe5SAndy Adamson 	return 0;
24181da177e4SLinus Torvalds }
24191da177e4SLinus Torvalds 
24201da177e4SLinus Torvalds /*
2421683b57b4STrond Myklebust  * Encode FS_LOCATIONS request
2422683b57b4STrond Myklebust  */
24238687b63aSAl Viro static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
2424683b57b4STrond Myklebust {
2425683b57b4STrond Myklebust 	struct xdr_stream xdr;
2426683b57b4STrond Myklebust 	struct compound_hdr hdr = {
242766cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
2428683b57b4STrond Myklebust 	};
242928f56694SBenny Halevy 	uint32_t replen;
2430683b57b4STrond Myklebust 
2431683b57b4STrond Myklebust 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
24320c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
24339b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2434cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
2435cf8cdbe5SAndy Adamson 	encode_lookup(&xdr, args->name, &hdr);
243628f56694SBenny Halevy 	replen = hdr.replen;	/* get the attribute into args->page */
2437cf8cdbe5SAndy Adamson 	encode_fs_locations(&xdr, args->bitmask, &hdr);
2438cf8cdbe5SAndy Adamson 
243928f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
2440683b57b4STrond Myklebust 			0, PAGE_SIZE);
2441d017931cSAndy Adamson 	encode_nops(&hdr);
2442cf8cdbe5SAndy Adamson 	return 0;
2443683b57b4STrond Myklebust }
2444683b57b4STrond Myklebust 
244599fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
244699fe60d0SBenny Halevy /*
244799fe60d0SBenny Halevy  * EXCHANGE_ID request
244899fe60d0SBenny Halevy  */
244999fe60d0SBenny Halevy static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
245099fe60d0SBenny Halevy 				    struct nfs41_exchange_id_args *args)
245199fe60d0SBenny Halevy {
245299fe60d0SBenny Halevy 	struct xdr_stream xdr;
245399fe60d0SBenny Halevy 	struct compound_hdr hdr = {
2454a4432345STrond Myklebust 		.minorversion = args->client->cl_mvops->minor_version,
245599fe60d0SBenny Halevy 	};
245699fe60d0SBenny Halevy 
245799fe60d0SBenny Halevy 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
245899fe60d0SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
245999fe60d0SBenny Halevy 	encode_exchange_id(&xdr, args, &hdr);
246099fe60d0SBenny Halevy 	encode_nops(&hdr);
246199fe60d0SBenny Halevy 	return 0;
246299fe60d0SBenny Halevy }
24632050f0ccSAndy Adamson 
24642050f0ccSAndy Adamson /*
2465fc931582SAndy Adamson  * a CREATE_SESSION request
2466fc931582SAndy Adamson  */
2467fc931582SAndy Adamson static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
2468fc931582SAndy Adamson 				       struct nfs41_create_session_args *args)
2469fc931582SAndy Adamson {
2470fc931582SAndy Adamson 	struct xdr_stream xdr;
2471fc931582SAndy Adamson 	struct compound_hdr hdr = {
2472a4432345STrond Myklebust 		.minorversion = args->client->cl_mvops->minor_version,
2473fc931582SAndy Adamson 	};
2474fc931582SAndy Adamson 
2475fc931582SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2476fc931582SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
2477fc931582SAndy Adamson 	encode_create_session(&xdr, args, &hdr);
2478fc931582SAndy Adamson 	encode_nops(&hdr);
2479fc931582SAndy Adamson 	return 0;
2480fc931582SAndy Adamson }
2481fc931582SAndy Adamson 
2482fc931582SAndy Adamson /*
24830f3e66c6SAndy Adamson  * a DESTROY_SESSION request
24840f3e66c6SAndy Adamson  */
24850f3e66c6SAndy Adamson static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
24860f3e66c6SAndy Adamson 					struct nfs4_session *session)
24870f3e66c6SAndy Adamson {
24880f3e66c6SAndy Adamson 	struct xdr_stream xdr;
24890f3e66c6SAndy Adamson 	struct compound_hdr hdr = {
2490a4432345STrond Myklebust 		.minorversion = session->clp->cl_mvops->minor_version,
24910f3e66c6SAndy Adamson 	};
24920f3e66c6SAndy Adamson 
24930f3e66c6SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
24940f3e66c6SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
24950f3e66c6SAndy Adamson 	encode_destroy_session(&xdr, session, &hdr);
24960f3e66c6SAndy Adamson 	encode_nops(&hdr);
24970f3e66c6SAndy Adamson 	return 0;
24980f3e66c6SAndy Adamson }
24990f3e66c6SAndy Adamson 
25000f3e66c6SAndy Adamson /*
2501fc01cea9SAndy Adamson  * a SEQUENCE request
2502fc01cea9SAndy Adamson  */
2503fc01cea9SAndy Adamson static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
2504fc01cea9SAndy Adamson 				 struct nfs4_sequence_args *args)
2505fc01cea9SAndy Adamson {
2506fc01cea9SAndy Adamson 	struct xdr_stream xdr;
2507fc01cea9SAndy Adamson 	struct compound_hdr hdr = {
2508fc01cea9SAndy Adamson 		.minorversion = nfs4_xdr_minorversion(args),
2509fc01cea9SAndy Adamson 	};
2510fc01cea9SAndy Adamson 
2511fc01cea9SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2512fc01cea9SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
2513fc01cea9SAndy Adamson 	encode_sequence(&xdr, args, &hdr);
2514fc01cea9SAndy Adamson 	encode_nops(&hdr);
2515fc01cea9SAndy Adamson 	return 0;
2516fc01cea9SAndy Adamson }
2517fc01cea9SAndy Adamson 
2518fc01cea9SAndy Adamson /*
25192050f0ccSAndy Adamson  * a GET_LEASE_TIME request
25202050f0ccSAndy Adamson  */
25212050f0ccSAndy Adamson static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
25222050f0ccSAndy Adamson 				       struct nfs4_get_lease_time_args *args)
25232050f0ccSAndy Adamson {
25242050f0ccSAndy Adamson 	struct xdr_stream xdr;
25252050f0ccSAndy Adamson 	struct compound_hdr hdr = {
25262050f0ccSAndy Adamson 		.minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
25272050f0ccSAndy Adamson 	};
25282050f0ccSAndy Adamson 	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
25292050f0ccSAndy Adamson 
25302050f0ccSAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
25312050f0ccSAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
25322050f0ccSAndy Adamson 	encode_sequence(&xdr, &args->la_seq_args, &hdr);
25332050f0ccSAndy Adamson 	encode_putrootfh(&xdr, &hdr);
25342050f0ccSAndy Adamson 	encode_fsinfo(&xdr, lease_bitmap, &hdr);
25352050f0ccSAndy Adamson 	encode_nops(&hdr);
25362050f0ccSAndy Adamson 	return 0;
25372050f0ccSAndy Adamson }
253818019753SRicardo Labiaga 
253918019753SRicardo Labiaga /*
254018019753SRicardo Labiaga  * a RECLAIM_COMPLETE request
254118019753SRicardo Labiaga  */
254218019753SRicardo Labiaga static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p,
254318019753SRicardo Labiaga 				     struct nfs41_reclaim_complete_args *args)
254418019753SRicardo Labiaga {
254518019753SRicardo Labiaga 	struct xdr_stream xdr;
254618019753SRicardo Labiaga 	struct compound_hdr hdr = {
254718019753SRicardo Labiaga 		.minorversion = nfs4_xdr_minorversion(&args->seq_args)
254818019753SRicardo Labiaga 	};
254918019753SRicardo Labiaga 
255018019753SRicardo Labiaga 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
255118019753SRicardo Labiaga 	encode_compound_hdr(&xdr, req, &hdr);
255218019753SRicardo Labiaga 	encode_sequence(&xdr, &args->seq_args, &hdr);
255318019753SRicardo Labiaga 	encode_reclaim_complete(&xdr, args, &hdr);
255418019753SRicardo Labiaga 	encode_nops(&hdr);
255518019753SRicardo Labiaga 	return 0;
255618019753SRicardo Labiaga }
255718019753SRicardo Labiaga 
255899fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
255999fe60d0SBenny Halevy 
2560686841b3SBenny Halevy static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
2561686841b3SBenny Halevy {
2562686841b3SBenny Halevy 	dprintk("nfs: %s: prematurely hit end of receive buffer. "
2563686841b3SBenny Halevy 		"Remaining buffer length is %tu words.\n",
2564686841b3SBenny Halevy 		func, xdr->end - xdr->p);
2565686841b3SBenny Halevy }
25661da177e4SLinus Torvalds 
2567683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
25681da177e4SLinus Torvalds {
25698687b63aSAl Viro 	__be32 *p;
25701da177e4SLinus Torvalds 
2571c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2572c0eae66eSBenny Halevy 	if (unlikely(!p))
2573c0eae66eSBenny Halevy 		goto out_overflow;
2574cccddf4fSBenny Halevy 	*len = be32_to_cpup(p);
2575c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, *len);
2576c0eae66eSBenny Halevy 	if (unlikely(!p))
2577c0eae66eSBenny Halevy 		goto out_overflow;
25781da177e4SLinus Torvalds 	*string = (char *)p;
25791da177e4SLinus Torvalds 	return 0;
2580c0eae66eSBenny Halevy out_overflow:
2581c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2582c0eae66eSBenny Halevy 	return -EIO;
25831da177e4SLinus Torvalds }
25841da177e4SLinus Torvalds 
25851da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
25861da177e4SLinus Torvalds {
25878687b63aSAl Viro 	__be32 *p;
25881da177e4SLinus Torvalds 
2589c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
2590c0eae66eSBenny Halevy 	if (unlikely(!p))
2591c0eae66eSBenny Halevy 		goto out_overflow;
25926f723f77SBenny Halevy 	hdr->status = be32_to_cpup(p++);
2593cccddf4fSBenny Halevy 	hdr->taglen = be32_to_cpup(p);
25941da177e4SLinus Torvalds 
2595c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, hdr->taglen + 4);
2596c0eae66eSBenny Halevy 	if (unlikely(!p))
2597c0eae66eSBenny Halevy 		goto out_overflow;
25981da177e4SLinus Torvalds 	hdr->tag = (char *)p;
25991da177e4SLinus Torvalds 	p += XDR_QUADLEN(hdr->taglen);
2600cccddf4fSBenny Halevy 	hdr->nops = be32_to_cpup(p);
2601aadf6152SBenny Halevy 	if (unlikely(hdr->nops < 1))
2602aadf6152SBenny Halevy 		return nfs4_stat_to_errno(hdr->status);
26031da177e4SLinus Torvalds 	return 0;
2604c0eae66eSBenny Halevy out_overflow:
2605c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2606c0eae66eSBenny Halevy 	return -EIO;
26071da177e4SLinus Torvalds }
26081da177e4SLinus Torvalds 
26091da177e4SLinus Torvalds static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
26101da177e4SLinus Torvalds {
26118687b63aSAl Viro 	__be32 *p;
26121da177e4SLinus Torvalds 	uint32_t opnum;
26131da177e4SLinus Torvalds 	int32_t nfserr;
26141da177e4SLinus Torvalds 
2615c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
2616c0eae66eSBenny Halevy 	if (unlikely(!p))
2617c0eae66eSBenny Halevy 		goto out_overflow;
26186f723f77SBenny Halevy 	opnum = be32_to_cpup(p++);
26191da177e4SLinus Torvalds 	if (opnum != expected) {
2620fe82a183SChuck Lever 		dprintk("nfs: Server returned operation"
26211da177e4SLinus Torvalds 			" %d but we issued a request for %d\n",
26221da177e4SLinus Torvalds 				opnum, expected);
26231da177e4SLinus Torvalds 		return -EIO;
26241da177e4SLinus Torvalds 	}
2625cccddf4fSBenny Halevy 	nfserr = be32_to_cpup(p);
26261da177e4SLinus Torvalds 	if (nfserr != NFS_OK)
2627856dff3dSBenny Halevy 		return nfs4_stat_to_errno(nfserr);
26281da177e4SLinus Torvalds 	return 0;
2629c0eae66eSBenny Halevy out_overflow:
2630c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2631c0eae66eSBenny Halevy 	return -EIO;
26321da177e4SLinus Torvalds }
26331da177e4SLinus Torvalds 
26341da177e4SLinus Torvalds /* Dummy routine */
2635adfa6f98SDavid Howells static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
26361da177e4SLinus Torvalds {
26378687b63aSAl Viro 	__be32 *p;
2638683b57b4STrond Myklebust 	unsigned int strlen;
26391da177e4SLinus Torvalds 	char *str;
26401da177e4SLinus Torvalds 
2641c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
2642c0eae66eSBenny Halevy 	if (likely(p))
26431da177e4SLinus Torvalds 		return decode_opaque_inline(xdr, &strlen, &str);
2644c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2645c0eae66eSBenny Halevy 	return -EIO;
26461da177e4SLinus Torvalds }
26471da177e4SLinus Torvalds 
26481da177e4SLinus Torvalds static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
26491da177e4SLinus Torvalds {
26508687b63aSAl Viro 	uint32_t bmlen;
26518687b63aSAl Viro 	__be32 *p;
26521da177e4SLinus Torvalds 
2653c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2654c0eae66eSBenny Halevy 	if (unlikely(!p))
2655c0eae66eSBenny Halevy 		goto out_overflow;
2656cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
26571da177e4SLinus Torvalds 
26581da177e4SLinus Torvalds 	bitmap[0] = bitmap[1] = 0;
2659c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, (bmlen << 2));
2660c0eae66eSBenny Halevy 	if (unlikely(!p))
2661c0eae66eSBenny Halevy 		goto out_overflow;
26621da177e4SLinus Torvalds 	if (bmlen > 0) {
26636f723f77SBenny Halevy 		bitmap[0] = be32_to_cpup(p++);
26641da177e4SLinus Torvalds 		if (bmlen > 1)
2665cccddf4fSBenny Halevy 			bitmap[1] = be32_to_cpup(p);
26661da177e4SLinus Torvalds 	}
26671da177e4SLinus Torvalds 	return 0;
2668c0eae66eSBenny Halevy out_overflow:
2669c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2670c0eae66eSBenny Halevy 	return -EIO;
26711da177e4SLinus Torvalds }
26721da177e4SLinus Torvalds 
26738687b63aSAl Viro static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep)
26741da177e4SLinus Torvalds {
26758687b63aSAl Viro 	__be32 *p;
26761da177e4SLinus Torvalds 
2677c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2678c0eae66eSBenny Halevy 	if (unlikely(!p))
2679c0eae66eSBenny Halevy 		goto out_overflow;
2680cccddf4fSBenny Halevy 	*attrlen = be32_to_cpup(p);
26811da177e4SLinus Torvalds 	*savep = xdr->p;
26821da177e4SLinus Torvalds 	return 0;
2683c0eae66eSBenny Halevy out_overflow:
2684c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2685c0eae66eSBenny Halevy 	return -EIO;
26861da177e4SLinus Torvalds }
26871da177e4SLinus Torvalds 
26881da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
26891da177e4SLinus Torvalds {
26901da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
26911da177e4SLinus Torvalds 		decode_attr_bitmap(xdr, bitmask);
26921da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
26931da177e4SLinus Torvalds 	} else
26941da177e4SLinus Torvalds 		bitmask[0] = bitmask[1] = 0;
269544109241SFred Isaman 	dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
26961da177e4SLinus Torvalds 	return 0;
26971da177e4SLinus Torvalds }
26981da177e4SLinus Torvalds 
26991da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
27001da177e4SLinus Torvalds {
27018687b63aSAl Viro 	__be32 *p;
2702409924e4STrond Myklebust 	int ret = 0;
27031da177e4SLinus Torvalds 
27041da177e4SLinus Torvalds 	*type = 0;
27051da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
27061da177e4SLinus Torvalds 		return -EIO;
27071da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
2708c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2709c0eae66eSBenny Halevy 		if (unlikely(!p))
2710c0eae66eSBenny Halevy 			goto out_overflow;
2711cccddf4fSBenny Halevy 		*type = be32_to_cpup(p);
27121da177e4SLinus Torvalds 		if (*type < NF4REG || *type > NF4NAMEDATTR) {
27133110ff80SHarvey Harrison 			dprintk("%s: bad type %d\n", __func__, *type);
27141da177e4SLinus Torvalds 			return -EIO;
27151da177e4SLinus Torvalds 		}
27161da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_TYPE;
2717409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_TYPE;
27181da177e4SLinus Torvalds 	}
2719bca79478STrond Myklebust 	dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
2720409924e4STrond Myklebust 	return ret;
2721c0eae66eSBenny Halevy out_overflow:
2722c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2723c0eae66eSBenny Halevy 	return -EIO;
27241da177e4SLinus Torvalds }
27251da177e4SLinus Torvalds 
27261da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
27271da177e4SLinus Torvalds {
27288687b63aSAl Viro 	__be32 *p;
2729409924e4STrond Myklebust 	int ret = 0;
27301da177e4SLinus Torvalds 
27311da177e4SLinus Torvalds 	*change = 0;
27321da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
27331da177e4SLinus Torvalds 		return -EIO;
27341da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
2735c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2736c0eae66eSBenny Halevy 		if (unlikely(!p))
2737c0eae66eSBenny Halevy 			goto out_overflow;
2738cccddf4fSBenny Halevy 		xdr_decode_hyper(p, change);
27391da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_CHANGE;
2740409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_CHANGE;
27411da177e4SLinus Torvalds 	}
27423110ff80SHarvey Harrison 	dprintk("%s: change attribute=%Lu\n", __func__,
27431da177e4SLinus Torvalds 			(unsigned long long)*change);
2744409924e4STrond Myklebust 	return ret;
2745c0eae66eSBenny Halevy out_overflow:
2746c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2747c0eae66eSBenny Halevy 	return -EIO;
27481da177e4SLinus Torvalds }
27491da177e4SLinus Torvalds 
27501da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
27511da177e4SLinus Torvalds {
27528687b63aSAl Viro 	__be32 *p;
2753409924e4STrond Myklebust 	int ret = 0;
27541da177e4SLinus Torvalds 
27551da177e4SLinus Torvalds 	*size = 0;
27561da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
27571da177e4SLinus Torvalds 		return -EIO;
27581da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
2759c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2760c0eae66eSBenny Halevy 		if (unlikely(!p))
2761c0eae66eSBenny Halevy 			goto out_overflow;
2762cccddf4fSBenny Halevy 		xdr_decode_hyper(p, size);
27631da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SIZE;
2764409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_SIZE;
27651da177e4SLinus Torvalds 	}
27663110ff80SHarvey Harrison 	dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
2767409924e4STrond Myklebust 	return ret;
2768c0eae66eSBenny Halevy out_overflow:
2769c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2770c0eae66eSBenny Halevy 	return -EIO;
27711da177e4SLinus Torvalds }
27721da177e4SLinus Torvalds 
27731da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
27741da177e4SLinus Torvalds {
27758687b63aSAl Viro 	__be32 *p;
27761da177e4SLinus Torvalds 
27771da177e4SLinus Torvalds 	*res = 0;
27781da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
27791da177e4SLinus Torvalds 		return -EIO;
27801da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
2781c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2782c0eae66eSBenny Halevy 		if (unlikely(!p))
2783c0eae66eSBenny Halevy 			goto out_overflow;
2784cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
27851da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
27861da177e4SLinus Torvalds 	}
27873110ff80SHarvey Harrison 	dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
27881da177e4SLinus Torvalds 	return 0;
2789c0eae66eSBenny Halevy out_overflow:
2790c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2791c0eae66eSBenny Halevy 	return -EIO;
27921da177e4SLinus Torvalds }
27931da177e4SLinus Torvalds 
27941da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
27951da177e4SLinus Torvalds {
27968687b63aSAl Viro 	__be32 *p;
27971da177e4SLinus Torvalds 
27981da177e4SLinus Torvalds 	*res = 0;
27991da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
28001da177e4SLinus Torvalds 		return -EIO;
28011da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
2802c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2803c0eae66eSBenny Halevy 		if (unlikely(!p))
2804c0eae66eSBenny Halevy 			goto out_overflow;
2805cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
28061da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
28071da177e4SLinus Torvalds 	}
28083110ff80SHarvey Harrison 	dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
28091da177e4SLinus Torvalds 	return 0;
2810c0eae66eSBenny Halevy out_overflow:
2811c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2812c0eae66eSBenny Halevy 	return -EIO;
28131da177e4SLinus Torvalds }
28141da177e4SLinus Torvalds 
28158b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
28161da177e4SLinus Torvalds {
28178687b63aSAl Viro 	__be32 *p;
2818409924e4STrond Myklebust 	int ret = 0;
28191da177e4SLinus Torvalds 
28201da177e4SLinus Torvalds 	fsid->major = 0;
28211da177e4SLinus Torvalds 	fsid->minor = 0;
28221da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
28231da177e4SLinus Torvalds 		return -EIO;
28241da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
2825c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 16);
2826c0eae66eSBenny Halevy 		if (unlikely(!p))
2827c0eae66eSBenny Halevy 			goto out_overflow;
28283ceb4dbbSBenny Halevy 		p = xdr_decode_hyper(p, &fsid->major);
2829cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &fsid->minor);
28301da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FSID;
2831409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FSID;
28321da177e4SLinus Torvalds 	}
28333110ff80SHarvey Harrison 	dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
28341da177e4SLinus Torvalds 			(unsigned long long)fsid->major,
28351da177e4SLinus Torvalds 			(unsigned long long)fsid->minor);
2836409924e4STrond Myklebust 	return ret;
2837c0eae66eSBenny Halevy out_overflow:
2838c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2839c0eae66eSBenny Halevy 	return -EIO;
28401da177e4SLinus Torvalds }
28411da177e4SLinus Torvalds 
28421da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
28431da177e4SLinus Torvalds {
28448687b63aSAl Viro 	__be32 *p;
28451da177e4SLinus Torvalds 
28461da177e4SLinus Torvalds 	*res = 60;
28471da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
28481da177e4SLinus Torvalds 		return -EIO;
28491da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
2850c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2851c0eae66eSBenny Halevy 		if (unlikely(!p))
2852c0eae66eSBenny Halevy 			goto out_overflow;
2853cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
28541da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
28551da177e4SLinus Torvalds 	}
28563110ff80SHarvey Harrison 	dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
28571da177e4SLinus Torvalds 	return 0;
2858c0eae66eSBenny Halevy out_overflow:
2859c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2860c0eae66eSBenny Halevy 	return -EIO;
28611da177e4SLinus Torvalds }
28621da177e4SLinus Torvalds 
2863ae42c70aSBryan Schumaker static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap)
2864ae42c70aSBryan Schumaker {
2865ae42c70aSBryan Schumaker 	__be32 *p;
2866ae42c70aSBryan Schumaker 
2867ae42c70aSBryan Schumaker 	if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
2868ae42c70aSBryan Schumaker 		return -EIO;
2869ae42c70aSBryan Schumaker 	if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
2870ae42c70aSBryan Schumaker 		p = xdr_inline_decode(xdr, 4);
2871ae42c70aSBryan Schumaker 		if (unlikely(!p))
2872ae42c70aSBryan Schumaker 			goto out_overflow;
2873ae42c70aSBryan Schumaker 		bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
2874ae42c70aSBryan Schumaker 	}
2875ae42c70aSBryan Schumaker 	return 0;
2876ae42c70aSBryan Schumaker out_overflow:
2877ae42c70aSBryan Schumaker 	print_overflow_msg(__func__, xdr);
2878ae42c70aSBryan Schumaker 	return -EIO;
2879ae42c70aSBryan Schumaker }
2880ae42c70aSBryan Schumaker 
2881ae42c70aSBryan Schumaker static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
2882ae42c70aSBryan Schumaker {
2883ae42c70aSBryan Schumaker 	__be32 *p;
2884ae42c70aSBryan Schumaker 	int len;
2885ae42c70aSBryan Schumaker 
28867ad07353STrond Myklebust 	if (fh != NULL)
2887ae42c70aSBryan Schumaker 		memset(fh, 0, sizeof(*fh));
2888ae42c70aSBryan Schumaker 
2889ae42c70aSBryan Schumaker 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
2890ae42c70aSBryan Schumaker 		return -EIO;
2891ae42c70aSBryan Schumaker 	if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
2892ae42c70aSBryan Schumaker 		p = xdr_inline_decode(xdr, 4);
2893ae42c70aSBryan Schumaker 		if (unlikely(!p))
2894ae42c70aSBryan Schumaker 			goto out_overflow;
2895ae42c70aSBryan Schumaker 		len = be32_to_cpup(p);
2896ae42c70aSBryan Schumaker 		if (len > NFS4_FHSIZE)
2897ae42c70aSBryan Schumaker 			return -EIO;
2898ae42c70aSBryan Schumaker 		p = xdr_inline_decode(xdr, len);
2899ae42c70aSBryan Schumaker 		if (unlikely(!p))
2900ae42c70aSBryan Schumaker 			goto out_overflow;
29017ad07353STrond Myklebust 		if (fh != NULL) {
2902ae42c70aSBryan Schumaker 			memcpy(fh->data, p, len);
29037ad07353STrond Myklebust 			fh->size = len;
29047ad07353STrond Myklebust 		}
2905ae42c70aSBryan Schumaker 		bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
2906ae42c70aSBryan Schumaker 	}
2907ae42c70aSBryan Schumaker 	return 0;
2908ae42c70aSBryan Schumaker out_overflow:
2909ae42c70aSBryan Schumaker 	print_overflow_msg(__func__, xdr);
2910ae42c70aSBryan Schumaker 	return -EIO;
2911ae42c70aSBryan Schumaker }
2912ae42c70aSBryan Schumaker 
29131da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
29141da177e4SLinus Torvalds {
29158687b63aSAl Viro 	__be32 *p;
29161da177e4SLinus Torvalds 
29171da177e4SLinus Torvalds 	*res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
29181da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
29191da177e4SLinus Torvalds 		return -EIO;
29201da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
2921c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2922c0eae66eSBenny Halevy 		if (unlikely(!p))
2923c0eae66eSBenny Halevy 			goto out_overflow;
2924cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
29251da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
29261da177e4SLinus Torvalds 	}
29273110ff80SHarvey Harrison 	dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
29281da177e4SLinus Torvalds 	return 0;
2929c0eae66eSBenny Halevy out_overflow:
2930c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2931c0eae66eSBenny Halevy 	return -EIO;
29321da177e4SLinus Torvalds }
29331da177e4SLinus Torvalds 
29341da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
29351da177e4SLinus Torvalds {
29368687b63aSAl Viro 	__be32 *p;
2937409924e4STrond Myklebust 	int ret = 0;
29381da177e4SLinus Torvalds 
29391da177e4SLinus Torvalds 	*fileid = 0;
29401da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
29411da177e4SLinus Torvalds 		return -EIO;
29421da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
2943c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2944c0eae66eSBenny Halevy 		if (unlikely(!p))
2945c0eae66eSBenny Halevy 			goto out_overflow;
2946cccddf4fSBenny Halevy 		xdr_decode_hyper(p, fileid);
29471da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILEID;
2948409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FILEID;
29491da177e4SLinus Torvalds 	}
29503110ff80SHarvey Harrison 	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
2951409924e4STrond Myklebust 	return ret;
2952c0eae66eSBenny Halevy out_overflow:
2953c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2954c0eae66eSBenny Halevy 	return -EIO;
29551da177e4SLinus Torvalds }
29561da177e4SLinus Torvalds 
295799baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
295899baf625SManoj Naik {
29598687b63aSAl Viro 	__be32 *p;
2960409924e4STrond Myklebust 	int ret = 0;
296199baf625SManoj Naik 
296299baf625SManoj Naik 	*fileid = 0;
296399baf625SManoj Naik 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
296499baf625SManoj Naik 		return -EIO;
296599baf625SManoj Naik 	if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
2966c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2967c0eae66eSBenny Halevy 		if (unlikely(!p))
2968c0eae66eSBenny Halevy 			goto out_overflow;
2969cccddf4fSBenny Halevy 		xdr_decode_hyper(p, fileid);
297099baf625SManoj Naik 		bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
2971409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FILEID;
297299baf625SManoj Naik 	}
29733110ff80SHarvey Harrison 	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
2974409924e4STrond Myklebust 	return ret;
2975c0eae66eSBenny Halevy out_overflow:
2976c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2977c0eae66eSBenny Halevy 	return -EIO;
297899baf625SManoj Naik }
297999baf625SManoj Naik 
29801da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
29811da177e4SLinus Torvalds {
29828687b63aSAl Viro 	__be32 *p;
29831da177e4SLinus Torvalds 	int status = 0;
29841da177e4SLinus Torvalds 
29851da177e4SLinus Torvalds 	*res = 0;
29861da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
29871da177e4SLinus Torvalds 		return -EIO;
29881da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
2989c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2990c0eae66eSBenny Halevy 		if (unlikely(!p))
2991c0eae66eSBenny Halevy 			goto out_overflow;
2992cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
29931da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
29941da177e4SLinus Torvalds 	}
29953110ff80SHarvey Harrison 	dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
29961da177e4SLinus Torvalds 	return status;
2997c0eae66eSBenny Halevy out_overflow:
2998c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2999c0eae66eSBenny Halevy 	return -EIO;
30001da177e4SLinus Torvalds }
30011da177e4SLinus Torvalds 
30021da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
30031da177e4SLinus Torvalds {
30048687b63aSAl Viro 	__be32 *p;
30051da177e4SLinus Torvalds 	int status = 0;
30061da177e4SLinus Torvalds 
30071da177e4SLinus Torvalds 	*res = 0;
30081da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
30091da177e4SLinus Torvalds 		return -EIO;
30101da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
3011c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3012c0eae66eSBenny Halevy 		if (unlikely(!p))
3013c0eae66eSBenny Halevy 			goto out_overflow;
3014cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
30151da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
30161da177e4SLinus Torvalds 	}
30173110ff80SHarvey Harrison 	dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
30181da177e4SLinus Torvalds 	return status;
3019c0eae66eSBenny Halevy out_overflow:
3020c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3021c0eae66eSBenny Halevy 	return -EIO;
30221da177e4SLinus Torvalds }
30231da177e4SLinus Torvalds 
30241da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
30251da177e4SLinus Torvalds {
30268687b63aSAl Viro 	__be32 *p;
30271da177e4SLinus Torvalds 	int status = 0;
30281da177e4SLinus Torvalds 
30291da177e4SLinus Torvalds 	*res = 0;
30301da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
30311da177e4SLinus Torvalds 		return -EIO;
30321da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
3033c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3034c0eae66eSBenny Halevy 		if (unlikely(!p))
3035c0eae66eSBenny Halevy 			goto out_overflow;
3036cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
30371da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
30381da177e4SLinus Torvalds 	}
30393110ff80SHarvey Harrison 	dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
30401da177e4SLinus Torvalds 	return status;
3041c0eae66eSBenny Halevy out_overflow:
3042c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3043c0eae66eSBenny Halevy 	return -EIO;
30441da177e4SLinus Torvalds }
30451da177e4SLinus Torvalds 
30467aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
30477aaa0b3bSManoj Naik {
3048464ad6b1SChuck Lever 	u32 n;
30498687b63aSAl Viro 	__be32 *p;
30507aaa0b3bSManoj Naik 	int status = 0;
30517aaa0b3bSManoj Naik 
3052c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3053c0eae66eSBenny Halevy 	if (unlikely(!p))
3054c0eae66eSBenny Halevy 		goto out_overflow;
3055cccddf4fSBenny Halevy 	n = be32_to_cpup(p);
305633a43f28SAndy Adamson 	if (n == 0)
305733a43f28SAndy Adamson 		goto root_path;
30587aaa0b3bSManoj Naik 	dprintk("path ");
30597aaa0b3bSManoj Naik 	path->ncomponents = 0;
30607aaa0b3bSManoj Naik 	while (path->ncomponents < n) {
30617aaa0b3bSManoj Naik 		struct nfs4_string *component = &path->components[path->ncomponents];
30627aaa0b3bSManoj Naik 		status = decode_opaque_inline(xdr, &component->len, &component->data);
30637aaa0b3bSManoj Naik 		if (unlikely(status != 0))
30647aaa0b3bSManoj Naik 			goto out_eio;
30657aaa0b3bSManoj Naik 		if (path->ncomponents != n)
30667aaa0b3bSManoj Naik 			dprintk("/");
30677aaa0b3bSManoj Naik 		dprintk("%s", component->data);
30687aaa0b3bSManoj Naik 		if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
30697aaa0b3bSManoj Naik 			path->ncomponents++;
30707aaa0b3bSManoj Naik 		else {
30717aaa0b3bSManoj Naik 			dprintk("cannot parse %d components in path\n", n);
30727aaa0b3bSManoj Naik 			goto out_eio;
30737aaa0b3bSManoj Naik 		}
30747aaa0b3bSManoj Naik 	}
30757aaa0b3bSManoj Naik out:
30767aaa0b3bSManoj Naik 	dprintk("\n");
30777aaa0b3bSManoj Naik 	return status;
307833a43f28SAndy Adamson root_path:
307933a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */
308033a43f28SAndy Adamson 	path->ncomponents = 1;
308133a43f28SAndy Adamson 	path->components[0].len=0;
308233a43f28SAndy Adamson 	path->components[0].data=NULL;
308333a43f28SAndy Adamson 	dprintk("path /\n");
308433a43f28SAndy Adamson 	goto out;
30857aaa0b3bSManoj Naik out_eio:
30867aaa0b3bSManoj Naik 	dprintk(" status %d", status);
30877aaa0b3bSManoj Naik 	status = -EIO;
30887aaa0b3bSManoj Naik 	goto out;
3089c0eae66eSBenny Halevy out_overflow:
3090c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3091c0eae66eSBenny Halevy 	return -EIO;
30927aaa0b3bSManoj Naik }
30937aaa0b3bSManoj Naik 
30947aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
3095683b57b4STrond Myklebust {
3096683b57b4STrond Myklebust 	int n;
30978687b63aSAl Viro 	__be32 *p;
3098683b57b4STrond Myklebust 	int status = -EIO;
3099683b57b4STrond Myklebust 
3100683b57b4STrond Myklebust 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
3101683b57b4STrond Myklebust 		goto out;
3102683b57b4STrond Myklebust 	status = 0;
3103683b57b4STrond Myklebust 	if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
3104683b57b4STrond Myklebust 		goto out;
31053110ff80SHarvey Harrison 	dprintk("%s: fsroot ", __func__);
31067aaa0b3bSManoj Naik 	status = decode_pathname(xdr, &res->fs_path);
3107683b57b4STrond Myklebust 	if (unlikely(status != 0))
3108683b57b4STrond Myklebust 		goto out;
3109c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3110c0eae66eSBenny Halevy 	if (unlikely(!p))
3111c0eae66eSBenny Halevy 		goto out_overflow;
3112cccddf4fSBenny Halevy 	n = be32_to_cpup(p);
3113683b57b4STrond Myklebust 	if (n <= 0)
3114683b57b4STrond Myklebust 		goto out_eio;
3115683b57b4STrond Myklebust 	res->nlocations = 0;
3116683b57b4STrond Myklebust 	while (res->nlocations < n) {
3117464ad6b1SChuck Lever 		u32 m;
31187aaa0b3bSManoj Naik 		struct nfs4_fs_location *loc = &res->locations[res->nlocations];
3119683b57b4STrond Myklebust 
3120c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3121c0eae66eSBenny Halevy 		if (unlikely(!p))
3122c0eae66eSBenny Halevy 			goto out_overflow;
3123cccddf4fSBenny Halevy 		m = be32_to_cpup(p);
31247aaa0b3bSManoj Naik 
31257aaa0b3bSManoj Naik 		loc->nservers = 0;
31263110ff80SHarvey Harrison 		dprintk("%s: servers ", __func__);
31277aaa0b3bSManoj Naik 		while (loc->nservers < m) {
31287aaa0b3bSManoj Naik 			struct nfs4_string *server = &loc->servers[loc->nservers];
31297aaa0b3bSManoj Naik 			status = decode_opaque_inline(xdr, &server->len, &server->data);
3130683b57b4STrond Myklebust 			if (unlikely(status != 0))
3131683b57b4STrond Myklebust 				goto out_eio;
31327aaa0b3bSManoj Naik 			dprintk("%s ", server->data);
31337aaa0b3bSManoj Naik 			if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
31347aaa0b3bSManoj Naik 				loc->nservers++;
31357aaa0b3bSManoj Naik 			else {
3136464ad6b1SChuck Lever 				unsigned int i;
3137464ad6b1SChuck Lever 				dprintk("%s: using first %u of %u servers "
3138464ad6b1SChuck Lever 					"returned for location %u\n",
31393110ff80SHarvey Harrison 						__func__,
3140464ad6b1SChuck Lever 						NFS4_FS_LOCATION_MAXSERVERS,
3141464ad6b1SChuck Lever 						m, res->nlocations);
31427aaa0b3bSManoj Naik 				for (i = loc->nservers; i < m; i++) {
31432e42c3e2STrond Myklebust 					unsigned int len;
31447aaa0b3bSManoj Naik 					char *data;
31457aaa0b3bSManoj Naik 					status = decode_opaque_inline(xdr, &len, &data);
3146683b57b4STrond Myklebust 					if (unlikely(status != 0))
3147683b57b4STrond Myklebust 						goto out_eio;
31487aaa0b3bSManoj Naik 				}
31497aaa0b3bSManoj Naik 			}
31507aaa0b3bSManoj Naik 		}
31517aaa0b3bSManoj Naik 		status = decode_pathname(xdr, &loc->rootpath);
31527aaa0b3bSManoj Naik 		if (unlikely(status != 0))
31537aaa0b3bSManoj Naik 			goto out_eio;
31547aaa0b3bSManoj Naik 		if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
3155683b57b4STrond Myklebust 			res->nlocations++;
3156683b57b4STrond Myklebust 	}
3157409924e4STrond Myklebust 	if (res->nlocations != 0)
3158409924e4STrond Myklebust 		status = NFS_ATTR_FATTR_V4_REFERRAL;
3159683b57b4STrond Myklebust out:
31603110ff80SHarvey Harrison 	dprintk("%s: fs_locations done, error = %d\n", __func__, status);
3161683b57b4STrond Myklebust 	return status;
3162c0eae66eSBenny Halevy out_overflow:
3163c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3164683b57b4STrond Myklebust out_eio:
3165683b57b4STrond Myklebust 	status = -EIO;
3166683b57b4STrond Myklebust 	goto out;
3167683b57b4STrond Myklebust }
3168683b57b4STrond Myklebust 
31691da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
31701da177e4SLinus Torvalds {
31718687b63aSAl Viro 	__be32 *p;
31721da177e4SLinus Torvalds 	int status = 0;
31731da177e4SLinus Torvalds 
31741da177e4SLinus Torvalds 	*res = 0;
31751da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
31761da177e4SLinus Torvalds 		return -EIO;
31771da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
3178c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3179c0eae66eSBenny Halevy 		if (unlikely(!p))
3180c0eae66eSBenny Halevy 			goto out_overflow;
3181cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
31821da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
31831da177e4SLinus Torvalds 	}
31843110ff80SHarvey Harrison 	dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
31851da177e4SLinus Torvalds 	return status;
3186c0eae66eSBenny Halevy out_overflow:
3187c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3188c0eae66eSBenny Halevy 	return -EIO;
31891da177e4SLinus Torvalds }
31901da177e4SLinus Torvalds 
31911da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
31921da177e4SLinus Torvalds {
31938687b63aSAl Viro 	__be32 *p;
31941da177e4SLinus Torvalds 	int status = 0;
31951da177e4SLinus Torvalds 
31961da177e4SLinus Torvalds 	*maxlink = 1;
31971da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
31981da177e4SLinus Torvalds 		return -EIO;
31991da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
3200c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3201c0eae66eSBenny Halevy 		if (unlikely(!p))
3202c0eae66eSBenny Halevy 			goto out_overflow;
3203cccddf4fSBenny Halevy 		*maxlink = be32_to_cpup(p);
32041da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
32051da177e4SLinus Torvalds 	}
32063110ff80SHarvey Harrison 	dprintk("%s: maxlink=%u\n", __func__, *maxlink);
32071da177e4SLinus Torvalds 	return status;
3208c0eae66eSBenny Halevy out_overflow:
3209c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3210c0eae66eSBenny Halevy 	return -EIO;
32111da177e4SLinus Torvalds }
32121da177e4SLinus Torvalds 
32131da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
32141da177e4SLinus Torvalds {
32158687b63aSAl Viro 	__be32 *p;
32161da177e4SLinus Torvalds 	int status = 0;
32171da177e4SLinus Torvalds 
32181da177e4SLinus Torvalds 	*maxname = 1024;
32191da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
32201da177e4SLinus Torvalds 		return -EIO;
32211da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
3222c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3223c0eae66eSBenny Halevy 		if (unlikely(!p))
3224c0eae66eSBenny Halevy 			goto out_overflow;
3225cccddf4fSBenny Halevy 		*maxname = be32_to_cpup(p);
32261da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
32271da177e4SLinus Torvalds 	}
32283110ff80SHarvey Harrison 	dprintk("%s: maxname=%u\n", __func__, *maxname);
32291da177e4SLinus Torvalds 	return status;
3230c0eae66eSBenny Halevy out_overflow:
3231c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3232c0eae66eSBenny Halevy 	return -EIO;
32331da177e4SLinus Torvalds }
32341da177e4SLinus Torvalds 
32351da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
32361da177e4SLinus Torvalds {
32378687b63aSAl Viro 	__be32 *p;
32381da177e4SLinus Torvalds 	int status = 0;
32391da177e4SLinus Torvalds 
32401da177e4SLinus Torvalds 	*res = 1024;
32411da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
32421da177e4SLinus Torvalds 		return -EIO;
32431da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
32441da177e4SLinus Torvalds 		uint64_t maxread;
3245c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3246c0eae66eSBenny Halevy 		if (unlikely(!p))
3247c0eae66eSBenny Halevy 			goto out_overflow;
3248cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &maxread);
32491da177e4SLinus Torvalds 		if (maxread > 0x7FFFFFFF)
32501da177e4SLinus Torvalds 			maxread = 0x7FFFFFFF;
32511da177e4SLinus Torvalds 		*res = (uint32_t)maxread;
32521da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
32531da177e4SLinus Torvalds 	}
32543110ff80SHarvey Harrison 	dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
32551da177e4SLinus Torvalds 	return status;
3256c0eae66eSBenny Halevy out_overflow:
3257c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3258c0eae66eSBenny Halevy 	return -EIO;
32591da177e4SLinus Torvalds }
32601da177e4SLinus Torvalds 
32611da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
32621da177e4SLinus Torvalds {
32638687b63aSAl Viro 	__be32 *p;
32641da177e4SLinus Torvalds 	int status = 0;
32651da177e4SLinus Torvalds 
32661da177e4SLinus Torvalds 	*res = 1024;
32671da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
32681da177e4SLinus Torvalds 		return -EIO;
32691da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
32701da177e4SLinus Torvalds 		uint64_t maxwrite;
3271c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3272c0eae66eSBenny Halevy 		if (unlikely(!p))
3273c0eae66eSBenny Halevy 			goto out_overflow;
3274cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &maxwrite);
32751da177e4SLinus Torvalds 		if (maxwrite > 0x7FFFFFFF)
32761da177e4SLinus Torvalds 			maxwrite = 0x7FFFFFFF;
32771da177e4SLinus Torvalds 		*res = (uint32_t)maxwrite;
32781da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
32791da177e4SLinus Torvalds 	}
32803110ff80SHarvey Harrison 	dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
32811da177e4SLinus Torvalds 	return status;
3282c0eae66eSBenny Halevy out_overflow:
3283c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3284c0eae66eSBenny Halevy 	return -EIO;
32851da177e4SLinus Torvalds }
32861da177e4SLinus Torvalds 
3287bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
32881da177e4SLinus Torvalds {
3289bca79478STrond Myklebust 	uint32_t tmp;
32908687b63aSAl Viro 	__be32 *p;
3291409924e4STrond Myklebust 	int ret = 0;
32921da177e4SLinus Torvalds 
32931da177e4SLinus Torvalds 	*mode = 0;
32941da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
32951da177e4SLinus Torvalds 		return -EIO;
32961da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
3297c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3298c0eae66eSBenny Halevy 		if (unlikely(!p))
3299c0eae66eSBenny Halevy 			goto out_overflow;
3300cccddf4fSBenny Halevy 		tmp = be32_to_cpup(p);
3301bca79478STrond Myklebust 		*mode = tmp & ~S_IFMT;
33021da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_MODE;
3303409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_MODE;
33041da177e4SLinus Torvalds 	}
33053110ff80SHarvey Harrison 	dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
3306409924e4STrond Myklebust 	return ret;
3307c0eae66eSBenny Halevy out_overflow:
3308c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3309c0eae66eSBenny Halevy 	return -EIO;
33101da177e4SLinus Torvalds }
33111da177e4SLinus Torvalds 
33121da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
33131da177e4SLinus Torvalds {
33148687b63aSAl Viro 	__be32 *p;
3315409924e4STrond Myklebust 	int ret = 0;
33161da177e4SLinus Torvalds 
33171da177e4SLinus Torvalds 	*nlink = 1;
33181da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
33191da177e4SLinus Torvalds 		return -EIO;
33201da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
3321c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3322c0eae66eSBenny Halevy 		if (unlikely(!p))
3323c0eae66eSBenny Halevy 			goto out_overflow;
3324cccddf4fSBenny Halevy 		*nlink = be32_to_cpup(p);
33251da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
3326409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_NLINK;
33271da177e4SLinus Torvalds 	}
33283110ff80SHarvey Harrison 	dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
3329409924e4STrond Myklebust 	return ret;
3330c0eae66eSBenny Halevy out_overflow:
3331c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3332c0eae66eSBenny Halevy 	return -EIO;
33331da177e4SLinus Torvalds }
33341da177e4SLinus Torvalds 
333580e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
333680e52aceSTrond Myklebust 		struct nfs_client *clp, uint32_t *uid, int may_sleep)
33371da177e4SLinus Torvalds {
33388687b63aSAl Viro 	uint32_t len;
33398687b63aSAl Viro 	__be32 *p;
3340409924e4STrond Myklebust 	int ret = 0;
33411da177e4SLinus Torvalds 
33421da177e4SLinus Torvalds 	*uid = -2;
33431da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
33441da177e4SLinus Torvalds 		return -EIO;
33451da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
3346c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3347c0eae66eSBenny Halevy 		if (unlikely(!p))
3348c0eae66eSBenny Halevy 			goto out_overflow;
3349cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
3350c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
3351c0eae66eSBenny Halevy 		if (unlikely(!p))
3352c0eae66eSBenny Halevy 			goto out_overflow;
335380e52aceSTrond Myklebust 		if (!may_sleep) {
335480e52aceSTrond Myklebust 			/* do nothing */
335580e52aceSTrond Myklebust 		} else if (len < XDR_MAX_NETOBJ) {
3356409924e4STrond Myklebust 			if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0)
3357409924e4STrond Myklebust 				ret = NFS_ATTR_FATTR_OWNER;
3358409924e4STrond Myklebust 			else
33591da177e4SLinus Torvalds 				dprintk("%s: nfs_map_name_to_uid failed!\n",
33603110ff80SHarvey Harrison 						__func__);
33611da177e4SLinus Torvalds 		} else
3362fe82a183SChuck Lever 			dprintk("%s: name too long (%u)!\n",
33633110ff80SHarvey Harrison 					__func__, len);
33641da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_OWNER;
33651da177e4SLinus Torvalds 	}
33663110ff80SHarvey Harrison 	dprintk("%s: uid=%d\n", __func__, (int)*uid);
3367409924e4STrond Myklebust 	return ret;
3368c0eae66eSBenny Halevy out_overflow:
3369c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3370c0eae66eSBenny Halevy 	return -EIO;
33711da177e4SLinus Torvalds }
33721da177e4SLinus Torvalds 
337380e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
337480e52aceSTrond Myklebust 		struct nfs_client *clp, uint32_t *gid, int may_sleep)
33751da177e4SLinus Torvalds {
33768687b63aSAl Viro 	uint32_t len;
33778687b63aSAl Viro 	__be32 *p;
3378409924e4STrond Myklebust 	int ret = 0;
33791da177e4SLinus Torvalds 
33801da177e4SLinus Torvalds 	*gid = -2;
33811da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
33821da177e4SLinus Torvalds 		return -EIO;
33831da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
3384c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3385c0eae66eSBenny Halevy 		if (unlikely(!p))
3386c0eae66eSBenny Halevy 			goto out_overflow;
3387cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
3388c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
3389c0eae66eSBenny Halevy 		if (unlikely(!p))
3390c0eae66eSBenny Halevy 			goto out_overflow;
339180e52aceSTrond Myklebust 		if (!may_sleep) {
339280e52aceSTrond Myklebust 			/* do nothing */
339380e52aceSTrond Myklebust 		} else if (len < XDR_MAX_NETOBJ) {
3394409924e4STrond Myklebust 			if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0)
3395409924e4STrond Myklebust 				ret = NFS_ATTR_FATTR_GROUP;
3396409924e4STrond Myklebust 			else
33971da177e4SLinus Torvalds 				dprintk("%s: nfs_map_group_to_gid failed!\n",
33983110ff80SHarvey Harrison 						__func__);
33991da177e4SLinus Torvalds 		} else
3400fe82a183SChuck Lever 			dprintk("%s: name too long (%u)!\n",
34013110ff80SHarvey Harrison 					__func__, len);
34021da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
34031da177e4SLinus Torvalds 	}
34043110ff80SHarvey Harrison 	dprintk("%s: gid=%d\n", __func__, (int)*gid);
3405409924e4STrond Myklebust 	return ret;
3406c0eae66eSBenny Halevy out_overflow:
3407c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3408c0eae66eSBenny Halevy 	return -EIO;
34091da177e4SLinus Torvalds }
34101da177e4SLinus Torvalds 
34111da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
34121da177e4SLinus Torvalds {
34138687b63aSAl Viro 	uint32_t major = 0, minor = 0;
34148687b63aSAl Viro 	__be32 *p;
3415409924e4STrond Myklebust 	int ret = 0;
34161da177e4SLinus Torvalds 
34171da177e4SLinus Torvalds 	*rdev = MKDEV(0,0);
34181da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
34191da177e4SLinus Torvalds 		return -EIO;
34201da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
34211da177e4SLinus Torvalds 		dev_t tmp;
34221da177e4SLinus Torvalds 
3423c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3424c0eae66eSBenny Halevy 		if (unlikely(!p))
3425c0eae66eSBenny Halevy 			goto out_overflow;
34266f723f77SBenny Halevy 		major = be32_to_cpup(p++);
3427cccddf4fSBenny Halevy 		minor = be32_to_cpup(p);
34281da177e4SLinus Torvalds 		tmp = MKDEV(major, minor);
34291da177e4SLinus Torvalds 		if (MAJOR(tmp) == major && MINOR(tmp) == minor)
34301da177e4SLinus Torvalds 			*rdev = tmp;
34311da177e4SLinus Torvalds 		bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
3432409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_RDEV;
34331da177e4SLinus Torvalds 	}
34343110ff80SHarvey Harrison 	dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
3435409924e4STrond Myklebust 	return ret;
3436c0eae66eSBenny Halevy out_overflow:
3437c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3438c0eae66eSBenny Halevy 	return -EIO;
34391da177e4SLinus Torvalds }
34401da177e4SLinus Torvalds 
34411da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
34421da177e4SLinus Torvalds {
34438687b63aSAl Viro 	__be32 *p;
34441da177e4SLinus Torvalds 	int status = 0;
34451da177e4SLinus Torvalds 
34461da177e4SLinus Torvalds 	*res = 0;
34471da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
34481da177e4SLinus Torvalds 		return -EIO;
34491da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
3450c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3451c0eae66eSBenny Halevy 		if (unlikely(!p))
3452c0eae66eSBenny Halevy 			goto out_overflow;
3453cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
34541da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
34551da177e4SLinus Torvalds 	}
34563110ff80SHarvey Harrison 	dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
34571da177e4SLinus Torvalds 	return status;
3458c0eae66eSBenny Halevy out_overflow:
3459c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3460c0eae66eSBenny Halevy 	return -EIO;
34611da177e4SLinus Torvalds }
34621da177e4SLinus Torvalds 
34631da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
34641da177e4SLinus Torvalds {
34658687b63aSAl Viro 	__be32 *p;
34661da177e4SLinus Torvalds 	int status = 0;
34671da177e4SLinus Torvalds 
34681da177e4SLinus Torvalds 	*res = 0;
34691da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
34701da177e4SLinus Torvalds 		return -EIO;
34711da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
3472c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3473c0eae66eSBenny Halevy 		if (unlikely(!p))
3474c0eae66eSBenny Halevy 			goto out_overflow;
3475cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
34761da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
34771da177e4SLinus Torvalds 	}
34783110ff80SHarvey Harrison 	dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
34791da177e4SLinus Torvalds 	return status;
3480c0eae66eSBenny Halevy out_overflow:
3481c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3482c0eae66eSBenny Halevy 	return -EIO;
34831da177e4SLinus Torvalds }
34841da177e4SLinus Torvalds 
34851da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
34861da177e4SLinus Torvalds {
34878687b63aSAl Viro 	__be32 *p;
34881da177e4SLinus Torvalds 	int status = 0;
34891da177e4SLinus Torvalds 
34901da177e4SLinus Torvalds 	*res = 0;
34911da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
34921da177e4SLinus Torvalds 		return -EIO;
34931da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
3494c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3495c0eae66eSBenny Halevy 		if (unlikely(!p))
3496c0eae66eSBenny Halevy 			goto out_overflow;
3497cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
34981da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
34991da177e4SLinus Torvalds 	}
35003110ff80SHarvey Harrison 	dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
35011da177e4SLinus Torvalds 	return status;
3502c0eae66eSBenny Halevy out_overflow:
3503c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3504c0eae66eSBenny Halevy 	return -EIO;
35051da177e4SLinus Torvalds }
35061da177e4SLinus Torvalds 
35071da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
35081da177e4SLinus Torvalds {
35098687b63aSAl Viro 	__be32 *p;
3510409924e4STrond Myklebust 	int ret = 0;
35111da177e4SLinus Torvalds 
35121da177e4SLinus Torvalds 	*used = 0;
35131da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
35141da177e4SLinus Torvalds 		return -EIO;
35151da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
3516c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3517c0eae66eSBenny Halevy 		if (unlikely(!p))
3518c0eae66eSBenny Halevy 			goto out_overflow;
3519cccddf4fSBenny Halevy 		xdr_decode_hyper(p, used);
35201da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
3521409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_SPACE_USED;
35221da177e4SLinus Torvalds 	}
35233110ff80SHarvey Harrison 	dprintk("%s: space used=%Lu\n", __func__,
35241da177e4SLinus Torvalds 			(unsigned long long)*used);
3525409924e4STrond Myklebust 	return ret;
3526c0eae66eSBenny Halevy out_overflow:
3527c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3528c0eae66eSBenny Halevy 	return -EIO;
35291da177e4SLinus Torvalds }
35301da177e4SLinus Torvalds 
35311da177e4SLinus Torvalds static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
35321da177e4SLinus Torvalds {
35338687b63aSAl Viro 	__be32 *p;
35341da177e4SLinus Torvalds 	uint64_t sec;
35351da177e4SLinus Torvalds 	uint32_t nsec;
35361da177e4SLinus Torvalds 
3537c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
3538c0eae66eSBenny Halevy 	if (unlikely(!p))
3539c0eae66eSBenny Halevy 		goto out_overflow;
35403ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &sec);
3541cccddf4fSBenny Halevy 	nsec = be32_to_cpup(p);
35421da177e4SLinus Torvalds 	time->tv_sec = (time_t)sec;
35431da177e4SLinus Torvalds 	time->tv_nsec = (long)nsec;
35441da177e4SLinus Torvalds 	return 0;
3545c0eae66eSBenny Halevy out_overflow:
3546c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3547c0eae66eSBenny Halevy 	return -EIO;
35481da177e4SLinus Torvalds }
35491da177e4SLinus Torvalds 
35501da177e4SLinus Torvalds static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
35511da177e4SLinus Torvalds {
35521da177e4SLinus Torvalds 	int status = 0;
35531da177e4SLinus Torvalds 
35541da177e4SLinus Torvalds 	time->tv_sec = 0;
35551da177e4SLinus Torvalds 	time->tv_nsec = 0;
35561da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
35571da177e4SLinus Torvalds 		return -EIO;
35581da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
35591da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3560409924e4STrond Myklebust 		if (status == 0)
3561409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_ATIME;
35621da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
35631da177e4SLinus Torvalds 	}
35643110ff80SHarvey Harrison 	dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec);
35651da177e4SLinus Torvalds 	return status;
35661da177e4SLinus Torvalds }
35671da177e4SLinus Torvalds 
35681da177e4SLinus Torvalds static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
35691da177e4SLinus Torvalds {
35701da177e4SLinus Torvalds 	int status = 0;
35711da177e4SLinus Torvalds 
35721da177e4SLinus Torvalds 	time->tv_sec = 0;
35731da177e4SLinus Torvalds 	time->tv_nsec = 0;
35741da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
35751da177e4SLinus Torvalds 		return -EIO;
35761da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
35771da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3578409924e4STrond Myklebust 		if (status == 0)
3579409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_CTIME;
35801da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
35811da177e4SLinus Torvalds 	}
35823110ff80SHarvey Harrison 	dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec);
35831da177e4SLinus Torvalds 	return status;
35841da177e4SLinus Torvalds }
35851da177e4SLinus Torvalds 
35861da177e4SLinus Torvalds static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
35871da177e4SLinus Torvalds {
35881da177e4SLinus Torvalds 	int status = 0;
35891da177e4SLinus Torvalds 
35901da177e4SLinus Torvalds 	time->tv_sec = 0;
35911da177e4SLinus Torvalds 	time->tv_nsec = 0;
35921da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
35931da177e4SLinus Torvalds 		return -EIO;
35941da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
35951da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3596409924e4STrond Myklebust 		if (status == 0)
3597409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_MTIME;
35981da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
35991da177e4SLinus Torvalds 	}
36003110ff80SHarvey Harrison 	dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec);
36011da177e4SLinus Torvalds 	return status;
36021da177e4SLinus Torvalds }
36031da177e4SLinus Torvalds 
36048687b63aSAl Viro static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
36051da177e4SLinus Torvalds {
36061da177e4SLinus Torvalds 	unsigned int attrwords = XDR_QUADLEN(attrlen);
36071da177e4SLinus Torvalds 	unsigned int nwords = xdr->p - savep;
36081da177e4SLinus Torvalds 
36091da177e4SLinus Torvalds 	if (unlikely(attrwords != nwords)) {
3610fe82a183SChuck Lever 		dprintk("%s: server returned incorrect attribute length: "
3611fe82a183SChuck Lever 			"%u %c %u\n",
36123110ff80SHarvey Harrison 				__func__,
36131da177e4SLinus Torvalds 				attrwords << 2,
36141da177e4SLinus Torvalds 				(attrwords < nwords) ? '<' : '>',
36151da177e4SLinus Torvalds 				nwords << 2);
36161da177e4SLinus Torvalds 		return -EIO;
36171da177e4SLinus Torvalds 	}
36181da177e4SLinus Torvalds 	return 0;
36191da177e4SLinus Torvalds }
36201da177e4SLinus Torvalds 
36211da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
36221da177e4SLinus Torvalds {
36238687b63aSAl Viro 	__be32 *p;
36241da177e4SLinus Torvalds 
3625c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 20);
3626c0eae66eSBenny Halevy 	if (unlikely(!p))
3627c0eae66eSBenny Halevy 		goto out_overflow;
36286f723f77SBenny Halevy 	cinfo->atomic = be32_to_cpup(p++);
36293ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &cinfo->before);
3630cccddf4fSBenny Halevy 	xdr_decode_hyper(p, &cinfo->after);
36311da177e4SLinus Torvalds 	return 0;
3632c0eae66eSBenny Halevy out_overflow:
3633c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3634c0eae66eSBenny Halevy 	return -EIO;
36351da177e4SLinus Torvalds }
36361da177e4SLinus Torvalds 
36371da177e4SLinus Torvalds static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
36381da177e4SLinus Torvalds {
36398687b63aSAl Viro 	__be32 *p;
36401da177e4SLinus Torvalds 	uint32_t supp, acc;
36411da177e4SLinus Torvalds 	int status;
36421da177e4SLinus Torvalds 
36431da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_ACCESS);
36441da177e4SLinus Torvalds 	if (status)
36451da177e4SLinus Torvalds 		return status;
3646c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
3647c0eae66eSBenny Halevy 	if (unlikely(!p))
3648c0eae66eSBenny Halevy 		goto out_overflow;
36496f723f77SBenny Halevy 	supp = be32_to_cpup(p++);
3650cccddf4fSBenny Halevy 	acc = be32_to_cpup(p);
36511da177e4SLinus Torvalds 	access->supported = supp;
36521da177e4SLinus Torvalds 	access->access = acc;
36531da177e4SLinus Torvalds 	return 0;
3654c0eae66eSBenny Halevy out_overflow:
3655c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3656c0eae66eSBenny Halevy 	return -EIO;
36571da177e4SLinus Torvalds }
36581da177e4SLinus Torvalds 
365907d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
36601da177e4SLinus Torvalds {
36618687b63aSAl Viro 	__be32 *p;
366207d30434SBenny Halevy 
366307d30434SBenny Halevy 	p = xdr_inline_decode(xdr, len);
366407d30434SBenny Halevy 	if (likely(p)) {
366507d30434SBenny Halevy 		memcpy(buf, p, len);
366607d30434SBenny Halevy 		return 0;
366707d30434SBenny Halevy 	}
366807d30434SBenny Halevy 	print_overflow_msg(__func__, xdr);
366907d30434SBenny Halevy 	return -EIO;
367007d30434SBenny Halevy }
367107d30434SBenny Halevy 
367207d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
367307d30434SBenny Halevy {
367407d30434SBenny Halevy 	return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE);
36751da177e4SLinus Torvalds }
36761da177e4SLinus Torvalds 
36771da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
36781da177e4SLinus Torvalds {
36791da177e4SLinus Torvalds 	int status;
36801da177e4SLinus Torvalds 
36811da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_CLOSE);
3682c1d51931STrond Myklebust 	if (status != -EIO)
3683c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
368407d30434SBenny Halevy 	if (!status)
368507d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
36861da177e4SLinus Torvalds 	return status;
36871da177e4SLinus Torvalds }
36881da177e4SLinus Torvalds 
3689db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier)
3690db942bbdSBenny Halevy {
3691db942bbdSBenny Halevy 	return decode_opaque_fixed(xdr, verifier, 8);
36921da177e4SLinus Torvalds }
36931da177e4SLinus Torvalds 
36941da177e4SLinus Torvalds static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
36951da177e4SLinus Torvalds {
36961da177e4SLinus Torvalds 	int status;
36971da177e4SLinus Torvalds 
36981da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_COMMIT);
3699db942bbdSBenny Halevy 	if (!status)
3700db942bbdSBenny Halevy 		status = decode_verifier(xdr, res->verf->verifier);
37011da177e4SLinus Torvalds 	return status;
37021da177e4SLinus Torvalds }
37031da177e4SLinus Torvalds 
37041da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
37051da177e4SLinus Torvalds {
37068687b63aSAl Viro 	__be32 *p;
37071da177e4SLinus Torvalds 	uint32_t bmlen;
37081da177e4SLinus Torvalds 	int status;
37091da177e4SLinus Torvalds 
37101da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_CREATE);
37111da177e4SLinus Torvalds 	if (status)
37121da177e4SLinus Torvalds 		return status;
37131da177e4SLinus Torvalds 	if ((status = decode_change_info(xdr, cinfo)))
37141da177e4SLinus Torvalds 		return status;
3715c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3716c0eae66eSBenny Halevy 	if (unlikely(!p))
3717c0eae66eSBenny Halevy 		goto out_overflow;
3718cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
3719c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
3720c0eae66eSBenny Halevy 	if (likely(p))
37211da177e4SLinus Torvalds 		return 0;
3722c0eae66eSBenny Halevy out_overflow:
3723c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3724c0eae66eSBenny Halevy 	return -EIO;
37251da177e4SLinus Torvalds }
37261da177e4SLinus Torvalds 
37271da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
37281da177e4SLinus Torvalds {
37298687b63aSAl Viro 	__be32 *savep;
37306c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
37311da177e4SLinus Torvalds 	int status;
37321da177e4SLinus Torvalds 
37331da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
37341da177e4SLinus Torvalds 		goto xdr_error;
37351da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
37361da177e4SLinus Torvalds 		goto xdr_error;
37371da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
37381da177e4SLinus Torvalds 		goto xdr_error;
37391da177e4SLinus Torvalds 	if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
37401da177e4SLinus Torvalds 		goto xdr_error;
37411da177e4SLinus Torvalds 	if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
37421da177e4SLinus Torvalds 		goto xdr_error;
37431da177e4SLinus Torvalds 	if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
37441da177e4SLinus Torvalds 		goto xdr_error;
37451da177e4SLinus Torvalds 	if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
37461da177e4SLinus Torvalds 		goto xdr_error;
37471da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
37481da177e4SLinus Torvalds xdr_error:
37493110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
37501da177e4SLinus Torvalds 	return status;
37511da177e4SLinus Torvalds }
37521da177e4SLinus Torvalds 
37531da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
37541da177e4SLinus Torvalds {
37558687b63aSAl Viro 	__be32 *savep;
37566c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
37571da177e4SLinus Torvalds 	int status;
37581da177e4SLinus Torvalds 
37591da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
37601da177e4SLinus Torvalds 		goto xdr_error;
37611da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
37621da177e4SLinus Torvalds 		goto xdr_error;
37631da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
37641da177e4SLinus Torvalds 		goto xdr_error;
37651da177e4SLinus Torvalds 
37661da177e4SLinus Torvalds 	if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
37671da177e4SLinus Torvalds 		goto xdr_error;
37681da177e4SLinus Torvalds 	if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
37691da177e4SLinus Torvalds 		goto xdr_error;
37701da177e4SLinus Torvalds 	if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
37711da177e4SLinus Torvalds 		goto xdr_error;
37721da177e4SLinus Torvalds 	if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
37731da177e4SLinus Torvalds 		goto xdr_error;
37741da177e4SLinus Torvalds 	if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
37751da177e4SLinus Torvalds 		goto xdr_error;
37761da177e4SLinus Torvalds 	if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
37771da177e4SLinus Torvalds 		goto xdr_error;
37781da177e4SLinus Torvalds 
37791da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
37801da177e4SLinus Torvalds xdr_error:
37813110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
37821da177e4SLinus Torvalds 	return status;
37831da177e4SLinus Torvalds }
37841da177e4SLinus Torvalds 
37851da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
37861da177e4SLinus Torvalds {
37878687b63aSAl Viro 	__be32 *savep;
37886c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
37891da177e4SLinus Torvalds 	int status;
37901da177e4SLinus Torvalds 
37911da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
37921da177e4SLinus Torvalds 		goto xdr_error;
37931da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
37941da177e4SLinus Torvalds 		goto xdr_error;
37951da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
37961da177e4SLinus Torvalds 		goto xdr_error;
37971da177e4SLinus Torvalds 
37981da177e4SLinus Torvalds 	if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
37991da177e4SLinus Torvalds 		goto xdr_error;
38001da177e4SLinus Torvalds 	if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
38011da177e4SLinus Torvalds 		goto xdr_error;
38021da177e4SLinus Torvalds 
38031da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
38041da177e4SLinus Torvalds xdr_error:
38053110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
38061da177e4SLinus Torvalds 	return status;
38071da177e4SLinus Torvalds }
38081da177e4SLinus Torvalds 
3809ae42c70aSBryan Schumaker static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
3810ae42c70aSBryan Schumaker 		struct nfs_fattr *fattr, struct nfs_fh *fh,
381180e52aceSTrond Myklebust 		const struct nfs_server *server, int may_sleep)
38121da177e4SLinus Torvalds {
3813bca79478STrond Myklebust 	int status;
3814bca79478STrond Myklebust 	umode_t fmode = 0;
381599baf625SManoj Naik 	uint64_t fileid;
3816ae42c70aSBryan Schumaker 	uint32_t type;
38171da177e4SLinus Torvalds 
3818f26c7a78STrond Myklebust 	status = decode_attr_type(xdr, bitmap, &type);
3819f26c7a78STrond Myklebust 	if (status < 0)
38201da177e4SLinus Torvalds 		goto xdr_error;
3821409924e4STrond Myklebust 	fattr->mode = 0;
3822409924e4STrond Myklebust 	if (status != 0) {
3823409924e4STrond Myklebust 		fattr->mode |= nfs_type2fmt[type];
3824409924e4STrond Myklebust 		fattr->valid |= status;
3825409924e4STrond Myklebust 	}
38261da177e4SLinus Torvalds 
3827f26c7a78STrond Myklebust 	status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
3828f26c7a78STrond Myklebust 	if (status < 0)
38291da177e4SLinus Torvalds 		goto xdr_error;
3830409924e4STrond Myklebust 	fattr->valid |= status;
3831f26c7a78STrond Myklebust 
3832f26c7a78STrond Myklebust 	status = decode_attr_size(xdr, bitmap, &fattr->size);
3833f26c7a78STrond Myklebust 	if (status < 0)
38341da177e4SLinus Torvalds 		goto xdr_error;
3835409924e4STrond Myklebust 	fattr->valid |= status;
3836f26c7a78STrond Myklebust 
3837f26c7a78STrond Myklebust 	status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
3838f26c7a78STrond Myklebust 	if (status < 0)
38391da177e4SLinus Torvalds 		goto xdr_error;
3840409924e4STrond Myklebust 	fattr->valid |= status;
3841f26c7a78STrond Myklebust 
3842ae42c70aSBryan Schumaker 	status = decode_attr_error(xdr, bitmap);
3843ae42c70aSBryan Schumaker 	if (status < 0)
3844ae42c70aSBryan Schumaker 		goto xdr_error;
3845ae42c70aSBryan Schumaker 
3846ae42c70aSBryan Schumaker 	status = decode_attr_filehandle(xdr, bitmap, fh);
3847ae42c70aSBryan Schumaker 	if (status < 0)
3848ae42c70aSBryan Schumaker 		goto xdr_error;
3849ae42c70aSBryan Schumaker 
3850f26c7a78STrond Myklebust 	status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
3851f26c7a78STrond Myklebust 	if (status < 0)
38521da177e4SLinus Torvalds 		goto xdr_error;
3853409924e4STrond Myklebust 	fattr->valid |= status;
3854f26c7a78STrond Myklebust 
3855f26c7a78STrond Myklebust 	status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
38567aaa0b3bSManoj Naik 						struct nfs4_fs_locations,
3857f26c7a78STrond Myklebust 						fattr));
3858f26c7a78STrond Myklebust 	if (status < 0)
3859683b57b4STrond Myklebust 		goto xdr_error;
3860409924e4STrond Myklebust 	fattr->valid |= status;
3861f26c7a78STrond Myklebust 
3862f26c7a78STrond Myklebust 	status = decode_attr_mode(xdr, bitmap, &fmode);
3863f26c7a78STrond Myklebust 	if (status < 0)
38641da177e4SLinus Torvalds 		goto xdr_error;
3865409924e4STrond Myklebust 	if (status != 0) {
38661da177e4SLinus Torvalds 		fattr->mode |= fmode;
3867409924e4STrond Myklebust 		fattr->valid |= status;
3868409924e4STrond Myklebust 	}
3869f26c7a78STrond Myklebust 
3870f26c7a78STrond Myklebust 	status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
3871f26c7a78STrond Myklebust 	if (status < 0)
38721da177e4SLinus Torvalds 		goto xdr_error;
3873409924e4STrond Myklebust 	fattr->valid |= status;
3874f26c7a78STrond Myklebust 
387580e52aceSTrond Myklebust 	status = decode_attr_owner(xdr, bitmap, server->nfs_client,
387680e52aceSTrond Myklebust 			&fattr->uid, may_sleep);
3877f26c7a78STrond Myklebust 	if (status < 0)
38781da177e4SLinus Torvalds 		goto xdr_error;
3879409924e4STrond Myklebust 	fattr->valid |= status;
3880f26c7a78STrond Myklebust 
388180e52aceSTrond Myklebust 	status = decode_attr_group(xdr, bitmap, server->nfs_client,
388280e52aceSTrond Myklebust 			&fattr->gid, may_sleep);
3883f26c7a78STrond Myklebust 	if (status < 0)
38841da177e4SLinus Torvalds 		goto xdr_error;
3885409924e4STrond Myklebust 	fattr->valid |= status;
3886f26c7a78STrond Myklebust 
3887f26c7a78STrond Myklebust 	status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
3888f26c7a78STrond Myklebust 	if (status < 0)
38891da177e4SLinus Torvalds 		goto xdr_error;
3890409924e4STrond Myklebust 	fattr->valid |= status;
3891f26c7a78STrond Myklebust 
3892f26c7a78STrond Myklebust 	status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
3893f26c7a78STrond Myklebust 	if (status < 0)
38941da177e4SLinus Torvalds 		goto xdr_error;
3895409924e4STrond Myklebust 	fattr->valid |= status;
3896f26c7a78STrond Myklebust 
3897f26c7a78STrond Myklebust 	status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
3898f26c7a78STrond Myklebust 	if (status < 0)
38991da177e4SLinus Torvalds 		goto xdr_error;
3900409924e4STrond Myklebust 	fattr->valid |= status;
3901f26c7a78STrond Myklebust 
3902f26c7a78STrond Myklebust 	status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
3903f26c7a78STrond Myklebust 	if (status < 0)
39041da177e4SLinus Torvalds 		goto xdr_error;
3905409924e4STrond Myklebust 	fattr->valid |= status;
3906f26c7a78STrond Myklebust 
3907f26c7a78STrond Myklebust 	status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
3908f26c7a78STrond Myklebust 	if (status < 0)
39091da177e4SLinus Torvalds 		goto xdr_error;
3910409924e4STrond Myklebust 	fattr->valid |= status;
3911f26c7a78STrond Myklebust 
3912f26c7a78STrond Myklebust 	status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid);
3913f26c7a78STrond Myklebust 	if (status < 0)
391499baf625SManoj Naik 		goto xdr_error;
39153201f3ddSTrond Myklebust 	if (status != 0 && !(fattr->valid & status)) {
391699baf625SManoj Naik 		fattr->fileid = fileid;
3917409924e4STrond Myklebust 		fattr->valid |= status;
3918409924e4STrond Myklebust 	}
3919f26c7a78STrond Myklebust 
3920ae42c70aSBryan Schumaker xdr_error:
3921ae42c70aSBryan Schumaker 	dprintk("%s: xdr returned %d\n", __func__, -status);
3922ae42c70aSBryan Schumaker 	return status;
3923ae42c70aSBryan Schumaker }
3924ae42c70aSBryan Schumaker 
3925ae42c70aSBryan Schumaker static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
3926ae42c70aSBryan Schumaker 		struct nfs_fh *fh, const struct nfs_server *server, int may_sleep)
3927ae42c70aSBryan Schumaker {
3928ae42c70aSBryan Schumaker 	__be32 *savep;
3929ae42c70aSBryan Schumaker 	uint32_t attrlen,
3930ae42c70aSBryan Schumaker 		 bitmap[2] = {0};
3931ae42c70aSBryan Schumaker 	int status;
3932ae42c70aSBryan Schumaker 
3933ae42c70aSBryan Schumaker 	status = decode_op_hdr(xdr, OP_GETATTR);
3934ae42c70aSBryan Schumaker 	if (status < 0)
3935ae42c70aSBryan Schumaker 		goto xdr_error;
3936ae42c70aSBryan Schumaker 
3937ae42c70aSBryan Schumaker 	status = decode_attr_bitmap(xdr, bitmap);
3938ae42c70aSBryan Schumaker 	if (status < 0)
3939ae42c70aSBryan Schumaker 		goto xdr_error;
3940ae42c70aSBryan Schumaker 
3941ae42c70aSBryan Schumaker 	status = decode_attr_length(xdr, &attrlen, &savep);
3942ae42c70aSBryan Schumaker 	if (status < 0)
3943ae42c70aSBryan Schumaker 		goto xdr_error;
3944ae42c70aSBryan Schumaker 
3945ae42c70aSBryan Schumaker 	status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, server, may_sleep);
3946ae42c70aSBryan Schumaker 	if (status < 0)
3947ae42c70aSBryan Schumaker 		goto xdr_error;
3948ae42c70aSBryan Schumaker 
3949f26c7a78STrond Myklebust 	status = verify_attr_len(xdr, savep, attrlen);
39501da177e4SLinus Torvalds xdr_error:
39513110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d\n", __func__, -status);
39521da177e4SLinus Torvalds 	return status;
39531da177e4SLinus Torvalds }
39541da177e4SLinus Torvalds 
3955ae42c70aSBryan Schumaker static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
3956ae42c70aSBryan Schumaker 		const struct nfs_server *server, int may_sleep)
3957ae42c70aSBryan Schumaker {
3958ae42c70aSBryan Schumaker 	return decode_getfattr_generic(xdr, fattr, NULL, server, may_sleep);
3959ae42c70aSBryan Schumaker }
39601da177e4SLinus Torvalds 
39611da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
39621da177e4SLinus Torvalds {
39638687b63aSAl Viro 	__be32 *savep;
39641da177e4SLinus Torvalds 	uint32_t attrlen, bitmap[2];
39651da177e4SLinus Torvalds 	int status;
39661da177e4SLinus Torvalds 
39671da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
39681da177e4SLinus Torvalds 		goto xdr_error;
39691da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
39701da177e4SLinus Torvalds 		goto xdr_error;
39711da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
39721da177e4SLinus Torvalds 		goto xdr_error;
39731da177e4SLinus Torvalds 
39741da177e4SLinus Torvalds 	fsinfo->rtmult = fsinfo->wtmult = 512;	/* ??? */
39751da177e4SLinus Torvalds 
39761da177e4SLinus Torvalds 	if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
39771da177e4SLinus Torvalds 		goto xdr_error;
39781da177e4SLinus Torvalds 	if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
39791da177e4SLinus Torvalds 		goto xdr_error;
39801da177e4SLinus Torvalds 	if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
39811da177e4SLinus Torvalds 		goto xdr_error;
39821da177e4SLinus Torvalds 	fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
39831da177e4SLinus Torvalds 	if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
39841da177e4SLinus Torvalds 		goto xdr_error;
39851da177e4SLinus Torvalds 	fsinfo->wtpref = fsinfo->wtmax;
39861da177e4SLinus Torvalds 
39871da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
39881da177e4SLinus Torvalds xdr_error:
39893110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
39901da177e4SLinus Torvalds 	return status;
39911da177e4SLinus Torvalds }
39921da177e4SLinus Torvalds 
39931da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
39941da177e4SLinus Torvalds {
39958687b63aSAl Viro 	__be32 *p;
39961da177e4SLinus Torvalds 	uint32_t len;
39971da177e4SLinus Torvalds 	int status;
39981da177e4SLinus Torvalds 
39999936781dSTrond Myklebust 	/* Zero handle first to allow comparisons */
40009936781dSTrond Myklebust 	memset(fh, 0, sizeof(*fh));
40019936781dSTrond Myklebust 
40021da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_GETFH);
40031da177e4SLinus Torvalds 	if (status)
40041da177e4SLinus Torvalds 		return status;
40051da177e4SLinus Torvalds 
4006c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4007c0eae66eSBenny Halevy 	if (unlikely(!p))
4008c0eae66eSBenny Halevy 		goto out_overflow;
4009cccddf4fSBenny Halevy 	len = be32_to_cpup(p);
40101da177e4SLinus Torvalds 	if (len > NFS4_FHSIZE)
40111da177e4SLinus Torvalds 		return -EIO;
40121da177e4SLinus Torvalds 	fh->size = len;
4013c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, len);
4014c0eae66eSBenny Halevy 	if (unlikely(!p))
4015c0eae66eSBenny Halevy 		goto out_overflow;
401699398d06SBenny Halevy 	memcpy(fh->data, p, len);
40171da177e4SLinus Torvalds 	return 0;
4018c0eae66eSBenny Halevy out_overflow:
4019c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4020c0eae66eSBenny Halevy 	return -EIO;
40211da177e4SLinus Torvalds }
40221da177e4SLinus Torvalds 
40231da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
40241da177e4SLinus Torvalds {
40251da177e4SLinus Torvalds 	int status;
40261da177e4SLinus Torvalds 
40271da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LINK);
40281da177e4SLinus Torvalds 	if (status)
40291da177e4SLinus Torvalds 		return status;
40301da177e4SLinus Torvalds 	return decode_change_info(xdr, cinfo);
40311da177e4SLinus Torvalds }
40321da177e4SLinus Torvalds 
40331da177e4SLinus Torvalds /*
40341da177e4SLinus Torvalds  * We create the owner, so we know a proper owner.id length is 4.
40351da177e4SLinus Torvalds  */
4036911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
40371da177e4SLinus Torvalds {
4038911d1aafSTrond Myklebust 	uint64_t offset, length, clientid;
40398687b63aSAl Viro 	__be32 *p;
4040911d1aafSTrond Myklebust 	uint32_t namelen, type;
40411da177e4SLinus Torvalds 
4042babddc72SBryan Schumaker 	p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
4043c0eae66eSBenny Halevy 	if (unlikely(!p))
4044c0eae66eSBenny Halevy 		goto out_overflow;
4045babddc72SBryan Schumaker 	p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
40463ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &length);
4047babddc72SBryan Schumaker 	type = be32_to_cpup(p++); /* 4 byte read */
4048babddc72SBryan Schumaker 	if (fl != NULL) { /* manipulate file lock */
4049911d1aafSTrond Myklebust 		fl->fl_start = (loff_t)offset;
4050911d1aafSTrond Myklebust 		fl->fl_end = fl->fl_start + (loff_t)length - 1;
4051911d1aafSTrond Myklebust 		if (length == ~(uint64_t)0)
4052911d1aafSTrond Myklebust 			fl->fl_end = OFFSET_MAX;
4053911d1aafSTrond Myklebust 		fl->fl_type = F_WRLCK;
4054911d1aafSTrond Myklebust 		if (type & 1)
4055911d1aafSTrond Myklebust 			fl->fl_type = F_RDLCK;
4056911d1aafSTrond Myklebust 		fl->fl_pid = 0;
4057911d1aafSTrond Myklebust 	}
4058babddc72SBryan Schumaker 	p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
4059babddc72SBryan Schumaker 	namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
4060babddc72SBryan Schumaker 	p = xdr_inline_decode(xdr, namelen); /* variable size field */
4061c0eae66eSBenny Halevy 	if (likely(p))
40621da177e4SLinus Torvalds 		return -NFS4ERR_DENIED;
4063c0eae66eSBenny Halevy out_overflow:
4064c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4065c0eae66eSBenny Halevy 	return -EIO;
40661da177e4SLinus Torvalds }
40671da177e4SLinus Torvalds 
4068911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
40691da177e4SLinus Torvalds {
40701da177e4SLinus Torvalds 	int status;
40711da177e4SLinus Torvalds 
40721da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCK);
4073c1d51931STrond Myklebust 	if (status == -EIO)
4074c1d51931STrond Myklebust 		goto out;
40751da177e4SLinus Torvalds 	if (status == 0) {
407607d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
407707d30434SBenny Halevy 		if (unlikely(status))
407807d30434SBenny Halevy 			goto out;
40791da177e4SLinus Torvalds 	} else if (status == -NFS4ERR_DENIED)
4080c1d51931STrond Myklebust 		status = decode_lock_denied(xdr, NULL);
4081c1d51931STrond Myklebust 	if (res->open_seqid != NULL)
4082c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->open_seqid);
4083c1d51931STrond Myklebust 	nfs_increment_lock_seqid(status, res->lock_seqid);
4084c1d51931STrond Myklebust out:
40851da177e4SLinus Torvalds 	return status;
40861da177e4SLinus Torvalds }
40871da177e4SLinus Torvalds 
4088911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
40891da177e4SLinus Torvalds {
40901da177e4SLinus Torvalds 	int status;
40911da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCKT);
40921da177e4SLinus Torvalds 	if (status == -NFS4ERR_DENIED)
4093911d1aafSTrond Myklebust 		return decode_lock_denied(xdr, res->denied);
40941da177e4SLinus Torvalds 	return status;
40951da177e4SLinus Torvalds }
40961da177e4SLinus Torvalds 
4097911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
40981da177e4SLinus Torvalds {
40991da177e4SLinus Torvalds 	int status;
41001da177e4SLinus Torvalds 
41011da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCKU);
4102c1d51931STrond Myklebust 	if (status != -EIO)
4103c1d51931STrond Myklebust 		nfs_increment_lock_seqid(status, res->seqid);
410407d30434SBenny Halevy 	if (status == 0)
410507d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
41061da177e4SLinus Torvalds 	return status;
41071da177e4SLinus Torvalds }
41081da177e4SLinus Torvalds 
4109d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr)
4110d3c7b7ccSTrond Myklebust {
4111d3c7b7ccSTrond Myklebust 	return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
4112d3c7b7ccSTrond Myklebust }
4113d3c7b7ccSTrond Myklebust 
41141da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr)
41151da177e4SLinus Torvalds {
41161da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_LOOKUP);
41171da177e4SLinus Torvalds }
41181da177e4SLinus Torvalds 
41191da177e4SLinus Torvalds /* This is too sick! */
41201da177e4SLinus Torvalds static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
41211da177e4SLinus Torvalds {
41228687b63aSAl Viro 	__be32 *p;
41231da177e4SLinus Torvalds 	uint32_t limit_type, nblocks, blocksize;
41241da177e4SLinus Torvalds 
4125c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
4126c0eae66eSBenny Halevy 	if (unlikely(!p))
4127c0eae66eSBenny Halevy 		goto out_overflow;
41286f723f77SBenny Halevy 	limit_type = be32_to_cpup(p++);
41291da177e4SLinus Torvalds 	switch (limit_type) {
41301da177e4SLinus Torvalds 	case 1:
4131cccddf4fSBenny Halevy 		xdr_decode_hyper(p, maxsize);
41321da177e4SLinus Torvalds 		break;
41331da177e4SLinus Torvalds 	case 2:
41346f723f77SBenny Halevy 		nblocks = be32_to_cpup(p++);
4135cccddf4fSBenny Halevy 		blocksize = be32_to_cpup(p);
41361da177e4SLinus Torvalds 		*maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
41371da177e4SLinus Torvalds 	}
41381da177e4SLinus Torvalds 	return 0;
4139c0eae66eSBenny Halevy out_overflow:
4140c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4141c0eae66eSBenny Halevy 	return -EIO;
41421da177e4SLinus Torvalds }
41431da177e4SLinus Torvalds 
41441da177e4SLinus Torvalds static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
41451da177e4SLinus Torvalds {
41468687b63aSAl Viro 	__be32 *p;
41471da177e4SLinus Torvalds 	uint32_t delegation_type;
414807d30434SBenny Halevy 	int status;
41491da177e4SLinus Torvalds 
4150c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4151c0eae66eSBenny Halevy 	if (unlikely(!p))
4152c0eae66eSBenny Halevy 		goto out_overflow;
4153cccddf4fSBenny Halevy 	delegation_type = be32_to_cpup(p);
41541da177e4SLinus Torvalds 	if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
41551da177e4SLinus Torvalds 		res->delegation_type = 0;
41561da177e4SLinus Torvalds 		return 0;
41571da177e4SLinus Torvalds 	}
415807d30434SBenny Halevy 	status = decode_stateid(xdr, &res->delegation);
415907d30434SBenny Halevy 	if (unlikely(status))
416007d30434SBenny Halevy 		return status;
4161c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4162c0eae66eSBenny Halevy 	if (unlikely(!p))
4163c0eae66eSBenny Halevy 		goto out_overflow;
4164cccddf4fSBenny Halevy 	res->do_recall = be32_to_cpup(p);
416505d564feSAndy Adamson 
41661da177e4SLinus Torvalds 	switch (delegation_type) {
41671da177e4SLinus Torvalds 	case NFS4_OPEN_DELEGATE_READ:
41681da177e4SLinus Torvalds 		res->delegation_type = FMODE_READ;
41691da177e4SLinus Torvalds 		break;
41701da177e4SLinus Torvalds 	case NFS4_OPEN_DELEGATE_WRITE:
41711da177e4SLinus Torvalds 		res->delegation_type = FMODE_WRITE|FMODE_READ;
41721da177e4SLinus Torvalds 		if (decode_space_limit(xdr, &res->maxsize) < 0)
41731da177e4SLinus Torvalds 				return -EIO;
41741da177e4SLinus Torvalds 	}
41757539bbabSDavid Howells 	return decode_ace(xdr, NULL, res->server->nfs_client);
4176c0eae66eSBenny Halevy out_overflow:
4177c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4178c0eae66eSBenny Halevy 	return -EIO;
41791da177e4SLinus Torvalds }
41801da177e4SLinus Torvalds 
41811da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
41821da177e4SLinus Torvalds {
41838687b63aSAl Viro 	__be32 *p;
4184aa53ed54SJeff Layton 	uint32_t savewords, bmlen, i;
41851da177e4SLinus Torvalds 	int status;
41861da177e4SLinus Torvalds 
41871da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN);
4188c1d51931STrond Myklebust 	if (status != -EIO)
4189c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
419007d30434SBenny Halevy 	if (!status)
419107d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
419207d30434SBenny Halevy 	if (unlikely(status))
41931da177e4SLinus Torvalds 		return status;
41941da177e4SLinus Torvalds 
41951da177e4SLinus Torvalds 	decode_change_info(xdr, &res->cinfo);
41961da177e4SLinus Torvalds 
4197c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4198c0eae66eSBenny Halevy 	if (unlikely(!p))
4199c0eae66eSBenny Halevy 		goto out_overflow;
42006f723f77SBenny Halevy 	res->rflags = be32_to_cpup(p++);
4201cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
42021da177e4SLinus Torvalds 	if (bmlen > 10)
42031da177e4SLinus Torvalds 		goto xdr_error;
42041da177e4SLinus Torvalds 
4205c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
4206c0eae66eSBenny Halevy 	if (unlikely(!p))
4207c0eae66eSBenny Halevy 		goto out_overflow;
4208aa53ed54SJeff Layton 	savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
4209aa53ed54SJeff Layton 	for (i = 0; i < savewords; ++i)
42106f723f77SBenny Halevy 		res->attrset[i] = be32_to_cpup(p++);
4211aa53ed54SJeff Layton 	for (; i < NFS4_BITMAP_SIZE; i++)
4212aa53ed54SJeff Layton 		res->attrset[i] = 0;
4213aa53ed54SJeff Layton 
42141da177e4SLinus Torvalds 	return decode_delegation(xdr, res);
42151da177e4SLinus Torvalds xdr_error:
42163110ff80SHarvey Harrison 	dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
42171da177e4SLinus Torvalds 	return -EIO;
4218c0eae66eSBenny Halevy out_overflow:
4219c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4220c0eae66eSBenny Halevy 	return -EIO;
42211da177e4SLinus Torvalds }
42221da177e4SLinus Torvalds 
42231da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
42241da177e4SLinus Torvalds {
42251da177e4SLinus Torvalds 	int status;
42261da177e4SLinus Torvalds 
42271da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
4228c1d51931STrond Myklebust 	if (status != -EIO)
4229c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
423007d30434SBenny Halevy 	if (!status)
423107d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
42321da177e4SLinus Torvalds 	return status;
42331da177e4SLinus Torvalds }
42341da177e4SLinus Torvalds 
42351da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
42361da177e4SLinus Torvalds {
42371da177e4SLinus Torvalds 	int status;
42381da177e4SLinus Torvalds 
42391da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
4240c1d51931STrond Myklebust 	if (status != -EIO)
4241c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
424207d30434SBenny Halevy 	if (!status)
424307d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
42441da177e4SLinus Torvalds 	return status;
42451da177e4SLinus Torvalds }
42461da177e4SLinus Torvalds 
42471da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr)
42481da177e4SLinus Torvalds {
42491da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_PUTFH);
42501da177e4SLinus Torvalds }
42511da177e4SLinus Torvalds 
42521da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr)
42531da177e4SLinus Torvalds {
42541da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_PUTROOTFH);
42551da177e4SLinus Torvalds }
42561da177e4SLinus Torvalds 
42571da177e4SLinus Torvalds static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
42581da177e4SLinus Torvalds {
42591da177e4SLinus Torvalds 	struct kvec *iov = req->rq_rcv_buf.head;
42608687b63aSAl Viro 	__be32 *p;
42611da177e4SLinus Torvalds 	uint32_t count, eof, recvd, hdrlen;
42621da177e4SLinus Torvalds 	int status;
42631da177e4SLinus Torvalds 
42641da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READ);
42651da177e4SLinus Torvalds 	if (status)
42661da177e4SLinus Torvalds 		return status;
4267c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4268c0eae66eSBenny Halevy 	if (unlikely(!p))
4269c0eae66eSBenny Halevy 		goto out_overflow;
42706f723f77SBenny Halevy 	eof = be32_to_cpup(p++);
4271cccddf4fSBenny Halevy 	count = be32_to_cpup(p);
42721da177e4SLinus Torvalds 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
42731da177e4SLinus Torvalds 	recvd = req->rq_rcv_buf.len - hdrlen;
42741da177e4SLinus Torvalds 	if (count > recvd) {
4275fe82a183SChuck Lever 		dprintk("NFS: server cheating in read reply: "
42761da177e4SLinus Torvalds 				"count %u > recvd %u\n", count, recvd);
42771da177e4SLinus Torvalds 		count = recvd;
42781da177e4SLinus Torvalds 		eof = 0;
42791da177e4SLinus Torvalds 	}
42801da177e4SLinus Torvalds 	xdr_read_pages(xdr, count);
42811da177e4SLinus Torvalds 	res->eof = eof;
42821da177e4SLinus Torvalds 	res->count = count;
42831da177e4SLinus Torvalds 	return 0;
4284c0eae66eSBenny Halevy out_overflow:
4285c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4286c0eae66eSBenny Halevy 	return -EIO;
42871da177e4SLinus Torvalds }
42881da177e4SLinus Torvalds 
42891da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
42901da177e4SLinus Torvalds {
42911da177e4SLinus Torvalds 	struct xdr_buf	*rcvbuf = &req->rq_rcv_buf;
42921da177e4SLinus Torvalds 	struct kvec	*iov = rcvbuf->head;
4293bcecff77SChuck Lever 	size_t		hdrlen;
4294bcecff77SChuck Lever 	u32		recvd, pglen = rcvbuf->page_len;
4295bcecff77SChuck Lever 	int		status;
42961da177e4SLinus Torvalds 
42971da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READDIR);
4298db942bbdSBenny Halevy 	if (!status)
4299db942bbdSBenny Halevy 		status = decode_verifier(xdr, readdir->verifier.data);
4300db942bbdSBenny Halevy 	if (unlikely(status))
43011da177e4SLinus Torvalds 		return status;
430244109241SFred Isaman 	dprintk("%s: verifier = %08x:%08x\n",
430344109241SFred Isaman 			__func__,
4304eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[0],
4305eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[1]);
4306eadf4598STrond Myklebust 
43071da177e4SLinus Torvalds 
4308db942bbdSBenny Halevy 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
43091da177e4SLinus Torvalds 	recvd = rcvbuf->len - hdrlen;
43101da177e4SLinus Torvalds 	if (pglen > recvd)
43111da177e4SLinus Torvalds 		pglen = recvd;
43121da177e4SLinus Torvalds 	xdr_read_pages(xdr, pglen);
43131da177e4SLinus Torvalds 
43147bda2cdfSJeff Layton 
43151da177e4SLinus Torvalds 	return 0;
43161da177e4SLinus Torvalds }
43171da177e4SLinus Torvalds 
43181da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
43191da177e4SLinus Torvalds {
43201da177e4SLinus Torvalds 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
43211da177e4SLinus Torvalds 	struct kvec *iov = rcvbuf->head;
4322bcecff77SChuck Lever 	size_t hdrlen;
4323bcecff77SChuck Lever 	u32 len, recvd;
43248687b63aSAl Viro 	__be32 *p;
43251da177e4SLinus Torvalds 	int status;
43261da177e4SLinus Torvalds 
43271da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READLINK);
43281da177e4SLinus Torvalds 	if (status)
43291da177e4SLinus Torvalds 		return status;
43301da177e4SLinus Torvalds 
43311da177e4SLinus Torvalds 	/* Convert length of symlink */
4332c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4333c0eae66eSBenny Halevy 	if (unlikely(!p))
4334c0eae66eSBenny Halevy 		goto out_overflow;
4335cccddf4fSBenny Halevy 	len = be32_to_cpup(p);
43361da177e4SLinus Torvalds 	if (len >= rcvbuf->page_len || len <= 0) {
4337fe82a183SChuck Lever 		dprintk("nfs: server returned giant symlink!\n");
43381da177e4SLinus Torvalds 		return -ENAMETOOLONG;
43391da177e4SLinus Torvalds 	}
43401da177e4SLinus Torvalds 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
43411da177e4SLinus Torvalds 	recvd = req->rq_rcv_buf.len - hdrlen;
43421da177e4SLinus Torvalds 	if (recvd < len) {
4343fe82a183SChuck Lever 		dprintk("NFS: server cheating in readlink reply: "
43441da177e4SLinus Torvalds 				"count %u > recvd %u\n", len, recvd);
43451da177e4SLinus Torvalds 		return -EIO;
43461da177e4SLinus Torvalds 	}
43471da177e4SLinus Torvalds 	xdr_read_pages(xdr, len);
43481da177e4SLinus Torvalds 	/*
43491da177e4SLinus Torvalds 	 * The XDR encode routine has set things up so that
43501da177e4SLinus Torvalds 	 * the link text will be copied directly into the
43511da177e4SLinus Torvalds 	 * buffer.  We just have to do overflow-checking,
43521da177e4SLinus Torvalds 	 * and and null-terminate the text (the VFS expects
43531da177e4SLinus Torvalds 	 * null-termination).
43541da177e4SLinus Torvalds 	 */
4355b4687da7SChuck Lever 	xdr_terminate_string(rcvbuf, len);
43561da177e4SLinus Torvalds 	return 0;
4357c0eae66eSBenny Halevy out_overflow:
4358c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4359c0eae66eSBenny Halevy 	return -EIO;
43601da177e4SLinus Torvalds }
43611da177e4SLinus Torvalds 
43621da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
43631da177e4SLinus Torvalds {
43641da177e4SLinus Torvalds 	int status;
43651da177e4SLinus Torvalds 
43661da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_REMOVE);
43671da177e4SLinus Torvalds 	if (status)
43681da177e4SLinus Torvalds 		goto out;
43691da177e4SLinus Torvalds 	status = decode_change_info(xdr, cinfo);
43701da177e4SLinus Torvalds out:
43711da177e4SLinus Torvalds 	return status;
43721da177e4SLinus Torvalds }
43731da177e4SLinus Torvalds 
43741da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
43751da177e4SLinus Torvalds 	      struct nfs4_change_info *new_cinfo)
43761da177e4SLinus Torvalds {
43771da177e4SLinus Torvalds 	int status;
43781da177e4SLinus Torvalds 
43791da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_RENAME);
43801da177e4SLinus Torvalds 	if (status)
43811da177e4SLinus Torvalds 		goto out;
43821da177e4SLinus Torvalds 	if ((status = decode_change_info(xdr, old_cinfo)))
43831da177e4SLinus Torvalds 		goto out;
43841da177e4SLinus Torvalds 	status = decode_change_info(xdr, new_cinfo);
43851da177e4SLinus Torvalds out:
43861da177e4SLinus Torvalds 	return status;
43871da177e4SLinus Torvalds }
43881da177e4SLinus Torvalds 
43891da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr)
43901da177e4SLinus Torvalds {
43911da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_RENEW);
43921da177e4SLinus Torvalds }
43931da177e4SLinus Torvalds 
439456ae19f3STrond Myklebust static int
439556ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr)
439656ae19f3STrond Myklebust {
439756ae19f3STrond Myklebust 	return decode_op_hdr(xdr, OP_RESTOREFH);
439856ae19f3STrond Myklebust }
439956ae19f3STrond Myklebust 
4400029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
4401029d105eSJ. Bruce Fields 		size_t *acl_len)
4402029d105eSJ. Bruce Fields {
44038687b63aSAl Viro 	__be32 *savep;
4404029d105eSJ. Bruce Fields 	uint32_t attrlen,
4405029d105eSJ. Bruce Fields 		 bitmap[2] = {0};
4406029d105eSJ. Bruce Fields 	struct kvec *iov = req->rq_rcv_buf.head;
4407029d105eSJ. Bruce Fields 	int status;
4408029d105eSJ. Bruce Fields 
4409029d105eSJ. Bruce Fields 	*acl_len = 0;
4410029d105eSJ. Bruce Fields 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4411029d105eSJ. Bruce Fields 		goto out;
4412029d105eSJ. Bruce Fields 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4413029d105eSJ. Bruce Fields 		goto out;
4414029d105eSJ. Bruce Fields 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4415029d105eSJ. Bruce Fields 		goto out;
4416029d105eSJ. Bruce Fields 
4417029d105eSJ. Bruce Fields 	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
4418029d105eSJ. Bruce Fields 		return -EIO;
4419029d105eSJ. Bruce Fields 	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
4420bcecff77SChuck Lever 		size_t hdrlen;
4421bcecff77SChuck Lever 		u32 recvd;
4422029d105eSJ. Bruce Fields 
4423029d105eSJ. Bruce Fields 		/* We ignore &savep and don't do consistency checks on
4424029d105eSJ. Bruce Fields 		 * the attr length.  Let userspace figure it out.... */
4425029d105eSJ. Bruce Fields 		hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
4426029d105eSJ. Bruce Fields 		recvd = req->rq_rcv_buf.len - hdrlen;
4427029d105eSJ. Bruce Fields 		if (attrlen > recvd) {
4428fe82a183SChuck Lever 			dprintk("NFS: server cheating in getattr"
4429029d105eSJ. Bruce Fields 					" acl reply: attrlen %u > recvd %u\n",
4430029d105eSJ. Bruce Fields 					attrlen, recvd);
4431029d105eSJ. Bruce Fields 			return -EINVAL;
4432029d105eSJ. Bruce Fields 		}
4433029d105eSJ. Bruce Fields 		xdr_read_pages(xdr, attrlen);
4434029d105eSJ. Bruce Fields 		*acl_len = attrlen;
44358c233cf9SJ. Bruce Fields 	} else
44368c233cf9SJ. Bruce Fields 		status = -EOPNOTSUPP;
4437029d105eSJ. Bruce Fields 
4438029d105eSJ. Bruce Fields out:
4439029d105eSJ. Bruce Fields 	return status;
4440029d105eSJ. Bruce Fields }
4441029d105eSJ. Bruce Fields 
44421da177e4SLinus Torvalds static int
44431da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr)
44441da177e4SLinus Torvalds {
44451da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_SAVEFH);
44461da177e4SLinus Torvalds }
44471da177e4SLinus Torvalds 
44489e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr)
44491da177e4SLinus Torvalds {
44508687b63aSAl Viro 	__be32 *p;
44511da177e4SLinus Torvalds 	uint32_t bmlen;
44521da177e4SLinus Torvalds 	int status;
44531da177e4SLinus Torvalds 
44541da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_SETATTR);
44551da177e4SLinus Torvalds 	if (status)
44561da177e4SLinus Torvalds 		return status;
4457c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4458c0eae66eSBenny Halevy 	if (unlikely(!p))
4459c0eae66eSBenny Halevy 		goto out_overflow;
4460cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
4461c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
4462c0eae66eSBenny Halevy 	if (likely(p))
44631da177e4SLinus Torvalds 		return 0;
4464c0eae66eSBenny Halevy out_overflow:
4465c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4466c0eae66eSBenny Halevy 	return -EIO;
44671da177e4SLinus Torvalds }
44681da177e4SLinus Torvalds 
4469bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res)
44701da177e4SLinus Torvalds {
44718687b63aSAl Viro 	__be32 *p;
44721da177e4SLinus Torvalds 	uint32_t opnum;
44731da177e4SLinus Torvalds 	int32_t nfserr;
44741da177e4SLinus Torvalds 
4475c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4476c0eae66eSBenny Halevy 	if (unlikely(!p))
4477c0eae66eSBenny Halevy 		goto out_overflow;
44786f723f77SBenny Halevy 	opnum = be32_to_cpup(p++);
44791da177e4SLinus Torvalds 	if (opnum != OP_SETCLIENTID) {
4480fe82a183SChuck Lever 		dprintk("nfs: decode_setclientid: Server returned operation"
44811da177e4SLinus Torvalds 			" %d\n", opnum);
44821da177e4SLinus Torvalds 		return -EIO;
44831da177e4SLinus Torvalds 	}
4484cccddf4fSBenny Halevy 	nfserr = be32_to_cpup(p);
44851da177e4SLinus Torvalds 	if (nfserr == NFS_OK) {
4486c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
4487c0eae66eSBenny Halevy 		if (unlikely(!p))
4488c0eae66eSBenny Halevy 			goto out_overflow;
4489bb8b27e5STrond Myklebust 		p = xdr_decode_hyper(p, &res->clientid);
4490bb8b27e5STrond Myklebust 		memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
44911da177e4SLinus Torvalds 	} else if (nfserr == NFSERR_CLID_INUSE) {
44921da177e4SLinus Torvalds 		uint32_t len;
44931da177e4SLinus Torvalds 
44941da177e4SLinus Torvalds 		/* skip netid string */
4495c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
4496c0eae66eSBenny Halevy 		if (unlikely(!p))
4497c0eae66eSBenny Halevy 			goto out_overflow;
4498cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
4499c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
4500c0eae66eSBenny Halevy 		if (unlikely(!p))
4501c0eae66eSBenny Halevy 			goto out_overflow;
45021da177e4SLinus Torvalds 
45031da177e4SLinus Torvalds 		/* skip uaddr string */
4504c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
4505c0eae66eSBenny Halevy 		if (unlikely(!p))
4506c0eae66eSBenny Halevy 			goto out_overflow;
4507cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
4508c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
4509c0eae66eSBenny Halevy 		if (unlikely(!p))
4510c0eae66eSBenny Halevy 			goto out_overflow;
45111da177e4SLinus Torvalds 		return -NFSERR_CLID_INUSE;
45121da177e4SLinus Torvalds 	} else
4513856dff3dSBenny Halevy 		return nfs4_stat_to_errno(nfserr);
45141da177e4SLinus Torvalds 
45151da177e4SLinus Torvalds 	return 0;
4516c0eae66eSBenny Halevy out_overflow:
4517c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4518c0eae66eSBenny Halevy 	return -EIO;
45191da177e4SLinus Torvalds }
45201da177e4SLinus Torvalds 
45211da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr)
45221da177e4SLinus Torvalds {
45231da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
45241da177e4SLinus Torvalds }
45251da177e4SLinus Torvalds 
45261da177e4SLinus Torvalds static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
45271da177e4SLinus Torvalds {
45288687b63aSAl Viro 	__be32 *p;
45291da177e4SLinus Torvalds 	int status;
45301da177e4SLinus Torvalds 
45311da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_WRITE);
45321da177e4SLinus Torvalds 	if (status)
45331da177e4SLinus Torvalds 		return status;
45341da177e4SLinus Torvalds 
4535c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 16);
4536c0eae66eSBenny Halevy 	if (unlikely(!p))
4537c0eae66eSBenny Halevy 		goto out_overflow;
45386f723f77SBenny Halevy 	res->count = be32_to_cpup(p++);
45396f723f77SBenny Halevy 	res->verf->committed = be32_to_cpup(p++);
454099398d06SBenny Halevy 	memcpy(res->verf->verifier, p, 8);
45411da177e4SLinus Torvalds 	return 0;
4542c0eae66eSBenny Halevy out_overflow:
4543c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4544c0eae66eSBenny Halevy 	return -EIO;
45451da177e4SLinus Torvalds }
45461da177e4SLinus Torvalds 
45471da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr)
45481da177e4SLinus Torvalds {
45491da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_DELEGRETURN);
45501da177e4SLinus Torvalds }
45511da177e4SLinus Torvalds 
455299fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
455399fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr,
455499fe60d0SBenny Halevy 			      struct nfs41_exchange_id_res *res)
455599fe60d0SBenny Halevy {
455699fe60d0SBenny Halevy 	__be32 *p;
455799fe60d0SBenny Halevy 	uint32_t dummy;
45582460ba57SBenny Halevy 	char *dummy_str;
455999fe60d0SBenny Halevy 	int status;
456099fe60d0SBenny Halevy 	struct nfs_client *clp = res->client;
456199fe60d0SBenny Halevy 
456299fe60d0SBenny Halevy 	status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
456399fe60d0SBenny Halevy 	if (status)
456499fe60d0SBenny Halevy 		return status;
456599fe60d0SBenny Halevy 
4566c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4567c0eae66eSBenny Halevy 	if (unlikely(!p))
4568c0eae66eSBenny Halevy 		goto out_overflow;
4569cccddf4fSBenny Halevy 	xdr_decode_hyper(p, &clp->cl_ex_clid);
4570c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
4571c0eae66eSBenny Halevy 	if (unlikely(!p))
4572c0eae66eSBenny Halevy 		goto out_overflow;
45736f723f77SBenny Halevy 	clp->cl_seqid = be32_to_cpup(p++);
45746f723f77SBenny Halevy 	clp->cl_exchange_flags = be32_to_cpup(p++);
457599fe60d0SBenny Halevy 
457699fe60d0SBenny Halevy 	/* We ask for SP4_NONE */
4577cccddf4fSBenny Halevy 	dummy = be32_to_cpup(p);
457899fe60d0SBenny Halevy 	if (dummy != SP4_NONE)
457999fe60d0SBenny Halevy 		return -EIO;
458099fe60d0SBenny Halevy 
458199fe60d0SBenny Halevy 	/* Throw away minor_id */
4582c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4583c0eae66eSBenny Halevy 	if (unlikely(!p))
4584c0eae66eSBenny Halevy 		goto out_overflow;
458599fe60d0SBenny Halevy 
458699fe60d0SBenny Halevy 	/* Throw away Major id */
45872460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45882460ba57SBenny Halevy 	if (unlikely(status))
45892460ba57SBenny Halevy 		return status;
459099fe60d0SBenny Halevy 
459199fe60d0SBenny Halevy 	/* Throw away server_scope */
45922460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45932460ba57SBenny Halevy 	if (unlikely(status))
45942460ba57SBenny Halevy 		return status;
459599fe60d0SBenny Halevy 
459699fe60d0SBenny Halevy 	/* Throw away Implementation id array */
45972460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45982460ba57SBenny Halevy 	if (unlikely(status))
45992460ba57SBenny Halevy 		return status;
460099fe60d0SBenny Halevy 
460199fe60d0SBenny Halevy 	return 0;
4602c0eae66eSBenny Halevy out_overflow:
4603c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4604c0eae66eSBenny Halevy 	return -EIO;
460599fe60d0SBenny Halevy }
4606fc931582SAndy Adamson 
4607fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr,
4608fc931582SAndy Adamson 			     struct nfs4_channel_attrs *attrs)
4609fc931582SAndy Adamson {
4610fc931582SAndy Adamson 	__be32 *p;
4611fc931582SAndy Adamson 	u32 nr_attrs;
4612fc931582SAndy Adamson 
4613c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 28);
4614c0eae66eSBenny Halevy 	if (unlikely(!p))
4615c0eae66eSBenny Halevy 		goto out_overflow;
46166f723f77SBenny Halevy 	attrs->headerpadsz = be32_to_cpup(p++);
46176f723f77SBenny Halevy 	attrs->max_rqst_sz = be32_to_cpup(p++);
46186f723f77SBenny Halevy 	attrs->max_resp_sz = be32_to_cpup(p++);
46196f723f77SBenny Halevy 	attrs->max_resp_sz_cached = be32_to_cpup(p++);
46206f723f77SBenny Halevy 	attrs->max_ops = be32_to_cpup(p++);
46216f723f77SBenny Halevy 	attrs->max_reqs = be32_to_cpup(p++);
4622cccddf4fSBenny Halevy 	nr_attrs = be32_to_cpup(p);
4623fc931582SAndy Adamson 	if (unlikely(nr_attrs > 1)) {
4624fc931582SAndy Adamson 		printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n",
4625fc931582SAndy Adamson 			__func__, nr_attrs);
4626fc931582SAndy Adamson 		return -EINVAL;
4627fc931582SAndy Adamson 	}
4628c0eae66eSBenny Halevy 	if (nr_attrs == 1) {
4629c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
4630c0eae66eSBenny Halevy 		if (unlikely(!p))
4631c0eae66eSBenny Halevy 			goto out_overflow;
4632c0eae66eSBenny Halevy 	}
4633fc931582SAndy Adamson 	return 0;
4634c0eae66eSBenny Halevy out_overflow:
4635c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4636c0eae66eSBenny Halevy 	return -EIO;
4637fc931582SAndy Adamson }
4638fc931582SAndy Adamson 
4639e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
4640e78291e4SBenny Halevy {
4641e78291e4SBenny Halevy 	return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
4642fc931582SAndy Adamson }
4643fc931582SAndy Adamson 
4644fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr,
4645fc931582SAndy Adamson 				 struct nfs41_create_session_res *res)
4646fc931582SAndy Adamson {
4647fc931582SAndy Adamson 	__be32 *p;
4648fc931582SAndy Adamson 	int status;
4649fc931582SAndy Adamson 	struct nfs_client *clp = res->client;
4650fc931582SAndy Adamson 	struct nfs4_session *session = clp->cl_session;
4651fc931582SAndy Adamson 
4652fc931582SAndy Adamson 	status = decode_op_hdr(xdr, OP_CREATE_SESSION);
4653e78291e4SBenny Halevy 	if (!status)
4654e78291e4SBenny Halevy 		status = decode_sessionid(xdr, &session->sess_id);
4655e78291e4SBenny Halevy 	if (unlikely(status))
4656fc931582SAndy Adamson 		return status;
4657fc931582SAndy Adamson 
4658fc931582SAndy Adamson 	/* seqid, flags */
4659c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4660c0eae66eSBenny Halevy 	if (unlikely(!p))
4661c0eae66eSBenny Halevy 		goto out_overflow;
46626f723f77SBenny Halevy 	clp->cl_seqid = be32_to_cpup(p++);
4663cccddf4fSBenny Halevy 	session->flags = be32_to_cpup(p);
4664fc931582SAndy Adamson 
4665fc931582SAndy Adamson 	/* Channel attributes */
4666fc931582SAndy Adamson 	status = decode_chan_attrs(xdr, &session->fc_attrs);
4667fc931582SAndy Adamson 	if (!status)
4668fc931582SAndy Adamson 		status = decode_chan_attrs(xdr, &session->bc_attrs);
4669fc931582SAndy Adamson 	return status;
4670c0eae66eSBenny Halevy out_overflow:
4671c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4672c0eae66eSBenny Halevy 	return -EIO;
4673fc931582SAndy Adamson }
46740f3e66c6SAndy Adamson 
46750f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
46760f3e66c6SAndy Adamson {
46770f3e66c6SAndy Adamson 	return decode_op_hdr(xdr, OP_DESTROY_SESSION);
46780f3e66c6SAndy Adamson }
467918019753SRicardo Labiaga 
468018019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
468118019753SRicardo Labiaga {
468218019753SRicardo Labiaga 	return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
468318019753SRicardo Labiaga }
468499fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
468599fe60d0SBenny Halevy 
46869b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr,
46879b7b9fccSAndy Adamson 			   struct nfs4_sequence_res *res,
46889b7b9fccSAndy Adamson 			   struct rpc_rqst *rqstp)
46899b7b9fccSAndy Adamson {
46909b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1)
4691fc01cea9SAndy Adamson 	struct nfs4_sessionid id;
4692fc01cea9SAndy Adamson 	u32 dummy;
4693fc01cea9SAndy Adamson 	int status;
4694fc01cea9SAndy Adamson 	__be32 *p;
4695fc01cea9SAndy Adamson 
46969b7b9fccSAndy Adamson 	if (!res->sr_session)
46979b7b9fccSAndy Adamson 		return 0;
46989b7b9fccSAndy Adamson 
4699fc01cea9SAndy Adamson 	status = decode_op_hdr(xdr, OP_SEQUENCE);
4700e78291e4SBenny Halevy 	if (!status)
4701e78291e4SBenny Halevy 		status = decode_sessionid(xdr, &id);
4702e78291e4SBenny Halevy 	if (unlikely(status))
4703fc01cea9SAndy Adamson 		goto out_err;
47049b7b9fccSAndy Adamson 
4705fc01cea9SAndy Adamson 	/*
4706fc01cea9SAndy Adamson 	 * If the server returns different values for sessionID, slotID or
4707fc01cea9SAndy Adamson 	 * sequence number, the server is looney tunes.
4708fc01cea9SAndy Adamson 	 */
4709fdcb4577STrond Myklebust 	status = -EREMOTEIO;
4710fc01cea9SAndy Adamson 
4711fc01cea9SAndy Adamson 	if (memcmp(id.data, res->sr_session->sess_id.data,
4712fc01cea9SAndy Adamson 		   NFS4_MAX_SESSIONID_LEN)) {
4713fc01cea9SAndy Adamson 		dprintk("%s Invalid session id\n", __func__);
4714fc01cea9SAndy Adamson 		goto out_err;
4715fc01cea9SAndy Adamson 	}
4716e78291e4SBenny Halevy 
4717c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 20);
4718c0eae66eSBenny Halevy 	if (unlikely(!p))
4719c0eae66eSBenny Halevy 		goto out_overflow;
4720e78291e4SBenny Halevy 
4721fc01cea9SAndy Adamson 	/* seqid */
47226f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4723dfb4f309SBenny Halevy 	if (dummy != res->sr_slot->seq_nr) {
4724fc01cea9SAndy Adamson 		dprintk("%s Invalid sequence number\n", __func__);
4725fc01cea9SAndy Adamson 		goto out_err;
4726fc01cea9SAndy Adamson 	}
4727fc01cea9SAndy Adamson 	/* slot id */
47286f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4729dfb4f309SBenny Halevy 	if (dummy != res->sr_slot - res->sr_session->fc_slot_table.slots) {
4730fc01cea9SAndy Adamson 		dprintk("%s Invalid slot id\n", __func__);
4731fc01cea9SAndy Adamson 		goto out_err;
4732fc01cea9SAndy Adamson 	}
4733fc01cea9SAndy Adamson 	/* highest slot id - currently not processed */
47346f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4735fc01cea9SAndy Adamson 	/* target highest slot id - currently not processed */
47366f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
47370629e370SAlexandros Batsakis 	/* result flags */
47380629e370SAlexandros Batsakis 	res->sr_status_flags = be32_to_cpup(p);
4739fc01cea9SAndy Adamson 	status = 0;
4740fc01cea9SAndy Adamson out_err:
4741fc01cea9SAndy Adamson 	res->sr_status = status;
4742fc01cea9SAndy Adamson 	return status;
4743c0eae66eSBenny Halevy out_overflow:
4744c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4745c0eae66eSBenny Halevy 	status = -EIO;
4746c0eae66eSBenny Halevy 	goto out_err;
4747fc01cea9SAndy Adamson #else  /* CONFIG_NFS_V4_1 */
47489b7b9fccSAndy Adamson 	return 0;
4749fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */
47509b7b9fccSAndy Adamson }
47519b7b9fccSAndy Adamson 
47521da177e4SLinus Torvalds /*
475349c2559eSBenny Halevy  * END OF "GENERIC" DECODE ROUTINES.
475449c2559eSBenny Halevy  */
475549c2559eSBenny Halevy 
475649c2559eSBenny Halevy /*
47571da177e4SLinus Torvalds  * Decode OPEN_DOWNGRADE response
47581da177e4SLinus Torvalds  */
47598687b63aSAl Viro static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
47601da177e4SLinus Torvalds {
47611da177e4SLinus Torvalds 	struct xdr_stream xdr;
47621da177e4SLinus Torvalds 	struct compound_hdr hdr;
47631da177e4SLinus Torvalds 	int status;
47641da177e4SLinus Torvalds 
47651da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
47661da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
47671da177e4SLinus Torvalds 	if (status)
47681da177e4SLinus Torvalds 		goto out;
47699b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
47709b7b9fccSAndy Adamson 	if (status)
47719b7b9fccSAndy Adamson 		goto out;
47721da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
47731da177e4SLinus Torvalds 	if (status)
47741da177e4SLinus Torvalds 		goto out;
47751da177e4SLinus Torvalds 	status = decode_open_downgrade(&xdr, res);
4776516a6af6STrond Myklebust 	if (status != 0)
4777516a6af6STrond Myklebust 		goto out;
477880e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
477980e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
47801da177e4SLinus Torvalds out:
47811da177e4SLinus Torvalds 	return status;
47821da177e4SLinus Torvalds }
47831da177e4SLinus Torvalds 
47841da177e4SLinus Torvalds /*
47851da177e4SLinus Torvalds  * Decode ACCESS response
47861da177e4SLinus Torvalds  */
47878687b63aSAl Viro static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
47881da177e4SLinus Torvalds {
47891da177e4SLinus Torvalds 	struct xdr_stream xdr;
47901da177e4SLinus Torvalds 	struct compound_hdr hdr;
47911da177e4SLinus Torvalds 	int status;
47921da177e4SLinus Torvalds 
47931da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
47949b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
47959b7b9fccSAndy Adamson 	if (status)
47969b7b9fccSAndy Adamson 		goto out;
47979b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
47989b7b9fccSAndy Adamson 	if (status)
47991da177e4SLinus Torvalds 		goto out;
480076b32999STrond Myklebust 	status = decode_putfh(&xdr);
480176b32999STrond Myklebust 	if (status != 0)
480276b32999STrond Myklebust 		goto out;
48031da177e4SLinus Torvalds 	status = decode_access(&xdr, res);
480476b32999STrond Myklebust 	if (status != 0)
480576b32999STrond Myklebust 		goto out;
480680e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
480780e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
48081da177e4SLinus Torvalds out:
48091da177e4SLinus Torvalds 	return status;
48101da177e4SLinus Torvalds }
48111da177e4SLinus Torvalds 
48121da177e4SLinus Torvalds /*
48131da177e4SLinus Torvalds  * Decode LOOKUP response
48141da177e4SLinus Torvalds  */
48158687b63aSAl Viro static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
48161da177e4SLinus Torvalds {
48171da177e4SLinus Torvalds 	struct xdr_stream xdr;
48181da177e4SLinus Torvalds 	struct compound_hdr hdr;
48191da177e4SLinus Torvalds 	int status;
48201da177e4SLinus Torvalds 
48211da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48229b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48239b7b9fccSAndy Adamson 	if (status)
48249b7b9fccSAndy Adamson 		goto out;
48259b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48269b7b9fccSAndy Adamson 	if (status)
48271da177e4SLinus Torvalds 		goto out;
48281da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
48291da177e4SLinus Torvalds 		goto out;
48301da177e4SLinus Torvalds 	if ((status = decode_lookup(&xdr)) != 0)
48311da177e4SLinus Torvalds 		goto out;
48321da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
48331da177e4SLinus Torvalds 		goto out;
483480e52aceSTrond Myklebust 	status = decode_getfattr(&xdr, res->fattr, res->server
483580e52aceSTrond Myklebust 			,!RPC_IS_ASYNC(rqstp->rq_task));
48361da177e4SLinus Torvalds out:
48371da177e4SLinus Torvalds 	return status;
48381da177e4SLinus Torvalds }
48391da177e4SLinus Torvalds 
48401da177e4SLinus Torvalds /*
48411da177e4SLinus Torvalds  * Decode LOOKUP_ROOT response
48421da177e4SLinus Torvalds  */
48438687b63aSAl Viro static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
48441da177e4SLinus Torvalds {
48451da177e4SLinus Torvalds 	struct xdr_stream xdr;
48461da177e4SLinus Torvalds 	struct compound_hdr hdr;
48471da177e4SLinus Torvalds 	int status;
48481da177e4SLinus Torvalds 
48491da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48509b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48519b7b9fccSAndy Adamson 	if (status)
48529b7b9fccSAndy Adamson 		goto out;
48539b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48549b7b9fccSAndy Adamson 	if (status)
48551da177e4SLinus Torvalds 		goto out;
48561da177e4SLinus Torvalds 	if ((status = decode_putrootfh(&xdr)) != 0)
48571da177e4SLinus Torvalds 		goto out;
48581da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) == 0)
485980e52aceSTrond Myklebust 		status = decode_getfattr(&xdr, res->fattr, res->server,
486080e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task));
48611da177e4SLinus Torvalds out:
48621da177e4SLinus Torvalds 	return status;
48631da177e4SLinus Torvalds }
48641da177e4SLinus Torvalds 
48651da177e4SLinus Torvalds /*
48661da177e4SLinus Torvalds  * Decode REMOVE response
48671da177e4SLinus Torvalds  */
48684fdc17b2STrond Myklebust static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
48691da177e4SLinus Torvalds {
48701da177e4SLinus Torvalds 	struct xdr_stream xdr;
48711da177e4SLinus Torvalds 	struct compound_hdr hdr;
48721da177e4SLinus Torvalds 	int status;
48731da177e4SLinus Torvalds 
48741da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48759b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48769b7b9fccSAndy Adamson 	if (status)
48779b7b9fccSAndy Adamson 		goto out;
48789b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48799b7b9fccSAndy Adamson 	if (status)
48801da177e4SLinus Torvalds 		goto out;
488116e42959STrond Myklebust 	if ((status = decode_putfh(&xdr)) != 0)
488216e42959STrond Myklebust 		goto out;
488316e42959STrond Myklebust 	if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
488416e42959STrond Myklebust 		goto out;
4885d346890bSTrond Myklebust 	decode_getfattr(&xdr, res->dir_attr, res->server,
488680e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
48871da177e4SLinus Torvalds out:
48881da177e4SLinus Torvalds 	return status;
48891da177e4SLinus Torvalds }
48901da177e4SLinus Torvalds 
48911da177e4SLinus Torvalds /*
48921da177e4SLinus Torvalds  * Decode RENAME response
48931da177e4SLinus Torvalds  */
4894e8582a8bSJeff Layton static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs_renameres *res)
48951da177e4SLinus Torvalds {
48961da177e4SLinus Torvalds 	struct xdr_stream xdr;
48971da177e4SLinus Torvalds 	struct compound_hdr hdr;
48981da177e4SLinus Torvalds 	int status;
48991da177e4SLinus Torvalds 
49001da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
49019b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
49029b7b9fccSAndy Adamson 	if (status)
49039b7b9fccSAndy Adamson 		goto out;
49049b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
49059b7b9fccSAndy Adamson 	if (status)
49061da177e4SLinus Torvalds 		goto out;
49071da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49081da177e4SLinus Torvalds 		goto out;
49091da177e4SLinus Torvalds 	if ((status = decode_savefh(&xdr)) != 0)
49101da177e4SLinus Torvalds 		goto out;
49111da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49121da177e4SLinus Torvalds 		goto out;
49136caf2c82STrond Myklebust 	if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
49146caf2c82STrond Myklebust 		goto out;
49156caf2c82STrond Myklebust 	/* Current FH is target directory */
491680e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->new_fattr, res->server,
491780e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
49186caf2c82STrond Myklebust 		goto out;
49196caf2c82STrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
49206caf2c82STrond Myklebust 		goto out;
492180e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->old_fattr, res->server,
492280e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49231da177e4SLinus Torvalds out:
49241da177e4SLinus Torvalds 	return status;
49251da177e4SLinus Torvalds }
49261da177e4SLinus Torvalds 
49271da177e4SLinus Torvalds /*
49281da177e4SLinus Torvalds  * Decode LINK response
49291da177e4SLinus Torvalds  */
49308687b63aSAl Viro static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
49311da177e4SLinus Torvalds {
49321da177e4SLinus Torvalds 	struct xdr_stream xdr;
49331da177e4SLinus Torvalds 	struct compound_hdr hdr;
49341da177e4SLinus Torvalds 	int status;
49351da177e4SLinus Torvalds 
49361da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
49379b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
49389b7b9fccSAndy Adamson 	if (status)
49399b7b9fccSAndy Adamson 		goto out;
49409b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
49419b7b9fccSAndy Adamson 	if (status)
49421da177e4SLinus Torvalds 		goto out;
49431da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49441da177e4SLinus Torvalds 		goto out;
49451da177e4SLinus Torvalds 	if ((status = decode_savefh(&xdr)) != 0)
49461da177e4SLinus Torvalds 		goto out;
49471da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49481da177e4SLinus Torvalds 		goto out;
494991ba2eeeSTrond Myklebust 	if ((status = decode_link(&xdr, &res->cinfo)) != 0)
495091ba2eeeSTrond Myklebust 		goto out;
495191ba2eeeSTrond Myklebust 	/*
495291ba2eeeSTrond Myklebust 	 * Note order: OP_LINK leaves the directory as the current
495391ba2eeeSTrond Myklebust 	 *             filehandle.
495491ba2eeeSTrond Myklebust 	 */
495580e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->dir_attr, res->server,
495680e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
495791ba2eeeSTrond Myklebust 		goto out;
495891ba2eeeSTrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
495991ba2eeeSTrond Myklebust 		goto out;
496080e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
496180e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49621da177e4SLinus Torvalds out:
49631da177e4SLinus Torvalds 	return status;
49641da177e4SLinus Torvalds }
49651da177e4SLinus Torvalds 
49661da177e4SLinus Torvalds /*
49671da177e4SLinus Torvalds  * Decode CREATE response
49681da177e4SLinus Torvalds  */
49698687b63aSAl Viro static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
49701da177e4SLinus Torvalds {
49711da177e4SLinus Torvalds 	struct xdr_stream xdr;
49721da177e4SLinus Torvalds 	struct compound_hdr hdr;
49731da177e4SLinus Torvalds 	int status;
49741da177e4SLinus Torvalds 
49751da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
49769b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
49779b7b9fccSAndy Adamson 	if (status)
49789b7b9fccSAndy Adamson 		goto out;
49799b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
49809b7b9fccSAndy Adamson 	if (status)
49811da177e4SLinus Torvalds 		goto out;
49821da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49831da177e4SLinus Torvalds 		goto out;
498456ae19f3STrond Myklebust 	if ((status = decode_savefh(&xdr)) != 0)
498556ae19f3STrond Myklebust 		goto out;
49861da177e4SLinus Torvalds 	if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
49871da177e4SLinus Torvalds 		goto out;
49881da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
49891da177e4SLinus Torvalds 		goto out;
499080e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->fattr, res->server,
499180e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
499256ae19f3STrond Myklebust 		goto out;
499356ae19f3STrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
499456ae19f3STrond Myklebust 		goto out;
499580e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->dir_fattr, res->server,
499680e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49971da177e4SLinus Torvalds out:
49981da177e4SLinus Torvalds 	return status;
49991da177e4SLinus Torvalds }
50001da177e4SLinus Torvalds 
50011da177e4SLinus Torvalds /*
50021da177e4SLinus Torvalds  * Decode SYMLINK response
50031da177e4SLinus Torvalds  */
50048687b63aSAl Viro static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
50051da177e4SLinus Torvalds {
50061da177e4SLinus Torvalds 	return nfs4_xdr_dec_create(rqstp, p, res);
50071da177e4SLinus Torvalds }
50081da177e4SLinus Torvalds 
50091da177e4SLinus Torvalds /*
50101da177e4SLinus Torvalds  * Decode GETATTR response
50111da177e4SLinus Torvalds  */
50128687b63aSAl Viro static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
50131da177e4SLinus Torvalds {
50141da177e4SLinus Torvalds 	struct xdr_stream xdr;
50151da177e4SLinus Torvalds 	struct compound_hdr hdr;
50161da177e4SLinus Torvalds 	int status;
50171da177e4SLinus Torvalds 
50181da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
50191da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
50201da177e4SLinus Torvalds 	if (status)
50211da177e4SLinus Torvalds 		goto out;
50229b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50239b7b9fccSAndy Adamson 	if (status)
50249b7b9fccSAndy Adamson 		goto out;
50251da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
50261da177e4SLinus Torvalds 	if (status)
50271da177e4SLinus Torvalds 		goto out;
502880e52aceSTrond Myklebust 	status = decode_getfattr(&xdr, res->fattr, res->server,
502980e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
50301da177e4SLinus Torvalds out:
50311da177e4SLinus Torvalds 	return status;
50321da177e4SLinus Torvalds }
50331da177e4SLinus Torvalds 
503423ec6965SJ. Bruce Fields /*
503523ec6965SJ. Bruce Fields  * Encode an SETACL request
503623ec6965SJ. Bruce Fields  */
503723ec6965SJ. Bruce Fields static int
50388687b63aSAl Viro nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
503923ec6965SJ. Bruce Fields {
504023ec6965SJ. Bruce Fields 	struct xdr_stream xdr;
504123ec6965SJ. Bruce Fields 	struct compound_hdr hdr = {
504266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
504323ec6965SJ. Bruce Fields 	};
504423ec6965SJ. Bruce Fields 	int status;
504523ec6965SJ. Bruce Fields 
504623ec6965SJ. Bruce Fields 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
50470c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
50489b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
5049cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
5050d017931cSAndy Adamson 	status = encode_setacl(&xdr, args, &hdr);
5051d017931cSAndy Adamson 	encode_nops(&hdr);
505223ec6965SJ. Bruce Fields 	return status;
505323ec6965SJ. Bruce Fields }
505405d564feSAndy Adamson 
505523ec6965SJ. Bruce Fields /*
505623ec6965SJ. Bruce Fields  * Decode SETACL response
505723ec6965SJ. Bruce Fields  */
505823ec6965SJ. Bruce Fields static int
505973c403a9SBenny Halevy nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
506073c403a9SBenny Halevy 		    struct nfs_setaclres *res)
506123ec6965SJ. Bruce Fields {
506223ec6965SJ. Bruce Fields 	struct xdr_stream xdr;
506323ec6965SJ. Bruce Fields 	struct compound_hdr hdr;
506423ec6965SJ. Bruce Fields 	int status;
506523ec6965SJ. Bruce Fields 
506623ec6965SJ. Bruce Fields 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
506723ec6965SJ. Bruce Fields 	status = decode_compound_hdr(&xdr, &hdr);
506823ec6965SJ. Bruce Fields 	if (status)
506923ec6965SJ. Bruce Fields 		goto out;
50709b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50719b7b9fccSAndy Adamson 	if (status)
50729b7b9fccSAndy Adamson 		goto out;
507323ec6965SJ. Bruce Fields 	status = decode_putfh(&xdr);
507423ec6965SJ. Bruce Fields 	if (status)
507523ec6965SJ. Bruce Fields 		goto out;
50769e9ecc03SBenny Halevy 	status = decode_setattr(&xdr);
507723ec6965SJ. Bruce Fields out:
507823ec6965SJ. Bruce Fields 	return status;
507923ec6965SJ. Bruce Fields }
50801da177e4SLinus Torvalds 
50811da177e4SLinus Torvalds /*
5082029d105eSJ. Bruce Fields  * Decode GETACL response
5083029d105eSJ. Bruce Fields  */
5084029d105eSJ. Bruce Fields static int
5085663c79b3SBenny Halevy nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
5086663c79b3SBenny Halevy 		    struct nfs_getaclres *res)
5087029d105eSJ. Bruce Fields {
5088029d105eSJ. Bruce Fields 	struct xdr_stream xdr;
5089029d105eSJ. Bruce Fields 	struct compound_hdr hdr;
5090029d105eSJ. Bruce Fields 	int status;
5091029d105eSJ. Bruce Fields 
5092029d105eSJ. Bruce Fields 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5093029d105eSJ. Bruce Fields 	status = decode_compound_hdr(&xdr, &hdr);
5094029d105eSJ. Bruce Fields 	if (status)
5095029d105eSJ. Bruce Fields 		goto out;
50969b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50979b7b9fccSAndy Adamson 	if (status)
50989b7b9fccSAndy Adamson 		goto out;
5099029d105eSJ. Bruce Fields 	status = decode_putfh(&xdr);
5100029d105eSJ. Bruce Fields 	if (status)
5101029d105eSJ. Bruce Fields 		goto out;
5102663c79b3SBenny Halevy 	status = decode_getacl(&xdr, rqstp, &res->acl_len);
5103029d105eSJ. Bruce Fields 
5104029d105eSJ. Bruce Fields out:
5105029d105eSJ. Bruce Fields 	return status;
5106029d105eSJ. Bruce Fields }
5107029d105eSJ. Bruce Fields 
5108029d105eSJ. Bruce Fields /*
51091da177e4SLinus Torvalds  * Decode CLOSE response
51101da177e4SLinus Torvalds  */
51118687b63aSAl Viro static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
51121da177e4SLinus Torvalds {
51131da177e4SLinus Torvalds 	struct xdr_stream xdr;
51141da177e4SLinus Torvalds 	struct compound_hdr hdr;
51151da177e4SLinus Torvalds 	int status;
51161da177e4SLinus Torvalds 
51171da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51181da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51191da177e4SLinus Torvalds 	if (status)
51201da177e4SLinus Torvalds 		goto out;
51219b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
51229b7b9fccSAndy Adamson 	if (status)
51239b7b9fccSAndy Adamson 		goto out;
51241da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51251da177e4SLinus Torvalds 	if (status)
51261da177e4SLinus Torvalds 		goto out;
51271da177e4SLinus Torvalds 	status = decode_close(&xdr, res);
5128516a6af6STrond Myklebust 	if (status != 0)
5129516a6af6STrond Myklebust 		goto out;
5130516a6af6STrond Myklebust 	/*
5131516a6af6STrond Myklebust 	 * Note: Server may do delete on close for this file
5132516a6af6STrond Myklebust 	 * 	in which case the getattr call will fail with
5133516a6af6STrond Myklebust 	 * 	an ESTALE error. Shouldn't be a problem,
5134516a6af6STrond Myklebust 	 * 	though, since fattr->valid will remain unset.
5135516a6af6STrond Myklebust 	 */
513680e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
513780e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
51381da177e4SLinus Torvalds out:
51391da177e4SLinus Torvalds 	return status;
51401da177e4SLinus Torvalds }
51411da177e4SLinus Torvalds 
51421da177e4SLinus Torvalds /*
51431da177e4SLinus Torvalds  * Decode OPEN response
51441da177e4SLinus Torvalds  */
51458687b63aSAl Viro static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
51461da177e4SLinus Torvalds {
51471da177e4SLinus Torvalds 	struct xdr_stream xdr;
51481da177e4SLinus Torvalds 	struct compound_hdr hdr;
51491da177e4SLinus Torvalds 	int status;
51501da177e4SLinus Torvalds 
51511da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51521da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51531da177e4SLinus Torvalds 	if (status)
51541da177e4SLinus Torvalds 		goto out;
51559b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
51569b7b9fccSAndy Adamson 	if (status)
51579b7b9fccSAndy Adamson 		goto out;
51581da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51591da177e4SLinus Torvalds 	if (status)
51601da177e4SLinus Torvalds 		goto out;
516156ae19f3STrond Myklebust 	status = decode_savefh(&xdr);
516256ae19f3STrond Myklebust 	if (status)
516356ae19f3STrond Myklebust 		goto out;
51641da177e4SLinus Torvalds 	status = decode_open(&xdr, res);
51651da177e4SLinus Torvalds 	if (status)
51661da177e4SLinus Torvalds 		goto out;
51679936781dSTrond Myklebust 	if (decode_getfh(&xdr, &res->fh) != 0)
51681da177e4SLinus Torvalds 		goto out;
516980e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->f_attr, res->server,
517080e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
517156ae19f3STrond Myklebust 		goto out;
5172365c8f58STrond Myklebust 	if (decode_restorefh(&xdr) != 0)
517356ae19f3STrond Myklebust 		goto out;
517480e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->dir_attr, res->server,
517580e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
51761da177e4SLinus Torvalds out:
51771da177e4SLinus Torvalds 	return status;
51781da177e4SLinus Torvalds }
51791da177e4SLinus Torvalds 
51801da177e4SLinus Torvalds /*
51811da177e4SLinus Torvalds  * Decode OPEN_CONFIRM response
51821da177e4SLinus Torvalds  */
51838687b63aSAl Viro static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res)
51841da177e4SLinus Torvalds {
51851da177e4SLinus Torvalds 	struct xdr_stream xdr;
51861da177e4SLinus Torvalds 	struct compound_hdr hdr;
51871da177e4SLinus Torvalds 	int status;
51881da177e4SLinus Torvalds 
51891da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51901da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51911da177e4SLinus Torvalds 	if (status)
51921da177e4SLinus Torvalds 		goto out;
51931da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51941da177e4SLinus Torvalds 	if (status)
51951da177e4SLinus Torvalds 		goto out;
51961da177e4SLinus Torvalds 	status = decode_open_confirm(&xdr, res);
51971da177e4SLinus Torvalds out:
51981da177e4SLinus Torvalds 	return status;
51991da177e4SLinus Torvalds }
52001da177e4SLinus Torvalds 
52011da177e4SLinus Torvalds /*
52021da177e4SLinus Torvalds  * Decode OPEN response
52031da177e4SLinus Torvalds  */
52048687b63aSAl Viro static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
52051da177e4SLinus Torvalds {
52061da177e4SLinus Torvalds 	struct xdr_stream xdr;
52071da177e4SLinus Torvalds 	struct compound_hdr hdr;
52081da177e4SLinus Torvalds 	int status;
52091da177e4SLinus Torvalds 
52101da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52111da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52121da177e4SLinus Torvalds 	if (status)
52131da177e4SLinus Torvalds 		goto out;
52149b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52159b7b9fccSAndy Adamson 	if (status)
52169b7b9fccSAndy Adamson 		goto out;
52171da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52181da177e4SLinus Torvalds 	if (status)
52191da177e4SLinus Torvalds 		goto out;
52201da177e4SLinus Torvalds 	status = decode_open(&xdr, res);
5221864472e9STrond Myklebust 	if (status)
5222864472e9STrond Myklebust 		goto out;
522380e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->f_attr, res->server,
522480e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
52251da177e4SLinus Torvalds out:
52261da177e4SLinus Torvalds 	return status;
52271da177e4SLinus Torvalds }
52281da177e4SLinus Torvalds 
52291da177e4SLinus Torvalds /*
52301da177e4SLinus Torvalds  * Decode SETATTR response
52311da177e4SLinus Torvalds  */
52328687b63aSAl Viro static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
52331da177e4SLinus Torvalds {
52341da177e4SLinus Torvalds 	struct xdr_stream xdr;
52351da177e4SLinus Torvalds 	struct compound_hdr hdr;
52361da177e4SLinus Torvalds 	int status;
52371da177e4SLinus Torvalds 
52381da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52391da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52401da177e4SLinus Torvalds 	if (status)
52411da177e4SLinus Torvalds 		goto out;
52429b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52439b7b9fccSAndy Adamson 	if (status)
52449b7b9fccSAndy Adamson 		goto out;
52451da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52461da177e4SLinus Torvalds 	if (status)
52471da177e4SLinus Torvalds 		goto out;
52489e9ecc03SBenny Halevy 	status = decode_setattr(&xdr);
52491da177e4SLinus Torvalds 	if (status)
52501da177e4SLinus Torvalds 		goto out;
525180e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
525280e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
52531da177e4SLinus Torvalds out:
52541da177e4SLinus Torvalds 	return status;
52551da177e4SLinus Torvalds }
52561da177e4SLinus Torvalds 
52571da177e4SLinus Torvalds /*
52581da177e4SLinus Torvalds  * Decode LOCK response
52591da177e4SLinus Torvalds  */
52608687b63aSAl Viro static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
52611da177e4SLinus Torvalds {
52621da177e4SLinus Torvalds 	struct xdr_stream xdr;
52631da177e4SLinus Torvalds 	struct compound_hdr hdr;
52641da177e4SLinus Torvalds 	int status;
52651da177e4SLinus Torvalds 
52661da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52671da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52681da177e4SLinus Torvalds 	if (status)
52691da177e4SLinus Torvalds 		goto out;
52709b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52719b7b9fccSAndy Adamson 	if (status)
52729b7b9fccSAndy Adamson 		goto out;
52731da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52741da177e4SLinus Torvalds 	if (status)
52751da177e4SLinus Torvalds 		goto out;
52761da177e4SLinus Torvalds 	status = decode_lock(&xdr, res);
52771da177e4SLinus Torvalds out:
52781da177e4SLinus Torvalds 	return status;
52791da177e4SLinus Torvalds }
52801da177e4SLinus Torvalds 
52811da177e4SLinus Torvalds /*
52821da177e4SLinus Torvalds  * Decode LOCKT response
52831da177e4SLinus Torvalds  */
52848687b63aSAl Viro static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
52851da177e4SLinus Torvalds {
52861da177e4SLinus Torvalds 	struct xdr_stream xdr;
52871da177e4SLinus Torvalds 	struct compound_hdr hdr;
52881da177e4SLinus Torvalds 	int status;
52891da177e4SLinus Torvalds 
52901da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52911da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52921da177e4SLinus Torvalds 	if (status)
52931da177e4SLinus Torvalds 		goto out;
52949b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52959b7b9fccSAndy Adamson 	if (status)
52969b7b9fccSAndy Adamson 		goto out;
52971da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52981da177e4SLinus Torvalds 	if (status)
52991da177e4SLinus Torvalds 		goto out;
53001da177e4SLinus Torvalds 	status = decode_lockt(&xdr, res);
53011da177e4SLinus Torvalds out:
53021da177e4SLinus Torvalds 	return status;
53031da177e4SLinus Torvalds }
53041da177e4SLinus Torvalds 
53051da177e4SLinus Torvalds /*
53061da177e4SLinus Torvalds  * Decode LOCKU response
53071da177e4SLinus Torvalds  */
53088687b63aSAl Viro static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
53091da177e4SLinus Torvalds {
53101da177e4SLinus Torvalds 	struct xdr_stream xdr;
53111da177e4SLinus Torvalds 	struct compound_hdr hdr;
53121da177e4SLinus Torvalds 	int status;
53131da177e4SLinus Torvalds 
53141da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53151da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53161da177e4SLinus Torvalds 	if (status)
53171da177e4SLinus Torvalds 		goto out;
53189b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53199b7b9fccSAndy Adamson 	if (status)
53209b7b9fccSAndy Adamson 		goto out;
53211da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53221da177e4SLinus Torvalds 	if (status)
53231da177e4SLinus Torvalds 		goto out;
53241da177e4SLinus Torvalds 	status = decode_locku(&xdr, res);
53251da177e4SLinus Torvalds out:
53261da177e4SLinus Torvalds 	return status;
53271da177e4SLinus Torvalds }
53281da177e4SLinus Torvalds 
5329d3c7b7ccSTrond Myklebust static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
5330d3c7b7ccSTrond Myklebust {
5331d3c7b7ccSTrond Myklebust 	struct xdr_stream xdr;
5332d3c7b7ccSTrond Myklebust 	struct compound_hdr hdr;
5333d3c7b7ccSTrond Myklebust 	int status;
5334d3c7b7ccSTrond Myklebust 
5335d3c7b7ccSTrond Myklebust 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5336d3c7b7ccSTrond Myklebust 	status = decode_compound_hdr(&xdr, &hdr);
5337d3c7b7ccSTrond Myklebust 	if (!status)
5338d3c7b7ccSTrond Myklebust 		status = decode_release_lockowner(&xdr);
5339d3c7b7ccSTrond Myklebust 	return status;
5340d3c7b7ccSTrond Myklebust }
5341d3c7b7ccSTrond Myklebust 
53421da177e4SLinus Torvalds /*
53431da177e4SLinus Torvalds  * Decode READLINK response
53441da177e4SLinus Torvalds  */
5345f50c7000SBenny Halevy static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
5346f50c7000SBenny Halevy 				 struct nfs4_readlink_res *res)
53471da177e4SLinus Torvalds {
53481da177e4SLinus Torvalds 	struct xdr_stream xdr;
53491da177e4SLinus Torvalds 	struct compound_hdr hdr;
53501da177e4SLinus Torvalds 	int status;
53511da177e4SLinus Torvalds 
53521da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53531da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53541da177e4SLinus Torvalds 	if (status)
53551da177e4SLinus Torvalds 		goto out;
53569b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53579b7b9fccSAndy Adamson 	if (status)
53589b7b9fccSAndy Adamson 		goto out;
53591da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53601da177e4SLinus Torvalds 	if (status)
53611da177e4SLinus Torvalds 		goto out;
53621da177e4SLinus Torvalds 	status = decode_readlink(&xdr, rqstp);
53631da177e4SLinus Torvalds out:
53641da177e4SLinus Torvalds 	return status;
53651da177e4SLinus Torvalds }
53661da177e4SLinus Torvalds 
53671da177e4SLinus Torvalds /*
53681da177e4SLinus Torvalds  * Decode READDIR response
53691da177e4SLinus Torvalds  */
53708687b63aSAl Viro static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
53711da177e4SLinus Torvalds {
53721da177e4SLinus Torvalds 	struct xdr_stream xdr;
53731da177e4SLinus Torvalds 	struct compound_hdr hdr;
53741da177e4SLinus Torvalds 	int status;
53751da177e4SLinus Torvalds 
53761da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53771da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53781da177e4SLinus Torvalds 	if (status)
53791da177e4SLinus Torvalds 		goto out;
53809b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53819b7b9fccSAndy Adamson 	if (status)
53829b7b9fccSAndy Adamson 		goto out;
53831da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53841da177e4SLinus Torvalds 	if (status)
53851da177e4SLinus Torvalds 		goto out;
53861da177e4SLinus Torvalds 	status = decode_readdir(&xdr, rqstp, res);
53871da177e4SLinus Torvalds out:
53881da177e4SLinus Torvalds 	return status;
53891da177e4SLinus Torvalds }
53901da177e4SLinus Torvalds 
53911da177e4SLinus Torvalds /*
53921da177e4SLinus Torvalds  * Decode Read response
53931da177e4SLinus Torvalds  */
53948687b63aSAl Viro static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
53951da177e4SLinus Torvalds {
53961da177e4SLinus Torvalds 	struct xdr_stream xdr;
53971da177e4SLinus Torvalds 	struct compound_hdr hdr;
53981da177e4SLinus Torvalds 	int status;
53991da177e4SLinus Torvalds 
54001da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
54011da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54021da177e4SLinus Torvalds 	if (status)
54031da177e4SLinus Torvalds 		goto out;
54049b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
54059b7b9fccSAndy Adamson 	if (status)
54069b7b9fccSAndy Adamson 		goto out;
54071da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
54081da177e4SLinus Torvalds 	if (status)
54091da177e4SLinus Torvalds 		goto out;
54101da177e4SLinus Torvalds 	status = decode_read(&xdr, rqstp, res);
54111da177e4SLinus Torvalds 	if (!status)
54121da177e4SLinus Torvalds 		status = res->count;
54131da177e4SLinus Torvalds out:
54141da177e4SLinus Torvalds 	return status;
54151da177e4SLinus Torvalds }
54161da177e4SLinus Torvalds 
54171da177e4SLinus Torvalds /*
54181da177e4SLinus Torvalds  * Decode WRITE response
54191da177e4SLinus Torvalds  */
54208687b63aSAl Viro static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
54211da177e4SLinus Torvalds {
54221da177e4SLinus Torvalds 	struct xdr_stream xdr;
54231da177e4SLinus Torvalds 	struct compound_hdr hdr;
54241da177e4SLinus Torvalds 	int status;
54251da177e4SLinus Torvalds 
54261da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
54271da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54281da177e4SLinus Torvalds 	if (status)
54291da177e4SLinus Torvalds 		goto out;
54309b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
54319b7b9fccSAndy Adamson 	if (status)
54329b7b9fccSAndy Adamson 		goto out;
54331da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
54341da177e4SLinus Torvalds 	if (status)
54351da177e4SLinus Torvalds 		goto out;
54361da177e4SLinus Torvalds 	status = decode_write(&xdr, res);
54374f9838c7STrond Myklebust 	if (status)
54384f9838c7STrond Myklebust 		goto out;
543980e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
544080e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
54411da177e4SLinus Torvalds 	if (!status)
54421da177e4SLinus Torvalds 		status = res->count;
54431da177e4SLinus Torvalds out:
54441da177e4SLinus Torvalds 	return status;
54451da177e4SLinus Torvalds }
54461da177e4SLinus Torvalds 
54471da177e4SLinus Torvalds /*
54481da177e4SLinus Torvalds  * Decode COMMIT response
54491da177e4SLinus Torvalds  */
54508687b63aSAl Viro static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
54511da177e4SLinus Torvalds {
54521da177e4SLinus Torvalds 	struct xdr_stream xdr;
54531da177e4SLinus Torvalds 	struct compound_hdr hdr;
54541da177e4SLinus Torvalds 	int status;
54551da177e4SLinus Torvalds 
54561da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
54571da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54581da177e4SLinus Torvalds 	if (status)
54591da177e4SLinus Torvalds 		goto out;
54609b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
54619b7b9fccSAndy Adamson 	if (status)
54629b7b9fccSAndy Adamson 		goto out;
54631da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
54641da177e4SLinus Torvalds 	if (status)
54651da177e4SLinus Torvalds 		goto out;
54661da177e4SLinus Torvalds 	status = decode_commit(&xdr, res);
54674f9838c7STrond Myklebust 	if (status)
54684f9838c7STrond Myklebust 		goto out;
546980e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
547080e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
54711da177e4SLinus Torvalds out:
54721da177e4SLinus Torvalds 	return status;
54731da177e4SLinus Torvalds }
54741da177e4SLinus Torvalds 
54751da177e4SLinus Torvalds /*
54768b173218SRicardo Labiaga  * Decode FSINFO response
54771da177e4SLinus Torvalds  */
54783dda5e43SBenny Halevy static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
54793dda5e43SBenny Halevy 			       struct nfs4_fsinfo_res *res)
54801da177e4SLinus Torvalds {
54811da177e4SLinus Torvalds 	struct xdr_stream xdr;
54821da177e4SLinus Torvalds 	struct compound_hdr hdr;
54831da177e4SLinus Torvalds 	int status;
54841da177e4SLinus Torvalds 
54851da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
54861da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54871da177e4SLinus Torvalds 	if (!status)
54889b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
54899b7b9fccSAndy Adamson 	if (!status)
54901da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
54911da177e4SLinus Torvalds 	if (!status)
54923dda5e43SBenny Halevy 		status = decode_fsinfo(&xdr, res->fsinfo);
54931da177e4SLinus Torvalds 	return status;
54941da177e4SLinus Torvalds }
54951da177e4SLinus Torvalds 
54961da177e4SLinus Torvalds /*
54978b173218SRicardo Labiaga  * Decode PATHCONF response
54981da177e4SLinus Torvalds  */
5499d45b2989SBenny Halevy static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
5500d45b2989SBenny Halevy 				 struct nfs4_pathconf_res *res)
55011da177e4SLinus Torvalds {
55021da177e4SLinus Torvalds 	struct xdr_stream xdr;
55031da177e4SLinus Torvalds 	struct compound_hdr hdr;
55041da177e4SLinus Torvalds 	int status;
55051da177e4SLinus Torvalds 
55061da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55071da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55081da177e4SLinus Torvalds 	if (!status)
55099b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
55109b7b9fccSAndy Adamson 	if (!status)
55111da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
55121da177e4SLinus Torvalds 	if (!status)
5513d45b2989SBenny Halevy 		status = decode_pathconf(&xdr, res->pathconf);
55141da177e4SLinus Torvalds 	return status;
55151da177e4SLinus Torvalds }
55161da177e4SLinus Torvalds 
55171da177e4SLinus Torvalds /*
55188b173218SRicardo Labiaga  * Decode STATFS response
55191da177e4SLinus Torvalds  */
552024ad148aSBenny Halevy static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
552124ad148aSBenny Halevy 			       struct nfs4_statfs_res *res)
55221da177e4SLinus Torvalds {
55231da177e4SLinus Torvalds 	struct xdr_stream xdr;
55241da177e4SLinus Torvalds 	struct compound_hdr hdr;
55251da177e4SLinus Torvalds 	int status;
55261da177e4SLinus Torvalds 
55271da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55281da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55291da177e4SLinus Torvalds 	if (!status)
55309b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
55319b7b9fccSAndy Adamson 	if (!status)
55321da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
55331da177e4SLinus Torvalds 	if (!status)
553424ad148aSBenny Halevy 		status = decode_statfs(&xdr, res->fsstat);
55351da177e4SLinus Torvalds 	return status;
55361da177e4SLinus Torvalds }
55371da177e4SLinus Torvalds 
55381da177e4SLinus Torvalds /*
55398b173218SRicardo Labiaga  * Decode GETATTR_BITMAP response
55401da177e4SLinus Torvalds  */
55418687b63aSAl Viro static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
55421da177e4SLinus Torvalds {
55431da177e4SLinus Torvalds 	struct xdr_stream xdr;
55441da177e4SLinus Torvalds 	struct compound_hdr hdr;
55451da177e4SLinus Torvalds 	int status;
55461da177e4SLinus Torvalds 
55471da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55489b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
55499b7b9fccSAndy Adamson 	if (status)
55509b7b9fccSAndy Adamson 		goto out;
55519b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, req);
55529b7b9fccSAndy Adamson 	if (status)
55531da177e4SLinus Torvalds 		goto out;
55541da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
55551da177e4SLinus Torvalds 		goto out;
55561da177e4SLinus Torvalds 	status = decode_server_caps(&xdr, res);
55571da177e4SLinus Torvalds out:
55581da177e4SLinus Torvalds 	return status;
55591da177e4SLinus Torvalds }
55601da177e4SLinus Torvalds 
55611da177e4SLinus Torvalds /*
55621da177e4SLinus Torvalds  * Decode RENEW response
55631da177e4SLinus Torvalds  */
55648687b63aSAl Viro static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
55651da177e4SLinus Torvalds {
55661da177e4SLinus Torvalds 	struct xdr_stream xdr;
55671da177e4SLinus Torvalds 	struct compound_hdr hdr;
55681da177e4SLinus Torvalds 	int status;
55691da177e4SLinus Torvalds 
55701da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
55711da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55721da177e4SLinus Torvalds 	if (!status)
55731da177e4SLinus Torvalds 		status = decode_renew(&xdr);
55741da177e4SLinus Torvalds 	return status;
55751da177e4SLinus Torvalds }
55761da177e4SLinus Torvalds 
55771da177e4SLinus Torvalds /*
55788b173218SRicardo Labiaga  * Decode SETCLIENTID response
55791da177e4SLinus Torvalds  */
55808687b63aSAl Viro static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
5581bb8b27e5STrond Myklebust 		struct nfs4_setclientid_res *res)
55821da177e4SLinus Torvalds {
55831da177e4SLinus Torvalds 	struct xdr_stream xdr;
55841da177e4SLinus Torvalds 	struct compound_hdr hdr;
55851da177e4SLinus Torvalds 	int status;
55861da177e4SLinus Torvalds 
55871da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55881da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55891da177e4SLinus Torvalds 	if (!status)
5590bb8b27e5STrond Myklebust 		status = decode_setclientid(&xdr, res);
55911da177e4SLinus Torvalds 	return status;
55921da177e4SLinus Torvalds }
55931da177e4SLinus Torvalds 
55941da177e4SLinus Torvalds /*
55958b173218SRicardo Labiaga  * Decode SETCLIENTID_CONFIRM response
55961da177e4SLinus Torvalds  */
55978687b63aSAl Viro static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
55981da177e4SLinus Torvalds {
55991da177e4SLinus Torvalds 	struct xdr_stream xdr;
56001da177e4SLinus Torvalds 	struct compound_hdr hdr;
56011da177e4SLinus Torvalds 	int status;
56021da177e4SLinus Torvalds 
56031da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
56041da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
56051da177e4SLinus Torvalds 	if (!status)
56061da177e4SLinus Torvalds 		status = decode_setclientid_confirm(&xdr);
56071da177e4SLinus Torvalds 	if (!status)
56081da177e4SLinus Torvalds 		status = decode_putrootfh(&xdr);
56091da177e4SLinus Torvalds 	if (!status)
56101da177e4SLinus Torvalds 		status = decode_fsinfo(&xdr, fsinfo);
56111da177e4SLinus Torvalds 	return status;
56121da177e4SLinus Torvalds }
56131da177e4SLinus Torvalds 
56141da177e4SLinus Torvalds /*
56158b173218SRicardo Labiaga  * Decode DELEGRETURN response
56161da177e4SLinus Torvalds  */
56178687b63aSAl Viro static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
56181da177e4SLinus Torvalds {
56191da177e4SLinus Torvalds 	struct xdr_stream xdr;
56201da177e4SLinus Torvalds 	struct compound_hdr hdr;
56211da177e4SLinus Torvalds 	int status;
56221da177e4SLinus Torvalds 
56231da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
56241da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
56259b7b9fccSAndy Adamson 	if (status)
56269b7b9fccSAndy Adamson 		goto out;
56279b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
56289b7b9fccSAndy Adamson 	if (status)
5629fa178f29STrond Myklebust 		goto out;
56301da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
5631fa178f29STrond Myklebust 	if (status != 0)
5632fa178f29STrond Myklebust 		goto out;
56331da177e4SLinus Torvalds 	status = decode_delegreturn(&xdr);
5634556ae3bbSJeff Layton 	if (status != 0)
5635556ae3bbSJeff Layton 		goto out;
563680e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
563780e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
5638fa178f29STrond Myklebust out:
56391da177e4SLinus Torvalds 	return status;
56401da177e4SLinus Torvalds }
56411da177e4SLinus Torvalds 
5642683b57b4STrond Myklebust /*
56438b173218SRicardo Labiaga  * Decode FS_LOCATIONS response
5644683b57b4STrond Myklebust  */
564522958463SBenny Halevy static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
564622958463SBenny Halevy 				     struct nfs4_fs_locations_res *res)
5647683b57b4STrond Myklebust {
5648683b57b4STrond Myklebust 	struct xdr_stream xdr;
5649683b57b4STrond Myklebust 	struct compound_hdr hdr;
5650683b57b4STrond Myklebust 	int status;
5651683b57b4STrond Myklebust 
5652683b57b4STrond Myklebust 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5653683b57b4STrond Myklebust 	status = decode_compound_hdr(&xdr, &hdr);
56549b7b9fccSAndy Adamson 	if (status)
56559b7b9fccSAndy Adamson 		goto out;
56569b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, req);
56579b7b9fccSAndy Adamson 	if (status)
5658683b57b4STrond Myklebust 		goto out;
5659683b57b4STrond Myklebust 	if ((status = decode_putfh(&xdr)) != 0)
5660683b57b4STrond Myklebust 		goto out;
5661683b57b4STrond Myklebust 	if ((status = decode_lookup(&xdr)) != 0)
5662683b57b4STrond Myklebust 		goto out;
5663683b57b4STrond Myklebust 	xdr_enter_page(&xdr, PAGE_SIZE);
566422958463SBenny Halevy 	status = decode_getfattr(&xdr, &res->fs_locations->fattr,
566580e52aceSTrond Myklebust 				 res->fs_locations->server,
566680e52aceSTrond Myklebust 				 !RPC_IS_ASYNC(req->rq_task));
5667683b57b4STrond Myklebust out:
5668683b57b4STrond Myklebust 	return status;
5669683b57b4STrond Myklebust }
5670683b57b4STrond Myklebust 
567199fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
567299fe60d0SBenny Halevy /*
56738b173218SRicardo Labiaga  * Decode EXCHANGE_ID response
567499fe60d0SBenny Halevy  */
567599fe60d0SBenny Halevy static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
567699fe60d0SBenny Halevy 				    void *res)
567799fe60d0SBenny Halevy {
567899fe60d0SBenny Halevy 	struct xdr_stream xdr;
567999fe60d0SBenny Halevy 	struct compound_hdr hdr;
568099fe60d0SBenny Halevy 	int status;
568199fe60d0SBenny Halevy 
568299fe60d0SBenny Halevy 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
568399fe60d0SBenny Halevy 	status = decode_compound_hdr(&xdr, &hdr);
568499fe60d0SBenny Halevy 	if (!status)
568599fe60d0SBenny Halevy 		status = decode_exchange_id(&xdr, res);
568699fe60d0SBenny Halevy 	return status;
568799fe60d0SBenny Halevy }
56882050f0ccSAndy Adamson 
56892050f0ccSAndy Adamson /*
56908b173218SRicardo Labiaga  * Decode CREATE_SESSION response
5691fc931582SAndy Adamson  */
5692fc931582SAndy Adamson static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
5693fc931582SAndy Adamson 				       struct nfs41_create_session_res *res)
5694fc931582SAndy Adamson {
5695fc931582SAndy Adamson 	struct xdr_stream xdr;
5696fc931582SAndy Adamson 	struct compound_hdr hdr;
5697fc931582SAndy Adamson 	int status;
5698fc931582SAndy Adamson 
5699fc931582SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5700fc931582SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
5701fc931582SAndy Adamson 	if (!status)
5702fc931582SAndy Adamson 		status = decode_create_session(&xdr, res);
5703fc931582SAndy Adamson 	return status;
5704fc931582SAndy Adamson }
5705fc931582SAndy Adamson 
5706fc931582SAndy Adamson /*
57078b173218SRicardo Labiaga  * Decode DESTROY_SESSION response
57080f3e66c6SAndy Adamson  */
57090f3e66c6SAndy Adamson static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
57100f3e66c6SAndy Adamson 					void *dummy)
57110f3e66c6SAndy Adamson {
57120f3e66c6SAndy Adamson 	struct xdr_stream xdr;
57130f3e66c6SAndy Adamson 	struct compound_hdr hdr;
57140f3e66c6SAndy Adamson 	int status;
57150f3e66c6SAndy Adamson 
57160f3e66c6SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
57170f3e66c6SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
57180f3e66c6SAndy Adamson 	if (!status)
57190f3e66c6SAndy Adamson 		status = decode_destroy_session(&xdr, dummy);
57200f3e66c6SAndy Adamson 	return status;
57210f3e66c6SAndy Adamson }
57220f3e66c6SAndy Adamson 
57230f3e66c6SAndy Adamson /*
57248b173218SRicardo Labiaga  * Decode SEQUENCE response
5725fc01cea9SAndy Adamson  */
5726fc01cea9SAndy Adamson static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
5727fc01cea9SAndy Adamson 				 struct nfs4_sequence_res *res)
5728fc01cea9SAndy Adamson {
5729fc01cea9SAndy Adamson 	struct xdr_stream xdr;
5730fc01cea9SAndy Adamson 	struct compound_hdr hdr;
5731fc01cea9SAndy Adamson 	int status;
5732fc01cea9SAndy Adamson 
5733fc01cea9SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5734fc01cea9SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
5735fc01cea9SAndy Adamson 	if (!status)
5736fc01cea9SAndy Adamson 		status = decode_sequence(&xdr, res, rqstp);
5737fc01cea9SAndy Adamson 	return status;
5738fc01cea9SAndy Adamson }
5739fc01cea9SAndy Adamson 
5740fc01cea9SAndy Adamson /*
57418b173218SRicardo Labiaga  * Decode GET_LEASE_TIME response
57422050f0ccSAndy Adamson  */
57432050f0ccSAndy Adamson static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
57442050f0ccSAndy Adamson 				       struct nfs4_get_lease_time_res *res)
57452050f0ccSAndy Adamson {
57462050f0ccSAndy Adamson 	struct xdr_stream xdr;
57472050f0ccSAndy Adamson 	struct compound_hdr hdr;
57482050f0ccSAndy Adamson 	int status;
57492050f0ccSAndy Adamson 
57502050f0ccSAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
57512050f0ccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
57522050f0ccSAndy Adamson 	if (!status)
57532050f0ccSAndy Adamson 		status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
57542050f0ccSAndy Adamson 	if (!status)
57552050f0ccSAndy Adamson 		status = decode_putrootfh(&xdr);
57562050f0ccSAndy Adamson 	if (!status)
57572050f0ccSAndy Adamson 		status = decode_fsinfo(&xdr, res->lr_fsinfo);
57582050f0ccSAndy Adamson 	return status;
57592050f0ccSAndy Adamson }
576018019753SRicardo Labiaga 
576118019753SRicardo Labiaga /*
576218019753SRicardo Labiaga  * Decode RECLAIM_COMPLETE response
576318019753SRicardo Labiaga  */
576418019753SRicardo Labiaga static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
576518019753SRicardo Labiaga 					 struct nfs41_reclaim_complete_res *res)
576618019753SRicardo Labiaga {
576718019753SRicardo Labiaga 	struct xdr_stream xdr;
576818019753SRicardo Labiaga 	struct compound_hdr hdr;
576918019753SRicardo Labiaga 	int status;
577018019753SRicardo Labiaga 
577118019753SRicardo Labiaga 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
577218019753SRicardo Labiaga 	status = decode_compound_hdr(&xdr, &hdr);
577318019753SRicardo Labiaga 	if (!status)
577418019753SRicardo Labiaga 		status = decode_sequence(&xdr, &res->seq_res, rqstp);
577518019753SRicardo Labiaga 	if (!status)
577618019753SRicardo Labiaga 		status = decode_reclaim_complete(&xdr, (void *)NULL);
577718019753SRicardo Labiaga 	return status;
577818019753SRicardo Labiaga }
577999fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
578099fe60d0SBenny Halevy 
578182f2e547SBryan Schumaker __be32 *nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
578282f2e547SBryan Schumaker 			   struct nfs_server *server, int plus)
57831da177e4SLinus Torvalds {
57841da177e4SLinus Torvalds 	uint32_t bitmap[2] = {0};
57851da177e4SLinus Torvalds 	uint32_t len;
5786babddc72SBryan Schumaker 	__be32 *p = xdr_inline_decode(xdr, 4);
5787babddc72SBryan Schumaker 	if (unlikely(!p))
5788babddc72SBryan Schumaker 		goto out_overflow;
5789babddc72SBryan Schumaker 	if (!ntohl(*p++)) {
5790babddc72SBryan Schumaker 		p = xdr_inline_decode(xdr, 4);
5791babddc72SBryan Schumaker 		if (unlikely(!p))
5792babddc72SBryan Schumaker 			goto out_overflow;
5793babddc72SBryan Schumaker 		if (!ntohl(*p++))
57941da177e4SLinus Torvalds 			return ERR_PTR(-EAGAIN);
57951da177e4SLinus Torvalds 		entry->eof = 1;
57961da177e4SLinus Torvalds 		return ERR_PTR(-EBADCOOKIE);
57971da177e4SLinus Torvalds 	}
57981da177e4SLinus Torvalds 
5799babddc72SBryan Schumaker 	p = xdr_inline_decode(xdr, 12);
5800babddc72SBryan Schumaker 	if (unlikely(!p))
5801babddc72SBryan Schumaker 		goto out_overflow;
58021da177e4SLinus Torvalds 	entry->prev_cookie = entry->cookie;
58031da177e4SLinus Torvalds 	p = xdr_decode_hyper(p, &entry->cookie);
58041da177e4SLinus Torvalds 	entry->len = ntohl(*p++);
5805babddc72SBryan Schumaker 
58069af8c222STrond Myklebust 	p = xdr_inline_decode(xdr, entry->len);
5807babddc72SBryan Schumaker 	if (unlikely(!p))
5808babddc72SBryan Schumaker 		goto out_overflow;
58091da177e4SLinus Torvalds 	entry->name = (const char *) p;
58101da177e4SLinus Torvalds 
58111da177e4SLinus Torvalds 	/*
58121da177e4SLinus Torvalds 	 * In case the server doesn't return an inode number,
58131da177e4SLinus Torvalds 	 * we fake one here.  (We don't use inode number 0,
58141da177e4SLinus Torvalds 	 * since glibc seems to choke on it...)
58151da177e4SLinus Torvalds 	 */
58161da177e4SLinus Torvalds 	entry->ino = 1;
58174f082222STrond Myklebust 	entry->fattr->valid = 0;
58181da177e4SLinus Torvalds 
58199af8c222STrond Myklebust 	if (decode_attr_bitmap(xdr, bitmap) < 0)
5820babddc72SBryan Schumaker 		goto out_overflow;
58219af8c222STrond Myklebust 
58229af8c222STrond Myklebust 	if (decode_attr_length(xdr, &len, &p) < 0)
5823babddc72SBryan Schumaker 		goto out_overflow;
58249af8c222STrond Myklebust 
582582f2e547SBryan Schumaker 	if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh, server, 1) < 0)
5826babddc72SBryan Schumaker 		goto out_overflow;
582782f2e547SBryan Schumaker 	if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
582882f2e547SBryan Schumaker 		entry->ino = entry->fattr->fileid;
58299af8c222STrond Myklebust 
58309af8c222STrond Myklebust 	if (verify_attr_len(xdr, p, len) < 0)
58319af8c222STrond Myklebust 		goto out_overflow;
58321da177e4SLinus Torvalds 
5833babddc72SBryan Schumaker 	p = xdr_inline_peek(xdr, 8);
5834babddc72SBryan Schumaker 	if (p != NULL)
58351da177e4SLinus Torvalds 		entry->eof = !p[0] && p[1];
5836babddc72SBryan Schumaker 	else
5837babddc72SBryan Schumaker 		entry->eof = 0;
5838babddc72SBryan Schumaker 
58391da177e4SLinus Torvalds 	return p;
5840babddc72SBryan Schumaker 
5841babddc72SBryan Schumaker out_overflow:
5842babddc72SBryan Schumaker 	print_overflow_msg(__func__, xdr);
5843babddc72SBryan Schumaker 	return ERR_PTR(-EIO);
58441da177e4SLinus Torvalds }
58451da177e4SLinus Torvalds 
58461da177e4SLinus Torvalds /*
58471da177e4SLinus Torvalds  * We need to translate between nfs status return values and
58481da177e4SLinus Torvalds  * the local errno values which may not be the same.
58491da177e4SLinus Torvalds  */
58501da177e4SLinus Torvalds static struct {
58511da177e4SLinus Torvalds 	int stat;
58521da177e4SLinus Torvalds 	int errno;
58531da177e4SLinus Torvalds } nfs_errtbl[] = {
58541da177e4SLinus Torvalds 	{ NFS4_OK,		0		},
5855856dff3dSBenny Halevy 	{ NFS4ERR_PERM,		-EPERM		},
5856856dff3dSBenny Halevy 	{ NFS4ERR_NOENT,	-ENOENT		},
5857856dff3dSBenny Halevy 	{ NFS4ERR_IO,		-errno_NFSERR_IO},
5858856dff3dSBenny Halevy 	{ NFS4ERR_NXIO,		-ENXIO		},
5859856dff3dSBenny Halevy 	{ NFS4ERR_ACCESS,	-EACCES		},
5860856dff3dSBenny Halevy 	{ NFS4ERR_EXIST,	-EEXIST		},
5861856dff3dSBenny Halevy 	{ NFS4ERR_XDEV,		-EXDEV		},
5862856dff3dSBenny Halevy 	{ NFS4ERR_NOTDIR,	-ENOTDIR	},
5863856dff3dSBenny Halevy 	{ NFS4ERR_ISDIR,	-EISDIR		},
5864856dff3dSBenny Halevy 	{ NFS4ERR_INVAL,	-EINVAL		},
5865856dff3dSBenny Halevy 	{ NFS4ERR_FBIG,		-EFBIG		},
5866856dff3dSBenny Halevy 	{ NFS4ERR_NOSPC,	-ENOSPC		},
5867856dff3dSBenny Halevy 	{ NFS4ERR_ROFS,		-EROFS		},
5868856dff3dSBenny Halevy 	{ NFS4ERR_MLINK,	-EMLINK		},
5869856dff3dSBenny Halevy 	{ NFS4ERR_NAMETOOLONG,	-ENAMETOOLONG	},
5870856dff3dSBenny Halevy 	{ NFS4ERR_NOTEMPTY,	-ENOTEMPTY	},
5871856dff3dSBenny Halevy 	{ NFS4ERR_DQUOT,	-EDQUOT		},
5872856dff3dSBenny Halevy 	{ NFS4ERR_STALE,	-ESTALE		},
5873856dff3dSBenny Halevy 	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
5874856dff3dSBenny Halevy 	{ NFS4ERR_BADOWNER,	-EINVAL		},
5875856dff3dSBenny Halevy 	{ NFS4ERR_BADNAME,	-EINVAL		},
5876856dff3dSBenny Halevy 	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
5877856dff3dSBenny Halevy 	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
5878856dff3dSBenny Halevy 	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
5879fdcb4577STrond Myklebust 	{ NFS4ERR_SERVERFAULT,	-EREMOTEIO	},
5880856dff3dSBenny Halevy 	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
5881856dff3dSBenny Halevy 	{ NFS4ERR_LOCKED,	-EAGAIN		},
5882856dff3dSBenny Halevy 	{ NFS4ERR_SYMLINK,	-ELOOP		},
5883856dff3dSBenny Halevy 	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
5884856dff3dSBenny Halevy 	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
5885856dff3dSBenny Halevy 	{ NFS4ERR_WRONGSEC,	-EPERM		}, /* FIXME: this needs
58861da177e4SLinus Torvalds 						    * to be handled by a
58871da177e4SLinus Torvalds 						    * middle-layer.
58881da177e4SLinus Torvalds 						    */
5889856dff3dSBenny Halevy 	{ -1,			-EIO		}
58901da177e4SLinus Torvalds };
58911da177e4SLinus Torvalds 
58921da177e4SLinus Torvalds /*
58931da177e4SLinus Torvalds  * Convert an NFS error code to a local one.
58941da177e4SLinus Torvalds  * This one is used jointly by NFSv2 and NFSv3.
58951da177e4SLinus Torvalds  */
58961da177e4SLinus Torvalds static int
58970a8ea437SDavid Howells nfs4_stat_to_errno(int stat)
58981da177e4SLinus Torvalds {
58991da177e4SLinus Torvalds 	int i;
59001da177e4SLinus Torvalds 	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
59011da177e4SLinus Torvalds 		if (nfs_errtbl[i].stat == stat)
59021da177e4SLinus Torvalds 			return nfs_errtbl[i].errno;
59031da177e4SLinus Torvalds 	}
59041da177e4SLinus Torvalds 	if (stat <= 10000 || stat > 10100) {
59051da177e4SLinus Torvalds 		/* The server is looney tunes. */
5906fdcb4577STrond Myklebust 		return -EREMOTEIO;
59071da177e4SLinus Torvalds 	}
59081da177e4SLinus Torvalds 	/* If we cannot translate the error, the recovery routines should
59091da177e4SLinus Torvalds 	 * handle it.
59101da177e4SLinus Torvalds 	 * Note: remaining NFSv4 error codes have values > 10000, so should
59111da177e4SLinus Torvalds 	 * not conflict with native Linux error codes.
59121da177e4SLinus Torvalds 	 */
5913856dff3dSBenny Halevy 	return -stat;
59141da177e4SLinus Torvalds }
59151da177e4SLinus Torvalds 
59161da177e4SLinus Torvalds #define PROC(proc, argtype, restype)				\
59171da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = {					\
59181da177e4SLinus Torvalds 	.p_proc   = NFSPROC4_COMPOUND,				\
59191da177e4SLinus Torvalds 	.p_encode = (kxdrproc_t) nfs4_xdr_##argtype,		\
59201da177e4SLinus Torvalds 	.p_decode = (kxdrproc_t) nfs4_xdr_##restype,		\
59212bea90d4SChuck Lever 	.p_arglen = NFS4_##argtype##_sz,			\
59222bea90d4SChuck Lever 	.p_replen = NFS4_##restype##_sz,			\
5923cc0175c1SChuck Lever 	.p_statidx = NFSPROC4_CLNT_##proc,			\
5924cc0175c1SChuck Lever 	.p_name   = #proc,					\
59251da177e4SLinus Torvalds }
59261da177e4SLinus Torvalds 
59271da177e4SLinus Torvalds struct rpc_procinfo	nfs4_procedures[] = {
59281da177e4SLinus Torvalds   PROC(READ,		enc_read,	dec_read),
59291da177e4SLinus Torvalds   PROC(WRITE,		enc_write,	dec_write),
59301da177e4SLinus Torvalds   PROC(COMMIT,		enc_commit,	dec_commit),
59311da177e4SLinus Torvalds   PROC(OPEN,		enc_open,	dec_open),
59321da177e4SLinus Torvalds   PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
59331da177e4SLinus Torvalds   PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
59341da177e4SLinus Torvalds   PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
59351da177e4SLinus Torvalds   PROC(CLOSE,		enc_close,	dec_close),
59361da177e4SLinus Torvalds   PROC(SETATTR,		enc_setattr,	dec_setattr),
59371da177e4SLinus Torvalds   PROC(FSINFO,		enc_fsinfo,	dec_fsinfo),
59381da177e4SLinus Torvalds   PROC(RENEW,		enc_renew,	dec_renew),
59391da177e4SLinus Torvalds   PROC(SETCLIENTID,	enc_setclientid,	dec_setclientid),
59401da177e4SLinus Torvalds   PROC(SETCLIENTID_CONFIRM,	enc_setclientid_confirm,	dec_setclientid_confirm),
59411da177e4SLinus Torvalds   PROC(LOCK,            enc_lock,       dec_lock),
59421da177e4SLinus Torvalds   PROC(LOCKT,           enc_lockt,      dec_lockt),
59431da177e4SLinus Torvalds   PROC(LOCKU,           enc_locku,      dec_locku),
59441da177e4SLinus Torvalds   PROC(ACCESS,		enc_access,	dec_access),
59451da177e4SLinus Torvalds   PROC(GETATTR,		enc_getattr,	dec_getattr),
59461da177e4SLinus Torvalds   PROC(LOOKUP,		enc_lookup,	dec_lookup),
59471da177e4SLinus Torvalds   PROC(LOOKUP_ROOT,	enc_lookup_root,	dec_lookup_root),
59481da177e4SLinus Torvalds   PROC(REMOVE,		enc_remove,	dec_remove),
59491da177e4SLinus Torvalds   PROC(RENAME,		enc_rename,	dec_rename),
59501da177e4SLinus Torvalds   PROC(LINK,		enc_link,	dec_link),
59511da177e4SLinus Torvalds   PROC(SYMLINK,		enc_symlink,	dec_symlink),
59521da177e4SLinus Torvalds   PROC(CREATE,		enc_create,	dec_create),
59531da177e4SLinus Torvalds   PROC(PATHCONF,	enc_pathconf,	dec_pathconf),
59541da177e4SLinus Torvalds   PROC(STATFS,		enc_statfs,	dec_statfs),
59551da177e4SLinus Torvalds   PROC(READLINK,	enc_readlink,	dec_readlink),
59561da177e4SLinus Torvalds   PROC(READDIR,		enc_readdir,	dec_readdir),
59571da177e4SLinus Torvalds   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
59581da177e4SLinus Torvalds   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
5959029d105eSJ. Bruce Fields   PROC(GETACL,		enc_getacl,	dec_getacl),
596023ec6965SJ. Bruce Fields   PROC(SETACL,		enc_setacl,	dec_setacl),
5961683b57b4STrond Myklebust   PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
5962d3c7b7ccSTrond Myklebust   PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
596399fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
596499fe60d0SBenny Halevy   PROC(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
5965fc931582SAndy Adamson   PROC(CREATE_SESSION,	enc_create_session,	dec_create_session),
59660f3e66c6SAndy Adamson   PROC(DESTROY_SESSION,	enc_destroy_session,	dec_destroy_session),
5967fc01cea9SAndy Adamson   PROC(SEQUENCE,	enc_sequence,	dec_sequence),
59682050f0ccSAndy Adamson   PROC(GET_LEASE_TIME,	enc_get_lease_time,	dec_get_lease_time),
596918019753SRicardo Labiaga   PROC(RECLAIM_COMPLETE, enc_reclaim_complete,  dec_reclaim_complete),
597099fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
59711da177e4SLinus Torvalds };
59721da177e4SLinus Torvalds 
59731da177e4SLinus Torvalds struct rpc_version		nfs_version4 = {
59741da177e4SLinus Torvalds 	.number			= 4,
5975e8c96f8cSTobias Klauser 	.nrprocs		= ARRAY_SIZE(nfs4_procedures),
59761da177e4SLinus Torvalds 	.procs			= nfs4_procedures
59771da177e4SLinus Torvalds };
59781da177e4SLinus Torvalds 
59791da177e4SLinus Torvalds /*
59801da177e4SLinus Torvalds  * Local variables:
59811da177e4SLinus Torvalds  *  c-basic-offset: 8
59821da177e4SLinus Torvalds  * End:
59831da177e4SLinus Torvalds  */
5984