xref: /openbmc/linux/fs/nfs/nfs4xdr.c (revision e8582a8b)
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) {
8197539bbabSDavid Howells 		owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
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) {
8317539bbabSDavid Howells 		owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
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 {
138897d312d0SManoj Naik 	uint32_t attrs[2] = {
138997d312d0SManoj Naik 		FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
139097d312d0SManoj Naik 		FATTR4_WORD1_MOUNTED_ON_FILEID,
139197d312d0SManoj Naik 	};
13928687b63aSAl Viro 	__be32 *p;
13931da177e4SLinus Torvalds 
139413c65ce9SBenny Halevy 	p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
1395e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_READDIR);
1396b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, readdir->cookie);
139793f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
1398e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(readdir->count >> 1);  /* We're not doing readdirplus */
1399e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(readdir->count);
1400e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(2);
140197d312d0SManoj Naik 	/* Switch to mounted_on_fileid if the server supports it */
140297d312d0SManoj Naik 	if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
140397d312d0SManoj Naik 		attrs[0] &= ~FATTR4_WORD0_FILEID;
140497d312d0SManoj Naik 	else
140597d312d0SManoj Naik 		attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
1406e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
140734558513SBenny Halevy 	*p = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
1408d017931cSAndy Adamson 	hdr->nops++;
1409dadf0c27SBenny Halevy 	hdr->replen += decode_readdir_maxsz;
141044109241SFred Isaman 	dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
141144109241SFred Isaman 			__func__,
1412eadf4598STrond Myklebust 			(unsigned long long)readdir->cookie,
1413eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[0],
1414eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[1],
1415eadf4598STrond Myklebust 			attrs[0] & readdir->bitmask[0],
1416eadf4598STrond Myklebust 			attrs[1] & readdir->bitmask[1]);
14171da177e4SLinus Torvalds }
14181da177e4SLinus Torvalds 
1419cf8cdbe5SAndy Adamson static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
14201da177e4SLinus Torvalds {
14218687b63aSAl Viro 	__be32 *p;
14221da177e4SLinus Torvalds 
142313c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
142434558513SBenny Halevy 	*p = cpu_to_be32(OP_READLINK);
1425d017931cSAndy Adamson 	hdr->nops++;
1426dadf0c27SBenny Halevy 	hdr->replen += decode_readlink_maxsz;
14271da177e4SLinus Torvalds }
14281da177e4SLinus Torvalds 
1429cf8cdbe5SAndy Adamson static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
14301da177e4SLinus Torvalds {
14318687b63aSAl Viro 	__be32 *p;
14321da177e4SLinus Torvalds 
143313c65ce9SBenny Halevy 	p = reserve_space(xdr, 8 + name->len);
1434e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_REMOVE);
1435811652bdSBenny Halevy 	xdr_encode_opaque(p, name->name, name->len);
1436d017931cSAndy Adamson 	hdr->nops++;
1437dadf0c27SBenny Halevy 	hdr->replen += decode_remove_maxsz;
14381da177e4SLinus Torvalds }
14391da177e4SLinus Torvalds 
1440cf8cdbe5SAndy Adamson static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
14411da177e4SLinus Torvalds {
14428687b63aSAl Viro 	__be32 *p;
14431da177e4SLinus Torvalds 
1444811652bdSBenny Halevy 	p = reserve_space(xdr, 4);
1445811652bdSBenny Halevy 	*p = cpu_to_be32(OP_RENAME);
1446811652bdSBenny Halevy 	encode_string(xdr, oldname->len, oldname->name);
1447811652bdSBenny Halevy 	encode_string(xdr, newname->len, newname->name);
1448d017931cSAndy Adamson 	hdr->nops++;
1449dadf0c27SBenny Halevy 	hdr->replen += decode_rename_maxsz;
14501da177e4SLinus Torvalds }
14511da177e4SLinus Torvalds 
1452cf8cdbe5SAndy Adamson static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr)
14531da177e4SLinus Torvalds {
14548687b63aSAl Viro 	__be32 *p;
14551da177e4SLinus Torvalds 
145613c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
1457e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_RENEW);
145834558513SBenny Halevy 	xdr_encode_hyper(p, client_stateid->cl_clientid);
1459d017931cSAndy Adamson 	hdr->nops++;
1460dadf0c27SBenny Halevy 	hdr->replen += decode_renew_maxsz;
14611da177e4SLinus Torvalds }
14621da177e4SLinus Torvalds 
1463cf8cdbe5SAndy Adamson static void
1464d017931cSAndy Adamson encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
146556ae19f3STrond Myklebust {
14668687b63aSAl Viro 	__be32 *p;
146756ae19f3STrond Myklebust 
146813c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
146934558513SBenny Halevy 	*p = cpu_to_be32(OP_RESTOREFH);
1470d017931cSAndy Adamson 	hdr->nops++;
1471dadf0c27SBenny Halevy 	hdr->replen += decode_restorefh_maxsz;
147256ae19f3STrond Myklebust }
147356ae19f3STrond Myklebust 
147456ae19f3STrond Myklebust static int
1475d017931cSAndy Adamson encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
147623ec6965SJ. Bruce Fields {
14778687b63aSAl Viro 	__be32 *p;
147823ec6965SJ. Bruce Fields 
147913c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
1480e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETATTR);
148134558513SBenny Halevy 	xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
148213c65ce9SBenny Halevy 	p = reserve_space(xdr, 2*4);
1483e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(1);
148434558513SBenny Halevy 	*p = cpu_to_be32(FATTR4_WORD0_ACL);
148523ec6965SJ. Bruce Fields 	if (arg->acl_len % 4)
148623ec6965SJ. Bruce Fields 		return -EINVAL;
148713c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
148834558513SBenny Halevy 	*p = cpu_to_be32(arg->acl_len);
148923ec6965SJ. Bruce Fields 	xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
1490d017931cSAndy Adamson 	hdr->nops++;
1491dadf0c27SBenny Halevy 	hdr->replen += decode_setacl_maxsz;
149223ec6965SJ. Bruce Fields 	return 0;
149323ec6965SJ. Bruce Fields }
149423ec6965SJ. Bruce Fields 
1495cf8cdbe5SAndy Adamson static void
1496d017931cSAndy Adamson encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
14971da177e4SLinus Torvalds {
14988687b63aSAl Viro 	__be32 *p;
14991da177e4SLinus Torvalds 
150013c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
150134558513SBenny Halevy 	*p = cpu_to_be32(OP_SAVEFH);
1502d017931cSAndy Adamson 	hdr->nops++;
1503dadf0c27SBenny Halevy 	hdr->replen += decode_savefh_maxsz;
15041da177e4SLinus Torvalds }
15051da177e4SLinus Torvalds 
1506cf8cdbe5SAndy Adamson static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
15071da177e4SLinus Torvalds {
15088687b63aSAl Viro 	__be32 *p;
15091da177e4SLinus Torvalds 
151013c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
1511e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETATTR);
151234558513SBenny Halevy 	xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
1513d017931cSAndy Adamson 	hdr->nops++;
1514dadf0c27SBenny Halevy 	hdr->replen += decode_setattr_maxsz;
1515cf8cdbe5SAndy Adamson 	encode_attrs(xdr, arg->iap, server);
15161da177e4SLinus Torvalds }
15171da177e4SLinus Torvalds 
1518cf8cdbe5SAndy Adamson static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
15191da177e4SLinus Torvalds {
15208687b63aSAl Viro 	__be32 *p;
15211da177e4SLinus Torvalds 
152213c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE);
1523e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETCLIENTID);
152434558513SBenny Halevy 	xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE);
15251da177e4SLinus Torvalds 
15261da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
152713c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
152834558513SBenny Halevy 	*p = cpu_to_be32(setclientid->sc_prog);
15291da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
15301da177e4SLinus Torvalds 	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
153113c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
153234558513SBenny Halevy 	*p = cpu_to_be32(setclientid->sc_cb_ident);
1533d017931cSAndy Adamson 	hdr->nops++;
1534dadf0c27SBenny Halevy 	hdr->replen += decode_setclientid_maxsz;
15351da177e4SLinus Torvalds }
15361da177e4SLinus Torvalds 
1537bb8b27e5STrond Myklebust static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr)
15381da177e4SLinus Torvalds {
15398687b63aSAl Viro 	__be32 *p;
15401da177e4SLinus Torvalds 
154113c65ce9SBenny Halevy 	p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE);
1542e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM);
1543bb8b27e5STrond Myklebust 	p = xdr_encode_hyper(p, arg->clientid);
1544bb8b27e5STrond Myklebust 	xdr_encode_opaque_fixed(p, arg->confirm.data, NFS4_VERIFIER_SIZE);
1545d017931cSAndy Adamson 	hdr->nops++;
1546dadf0c27SBenny Halevy 	hdr->replen += decode_setclientid_confirm_maxsz;
15471da177e4SLinus Torvalds }
15481da177e4SLinus Torvalds 
1549cf8cdbe5SAndy Adamson static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
15501da177e4SLinus Torvalds {
15518687b63aSAl Viro 	__be32 *p;
15521da177e4SLinus Torvalds 
155313c65ce9SBenny Halevy 	p = reserve_space(xdr, 4);
155434558513SBenny Halevy 	*p = cpu_to_be32(OP_WRITE);
15551da177e4SLinus Torvalds 
1556f11ac8dbSTrond Myklebust 	encode_stateid(xdr, args->context, args->lock_context);
15571da177e4SLinus Torvalds 
155813c65ce9SBenny Halevy 	p = reserve_space(xdr, 16);
1559b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, args->offset);
1560e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->stable);
156134558513SBenny Halevy 	*p = cpu_to_be32(args->count);
15621da177e4SLinus Torvalds 
15631da177e4SLinus Torvalds 	xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1564d017931cSAndy Adamson 	hdr->nops++;
1565dadf0c27SBenny Halevy 	hdr->replen += decode_write_maxsz;
15661da177e4SLinus Torvalds }
15671da177e4SLinus Torvalds 
1568cf8cdbe5SAndy Adamson static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
15691da177e4SLinus Torvalds {
15708687b63aSAl Viro 	__be32 *p;
15711da177e4SLinus Torvalds 
157213c65ce9SBenny Halevy 	p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
15731da177e4SLinus Torvalds 
1574e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_DELEGRETURN);
157534558513SBenny Halevy 	xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
1576d017931cSAndy Adamson 	hdr->nops++;
1577dadf0c27SBenny Halevy 	hdr->replen += decode_delegreturn_maxsz;
15781da177e4SLinus Torvalds }
15799b7b9fccSAndy Adamson 
158099fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
15819b7b9fccSAndy Adamson /* NFSv4.1 operations */
158299fe60d0SBenny Halevy static void encode_exchange_id(struct xdr_stream *xdr,
158399fe60d0SBenny Halevy 			       struct nfs41_exchange_id_args *args,
158499fe60d0SBenny Halevy 			       struct compound_hdr *hdr)
158599fe60d0SBenny Halevy {
158699fe60d0SBenny Halevy 	__be32 *p;
158799fe60d0SBenny Halevy 
158813c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + sizeof(args->verifier->data));
1589e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_EXCHANGE_ID);
159034558513SBenny Halevy 	xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data));
159199fe60d0SBenny Halevy 
159299fe60d0SBenny Halevy 	encode_string(xdr, args->id_len, args->id);
159399fe60d0SBenny Halevy 
159413c65ce9SBenny Halevy 	p = reserve_space(xdr, 12);
1595e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->flags);
1596e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);	/* zero length state_protect4_a */
159734558513SBenny Halevy 	*p = cpu_to_be32(0);	/* zero length implementation id array */
159899fe60d0SBenny Halevy 	hdr->nops++;
159999fe60d0SBenny Halevy 	hdr->replen += decode_exchange_id_maxsz;
160099fe60d0SBenny Halevy }
1601fc931582SAndy Adamson 
1602fc931582SAndy Adamson static void encode_create_session(struct xdr_stream *xdr,
1603fc931582SAndy Adamson 				  struct nfs41_create_session_args *args,
1604fc931582SAndy Adamson 				  struct compound_hdr *hdr)
1605fc931582SAndy Adamson {
1606fc931582SAndy Adamson 	__be32 *p;
1607fc931582SAndy Adamson 	char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
1608fc931582SAndy Adamson 	uint32_t len;
1609fc931582SAndy Adamson 	struct nfs_client *clp = args->client;
16108e0d46e1SMike Sager 	u32 max_resp_sz_cached;
16118e0d46e1SMike Sager 
16128e0d46e1SMike Sager 	/*
16138e0d46e1SMike Sager 	 * Assumes OPEN is the biggest non-idempotent compound.
16148e0d46e1SMike Sager 	 * 2 is the verifier.
16158e0d46e1SMike Sager 	 */
16168e0d46e1SMike Sager 	max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
16178e0d46e1SMike Sager 			      RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
1618fc931582SAndy Adamson 
1619fc931582SAndy Adamson 	len = scnprintf(machine_name, sizeof(machine_name), "%s",
1620fc931582SAndy Adamson 			clp->cl_ipaddr);
162142edd698SBenny Halevy 
162213c65ce9SBenny Halevy 	p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12);
1623e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_CREATE_SESSION);
1624b95be5a9SBenny Halevy 	p = xdr_encode_hyper(p, clp->cl_ex_clid);
1625e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(clp->cl_seqid);			/*Sequence id */
1626e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->flags);			/*flags */
1627fc931582SAndy Adamson 
1628fc931582SAndy Adamson 	/* Fore Channel */
1629e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.headerpadsz);	/* header padding size */
1630e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz);	/* max req size */
1631e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz);	/* max resp size */
16328e0d46e1SMike Sager 	*p++ = cpu_to_be32(max_resp_sz_cached);		/* Max resp sz cached */
1633e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_ops);	/* max operations */
1634e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.max_reqs);	/* max requests */
1635e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
1636fc931582SAndy Adamson 
1637fc931582SAndy Adamson 	/* Back Channel */
1638e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->fc_attrs.headerpadsz);	/* header padding size */
1639e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz);	/* max req size */
1640e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz);	/* max resp size */
1641e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached);	/* Max resp sz cached */
1642e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_ops);	/* max operations */
1643e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->bc_attrs.max_reqs);	/* max requests */
1644e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
1645fc931582SAndy Adamson 
1646e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->cb_program);		/* cb_program */
1647e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(1);
1648e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(RPC_AUTH_UNIX);			/* auth_sys */
1649fc931582SAndy Adamson 
1650fc931582SAndy Adamson 	/* authsys_parms rfc1831 */
1651e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec);	/* stamp */
1652811652bdSBenny Halevy 	p = xdr_encode_opaque(p, machine_name, len);
1653e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* UID */
1654e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(0);				/* GID */
165534558513SBenny Halevy 	*p = cpu_to_be32(0);				/* No more gids */
1656fc931582SAndy Adamson 	hdr->nops++;
1657fc931582SAndy Adamson 	hdr->replen += decode_create_session_maxsz;
1658fc931582SAndy Adamson }
16590f3e66c6SAndy Adamson 
16600f3e66c6SAndy Adamson static void encode_destroy_session(struct xdr_stream *xdr,
16610f3e66c6SAndy Adamson 				   struct nfs4_session *session,
16620f3e66c6SAndy Adamson 				   struct compound_hdr *hdr)
16630f3e66c6SAndy Adamson {
16640f3e66c6SAndy Adamson 	__be32 *p;
166513c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN);
1666e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_DESTROY_SESSION);
166734558513SBenny Halevy 	xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
16680f3e66c6SAndy Adamson 	hdr->nops++;
16690f3e66c6SAndy Adamson 	hdr->replen += decode_destroy_session_maxsz;
16700f3e66c6SAndy Adamson }
167118019753SRicardo Labiaga 
167218019753SRicardo Labiaga static void encode_reclaim_complete(struct xdr_stream *xdr,
167318019753SRicardo Labiaga 				    struct nfs41_reclaim_complete_args *args,
167418019753SRicardo Labiaga 				    struct compound_hdr *hdr)
167518019753SRicardo Labiaga {
167618019753SRicardo Labiaga 	__be32 *p;
167718019753SRicardo Labiaga 
167818019753SRicardo Labiaga 	p = reserve_space(xdr, 8);
167918019753SRicardo Labiaga 	*p++ = cpu_to_be32(OP_RECLAIM_COMPLETE);
168018019753SRicardo Labiaga 	*p++ = cpu_to_be32(args->one_fs);
168118019753SRicardo Labiaga 	hdr->nops++;
168218019753SRicardo Labiaga 	hdr->replen += decode_reclaim_complete_maxsz;
168318019753SRicardo Labiaga }
168499fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
168599fe60d0SBenny Halevy 
16869b7b9fccSAndy Adamson static void encode_sequence(struct xdr_stream *xdr,
16879b7b9fccSAndy Adamson 			    const struct nfs4_sequence_args *args,
16889b7b9fccSAndy Adamson 			    struct compound_hdr *hdr)
16899b7b9fccSAndy Adamson {
16909b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1)
16919b7b9fccSAndy Adamson 	struct nfs4_session *session = args->sa_session;
1692fc01cea9SAndy Adamson 	struct nfs4_slot_table *tp;
1693fc01cea9SAndy Adamson 	struct nfs4_slot *slot;
1694fc01cea9SAndy Adamson 	__be32 *p;
16959b7b9fccSAndy Adamson 
16969b7b9fccSAndy Adamson 	if (!session)
16979b7b9fccSAndy Adamson 		return;
16989b7b9fccSAndy Adamson 
1699fc01cea9SAndy Adamson 	tp = &session->fc_slot_table;
1700fc01cea9SAndy Adamson 
1701fc01cea9SAndy Adamson 	WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
1702fc01cea9SAndy Adamson 	slot = tp->slots + args->sa_slotid;
1703fc01cea9SAndy Adamson 
170413c65ce9SBenny Halevy 	p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16);
1705e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(OP_SEQUENCE);
1706fc01cea9SAndy Adamson 
1707fc01cea9SAndy Adamson 	/*
1708fc01cea9SAndy Adamson 	 * Sessionid + seqid + slotid + max slotid + cache_this
1709fc01cea9SAndy Adamson 	 */
1710fc01cea9SAndy Adamson 	dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1711fc01cea9SAndy Adamson 		"max_slotid=%d cache_this=%d\n",
1712fc01cea9SAndy Adamson 		__func__,
1713fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[0],
1714fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[1],
1715fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[2],
1716fc01cea9SAndy Adamson 		((u32 *)session->sess_id.data)[3],
1717fc01cea9SAndy Adamson 		slot->seq_nr, args->sa_slotid,
1718fc01cea9SAndy Adamson 		tp->highest_used_slotid, args->sa_cache_this);
171993f0cf25SBenny Halevy 	p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
1720e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(slot->seq_nr);
1721e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(args->sa_slotid);
1722e75bc1c8SBenny Halevy 	*p++ = cpu_to_be32(tp->highest_used_slotid);
172334558513SBenny Halevy 	*p = cpu_to_be32(args->sa_cache_this);
17249b7b9fccSAndy Adamson 	hdr->nops++;
17259b7b9fccSAndy Adamson 	hdr->replen += decode_sequence_maxsz;
17269b7b9fccSAndy Adamson #endif /* CONFIG_NFS_V4_1 */
17279b7b9fccSAndy Adamson }
17289b7b9fccSAndy Adamson 
17291da177e4SLinus Torvalds /*
17301da177e4SLinus Torvalds  * END OF "GENERIC" ENCODE ROUTINES.
17311da177e4SLinus Torvalds  */
17321da177e4SLinus Torvalds 
173366cc0429SBenny Halevy static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
173466cc0429SBenny Halevy {
173566cc0429SBenny Halevy #if defined(CONFIG_NFS_V4_1)
173666cc0429SBenny Halevy 	if (args->sa_session)
1737a4432345STrond Myklebust 		return args->sa_session->clp->cl_mvops->minor_version;
173866cc0429SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
173966cc0429SBenny Halevy 	return 0;
174066cc0429SBenny Halevy }
174166cc0429SBenny Halevy 
17421da177e4SLinus Torvalds /*
17431da177e4SLinus Torvalds  * Encode an ACCESS request
17441da177e4SLinus Torvalds  */
17458687b63aSAl Viro static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
17461da177e4SLinus Torvalds {
17471da177e4SLinus Torvalds 	struct xdr_stream xdr;
17481da177e4SLinus Torvalds 	struct compound_hdr hdr = {
174966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
17501da177e4SLinus Torvalds 	};
17511da177e4SLinus Torvalds 
17521da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
17530c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
17549b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1755cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1756cf8cdbe5SAndy Adamson 	encode_access(&xdr, args->access, &hdr);
1757cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1758d017931cSAndy Adamson 	encode_nops(&hdr);
1759cf8cdbe5SAndy Adamson 	return 0;
17601da177e4SLinus Torvalds }
17611da177e4SLinus Torvalds 
17621da177e4SLinus Torvalds /*
17631da177e4SLinus Torvalds  * Encode LOOKUP request
17641da177e4SLinus Torvalds  */
17658687b63aSAl Viro static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
17661da177e4SLinus Torvalds {
17671da177e4SLinus Torvalds 	struct xdr_stream xdr;
17681da177e4SLinus Torvalds 	struct compound_hdr hdr = {
176966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
17701da177e4SLinus Torvalds 	};
17711da177e4SLinus Torvalds 
17721da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
17730c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
17749b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1775cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1776cf8cdbe5SAndy Adamson 	encode_lookup(&xdr, args->name, &hdr);
1777cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1778cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1779d017931cSAndy Adamson 	encode_nops(&hdr);
1780cf8cdbe5SAndy Adamson 	return 0;
17811da177e4SLinus Torvalds }
17821da177e4SLinus Torvalds 
17831da177e4SLinus Torvalds /*
17841da177e4SLinus Torvalds  * Encode LOOKUP_ROOT request
17851da177e4SLinus Torvalds  */
17868687b63aSAl Viro static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
17871da177e4SLinus Torvalds {
17881da177e4SLinus Torvalds 	struct xdr_stream xdr;
17891da177e4SLinus Torvalds 	struct compound_hdr hdr = {
179066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
17911da177e4SLinus Torvalds 	};
17921da177e4SLinus Torvalds 
17931da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
17940c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
17959b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1796cf8cdbe5SAndy Adamson 	encode_putrootfh(&xdr, &hdr);
1797cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1798cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1799d017931cSAndy Adamson 	encode_nops(&hdr);
1800cf8cdbe5SAndy Adamson 	return 0;
18011da177e4SLinus Torvalds }
18021da177e4SLinus Torvalds 
18031da177e4SLinus Torvalds /*
18041da177e4SLinus Torvalds  * Encode REMOVE request
18051da177e4SLinus Torvalds  */
18064fdc17b2STrond Myklebust static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
18071da177e4SLinus Torvalds {
18081da177e4SLinus Torvalds 	struct xdr_stream xdr;
18091da177e4SLinus Torvalds 	struct compound_hdr hdr = {
181066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18111da177e4SLinus Torvalds 	};
18121da177e4SLinus Torvalds 
18131da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18140c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18159b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1816cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1817cf8cdbe5SAndy Adamson 	encode_remove(&xdr, &args->name, &hdr);
1818cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1819d017931cSAndy Adamson 	encode_nops(&hdr);
1820cf8cdbe5SAndy Adamson 	return 0;
18211da177e4SLinus Torvalds }
18221da177e4SLinus Torvalds 
18231da177e4SLinus Torvalds /*
18241da177e4SLinus Torvalds  * Encode RENAME request
18251da177e4SLinus Torvalds  */
1826920769f0SJeff Layton static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs_renameargs *args)
18271da177e4SLinus Torvalds {
18281da177e4SLinus Torvalds 	struct xdr_stream xdr;
18291da177e4SLinus Torvalds 	struct compound_hdr hdr = {
183066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18311da177e4SLinus Torvalds 	};
18321da177e4SLinus Torvalds 
18331da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18340c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18359b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1836cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->old_dir, &hdr);
1837cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1838cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->new_dir, &hdr);
1839cf8cdbe5SAndy Adamson 	encode_rename(&xdr, args->old_name, args->new_name, &hdr);
1840cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1841cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1842cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1843d017931cSAndy Adamson 	encode_nops(&hdr);
1844cf8cdbe5SAndy Adamson 	return 0;
18451da177e4SLinus Torvalds }
18461da177e4SLinus Torvalds 
18471da177e4SLinus Torvalds /*
18481da177e4SLinus Torvalds  * Encode LINK request
18491da177e4SLinus Torvalds  */
18508687b63aSAl Viro static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
18511da177e4SLinus Torvalds {
18521da177e4SLinus Torvalds 	struct xdr_stream xdr;
18531da177e4SLinus Torvalds 	struct compound_hdr hdr = {
185466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18551da177e4SLinus Torvalds 	};
18561da177e4SLinus Torvalds 
18571da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18580c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18599b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1860cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1861cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1862cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1863cf8cdbe5SAndy Adamson 	encode_link(&xdr, args->name, &hdr);
1864cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1865cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1866cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1867d017931cSAndy Adamson 	encode_nops(&hdr);
1868cf8cdbe5SAndy Adamson 	return 0;
18691da177e4SLinus Torvalds }
18701da177e4SLinus Torvalds 
18711da177e4SLinus Torvalds /*
18721da177e4SLinus Torvalds  * Encode CREATE request
18731da177e4SLinus Torvalds  */
18748687b63aSAl Viro static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
18751da177e4SLinus Torvalds {
18761da177e4SLinus Torvalds 	struct xdr_stream xdr;
18771da177e4SLinus Torvalds 	struct compound_hdr hdr = {
187866cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
18791da177e4SLinus Torvalds 	};
18801da177e4SLinus Torvalds 
18811da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
18820c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
18839b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1884cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
1885cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1886cf8cdbe5SAndy Adamson 	encode_create(&xdr, args, &hdr);
1887cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1888cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1889cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1890cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1891d017931cSAndy Adamson 	encode_nops(&hdr);
1892cf8cdbe5SAndy Adamson 	return 0;
18931da177e4SLinus Torvalds }
18941da177e4SLinus Torvalds 
18951da177e4SLinus Torvalds /*
18961da177e4SLinus Torvalds  * Encode SYMLINK request
18971da177e4SLinus Torvalds  */
18988687b63aSAl Viro static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
18991da177e4SLinus Torvalds {
19001da177e4SLinus Torvalds 	return nfs4_xdr_enc_create(req, p, args);
19011da177e4SLinus Torvalds }
19021da177e4SLinus Torvalds 
19031da177e4SLinus Torvalds /*
19041da177e4SLinus Torvalds  * Encode GETATTR request
19051da177e4SLinus Torvalds  */
19068687b63aSAl Viro static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
19071da177e4SLinus Torvalds {
19081da177e4SLinus Torvalds 	struct xdr_stream xdr;
19091da177e4SLinus Torvalds 	struct compound_hdr hdr = {
191066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19111da177e4SLinus Torvalds 	};
19121da177e4SLinus Torvalds 
19131da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19140c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19159b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1916cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1917cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1918d017931cSAndy Adamson 	encode_nops(&hdr);
1919cf8cdbe5SAndy Adamson 	return 0;
19201da177e4SLinus Torvalds }
19211da177e4SLinus Torvalds 
19221da177e4SLinus Torvalds /*
19231da177e4SLinus Torvalds  * Encode a CLOSE request
19241da177e4SLinus Torvalds  */
19258687b63aSAl Viro static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
19261da177e4SLinus Torvalds {
19271da177e4SLinus Torvalds 	struct xdr_stream xdr;
19281da177e4SLinus Torvalds 	struct compound_hdr hdr = {
192966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19301da177e4SLinus Torvalds 	};
19311da177e4SLinus Torvalds 
19321da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19330c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19349b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1935cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1936cf8cdbe5SAndy Adamson 	encode_close(&xdr, args, &hdr);
1937cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1938d017931cSAndy Adamson 	encode_nops(&hdr);
1939cf8cdbe5SAndy Adamson 	return 0;
19401da177e4SLinus Torvalds }
19411da177e4SLinus Torvalds 
19421da177e4SLinus Torvalds /*
19431da177e4SLinus Torvalds  * Encode an OPEN request
19441da177e4SLinus Torvalds  */
19458687b63aSAl Viro static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
19461da177e4SLinus Torvalds {
19471da177e4SLinus Torvalds 	struct xdr_stream xdr;
19481da177e4SLinus Torvalds 	struct compound_hdr hdr = {
194966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19501da177e4SLinus Torvalds 	};
19511da177e4SLinus Torvalds 
19521da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19530c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19549b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1955cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1956cf8cdbe5SAndy Adamson 	encode_savefh(&xdr, &hdr);
1957cf8cdbe5SAndy Adamson 	encode_open(&xdr, args, &hdr);
1958cf8cdbe5SAndy Adamson 	encode_getfh(&xdr, &hdr);
1959cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1960cf8cdbe5SAndy Adamson 	encode_restorefh(&xdr, &hdr);
1961cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
1962d017931cSAndy Adamson 	encode_nops(&hdr);
1963cf8cdbe5SAndy Adamson 	return 0;
19641da177e4SLinus Torvalds }
19651da177e4SLinus Torvalds 
19661da177e4SLinus Torvalds /*
19671da177e4SLinus Torvalds  * Encode an OPEN_CONFIRM request
19681da177e4SLinus Torvalds  */
19698687b63aSAl Viro static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_open_confirmargs *args)
19701da177e4SLinus Torvalds {
19711da177e4SLinus Torvalds 	struct xdr_stream xdr;
19721da177e4SLinus Torvalds 	struct compound_hdr hdr = {
1973d017931cSAndy Adamson 		.nops   = 0,
19741da177e4SLinus Torvalds 	};
19751da177e4SLinus Torvalds 
19761da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19770c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
1978cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1979cf8cdbe5SAndy Adamson 	encode_open_confirm(&xdr, args, &hdr);
1980d017931cSAndy Adamson 	encode_nops(&hdr);
1981cf8cdbe5SAndy Adamson 	return 0;
19821da177e4SLinus Torvalds }
19831da177e4SLinus Torvalds 
19841da177e4SLinus Torvalds /*
19851da177e4SLinus Torvalds  * Encode an OPEN request with no attributes.
19861da177e4SLinus Torvalds  */
19878687b63aSAl Viro static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
19881da177e4SLinus Torvalds {
19891da177e4SLinus Torvalds 	struct xdr_stream xdr;
19901da177e4SLinus Torvalds 	struct compound_hdr hdr = {
199166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
19921da177e4SLinus Torvalds 	};
19931da177e4SLinus Torvalds 
19941da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
19950c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
19969b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
1997cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
1998cf8cdbe5SAndy Adamson 	encode_open(&xdr, args, &hdr);
1999cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2000d017931cSAndy Adamson 	encode_nops(&hdr);
2001cf8cdbe5SAndy Adamson 	return 0;
20021da177e4SLinus Torvalds }
20031da177e4SLinus Torvalds 
20041da177e4SLinus Torvalds /*
20051da177e4SLinus Torvalds  * Encode an OPEN_DOWNGRADE request
20061da177e4SLinus Torvalds  */
20078687b63aSAl Viro static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
20081da177e4SLinus Torvalds {
20091da177e4SLinus Torvalds 	struct xdr_stream xdr;
20101da177e4SLinus Torvalds 	struct compound_hdr hdr = {
201166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20121da177e4SLinus Torvalds 	};
20131da177e4SLinus Torvalds 
20141da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20150c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20169b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2017cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2018cf8cdbe5SAndy Adamson 	encode_open_downgrade(&xdr, args, &hdr);
2019cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2020d017931cSAndy Adamson 	encode_nops(&hdr);
2021cf8cdbe5SAndy Adamson 	return 0;
20221da177e4SLinus Torvalds }
20231da177e4SLinus Torvalds 
20241da177e4SLinus Torvalds /*
20251da177e4SLinus Torvalds  * Encode a LOCK request
20261da177e4SLinus Torvalds  */
20278687b63aSAl Viro static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
20281da177e4SLinus Torvalds {
20291da177e4SLinus Torvalds 	struct xdr_stream xdr;
20301da177e4SLinus Torvalds 	struct compound_hdr hdr = {
203166cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20321da177e4SLinus Torvalds 	};
20331da177e4SLinus Torvalds 
20341da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20350c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20369b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2037cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2038cf8cdbe5SAndy Adamson 	encode_lock(&xdr, args, &hdr);
2039d017931cSAndy Adamson 	encode_nops(&hdr);
2040cf8cdbe5SAndy Adamson 	return 0;
20411da177e4SLinus Torvalds }
20421da177e4SLinus Torvalds 
20431da177e4SLinus Torvalds /*
20441da177e4SLinus Torvalds  * Encode a LOCKT request
20451da177e4SLinus Torvalds  */
20468687b63aSAl Viro static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
20471da177e4SLinus Torvalds {
20481da177e4SLinus Torvalds 	struct xdr_stream xdr;
20491da177e4SLinus Torvalds 	struct compound_hdr hdr = {
205066cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20511da177e4SLinus Torvalds 	};
20521da177e4SLinus Torvalds 
20531da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20540c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20559b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2056cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2057cf8cdbe5SAndy Adamson 	encode_lockt(&xdr, args, &hdr);
2058d017931cSAndy Adamson 	encode_nops(&hdr);
2059cf8cdbe5SAndy Adamson 	return 0;
20601da177e4SLinus Torvalds }
20611da177e4SLinus Torvalds 
20621da177e4SLinus Torvalds /*
20631da177e4SLinus Torvalds  * Encode a LOCKU request
20641da177e4SLinus Torvalds  */
20658687b63aSAl Viro static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
20661da177e4SLinus Torvalds {
20671da177e4SLinus Torvalds 	struct xdr_stream xdr;
20681da177e4SLinus Torvalds 	struct compound_hdr hdr = {
206966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
20701da177e4SLinus Torvalds 	};
20711da177e4SLinus Torvalds 
20721da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
20730c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
20749b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2075cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2076cf8cdbe5SAndy Adamson 	encode_locku(&xdr, args, &hdr);
2077d017931cSAndy Adamson 	encode_nops(&hdr);
2078cf8cdbe5SAndy Adamson 	return 0;
20791da177e4SLinus Torvalds }
20801da177e4SLinus Torvalds 
2081d3c7b7ccSTrond Myklebust static int nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, __be32 *p, struct nfs_release_lockowner_args *args)
2082d3c7b7ccSTrond Myklebust {
2083d3c7b7ccSTrond Myklebust 	struct xdr_stream xdr;
2084d3c7b7ccSTrond Myklebust 	struct compound_hdr hdr = {
2085d3c7b7ccSTrond Myklebust 		.minorversion = 0,
2086d3c7b7ccSTrond Myklebust 	};
2087d3c7b7ccSTrond Myklebust 
2088d3c7b7ccSTrond Myklebust 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2089d3c7b7ccSTrond Myklebust 	encode_compound_hdr(&xdr, req, &hdr);
2090d3c7b7ccSTrond Myklebust 	encode_release_lockowner(&xdr, &args->lock_owner, &hdr);
2091d3c7b7ccSTrond Myklebust 	encode_nops(&hdr);
2092d3c7b7ccSTrond Myklebust 	return 0;
2093d3c7b7ccSTrond Myklebust }
2094d3c7b7ccSTrond Myklebust 
20951da177e4SLinus Torvalds /*
20961da177e4SLinus Torvalds  * Encode a READLINK request
20971da177e4SLinus Torvalds  */
20988687b63aSAl Viro static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
20991da177e4SLinus Torvalds {
21001da177e4SLinus Torvalds 	struct xdr_stream xdr;
21011da177e4SLinus Torvalds 	struct compound_hdr hdr = {
210266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21031da177e4SLinus Torvalds 	};
21041da177e4SLinus Torvalds 
21051da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21060c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21079b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2108cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2109cf8cdbe5SAndy Adamson 	encode_readlink(&xdr, args, req, &hdr);
2110e3a535e1STrond Myklebust 
211128f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2112e3a535e1STrond Myklebust 			args->pgbase, args->pglen);
2113d017931cSAndy Adamson 	encode_nops(&hdr);
2114cf8cdbe5SAndy Adamson 	return 0;
21151da177e4SLinus Torvalds }
21161da177e4SLinus Torvalds 
21171da177e4SLinus Torvalds /*
21181da177e4SLinus Torvalds  * Encode a READDIR request
21191da177e4SLinus Torvalds  */
21208687b63aSAl Viro static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
21211da177e4SLinus Torvalds {
21221da177e4SLinus Torvalds 	struct xdr_stream xdr;
21231da177e4SLinus Torvalds 	struct compound_hdr hdr = {
212466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21251da177e4SLinus Torvalds 	};
21261da177e4SLinus Torvalds 
21271da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21280c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21299b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2130cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2131cf8cdbe5SAndy Adamson 	encode_readdir(&xdr, args, req, &hdr);
2132d6ac02dfSTrond Myklebust 
213328f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
2134d6ac02dfSTrond Myklebust 			 args->pgbase, args->count);
2135d6ac02dfSTrond Myklebust 	dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
213628f56694SBenny Halevy 			__func__, hdr.replen << 2, args->pages,
2137d6ac02dfSTrond Myklebust 			args->pgbase, args->count);
2138d017931cSAndy Adamson 	encode_nops(&hdr);
2139cf8cdbe5SAndy Adamson 	return 0;
21401da177e4SLinus Torvalds }
21411da177e4SLinus Torvalds 
21421da177e4SLinus Torvalds /*
21431da177e4SLinus Torvalds  * Encode a READ request
21441da177e4SLinus Torvalds  */
21458687b63aSAl Viro static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
21461da177e4SLinus Torvalds {
21471da177e4SLinus Torvalds 	struct xdr_stream xdr;
21481da177e4SLinus Torvalds 	struct compound_hdr hdr = {
214966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21501da177e4SLinus Torvalds 	};
21511da177e4SLinus Torvalds 
21521da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21530c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21549b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2155cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2156cf8cdbe5SAndy Adamson 	encode_read(&xdr, args, &hdr);
21571da177e4SLinus Torvalds 
215828f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
21591da177e4SLinus Torvalds 			 args->pages, args->pgbase, args->count);
21604f22ccc3S\"Talpey, Thomas\ 	req->rq_rcv_buf.flags |= XDRBUF_READ;
2161d017931cSAndy Adamson 	encode_nops(&hdr);
2162cf8cdbe5SAndy Adamson 	return 0;
21631da177e4SLinus Torvalds }
21641da177e4SLinus Torvalds 
21651da177e4SLinus Torvalds /*
21661da177e4SLinus Torvalds  * Encode an SETATTR request
21671da177e4SLinus Torvalds  */
21688687b63aSAl Viro static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
21691da177e4SLinus Torvalds {
21701da177e4SLinus Torvalds 	struct xdr_stream xdr;
21711da177e4SLinus Torvalds 	struct compound_hdr hdr = {
217266cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
21731da177e4SLinus Torvalds 	};
21741da177e4SLinus Torvalds 
21751da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21760c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
21779b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2178cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2179cf8cdbe5SAndy Adamson 	encode_setattr(&xdr, args, args->server, &hdr);
2180cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2181d017931cSAndy Adamson 	encode_nops(&hdr);
2182cf8cdbe5SAndy Adamson 	return 0;
21831da177e4SLinus Torvalds }
21841da177e4SLinus Torvalds 
21851da177e4SLinus Torvalds /*
2186029d105eSJ. Bruce Fields  * Encode a GETACL request
2187029d105eSJ. Bruce Fields  */
2188029d105eSJ. Bruce Fields static int
21898687b63aSAl Viro nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
2190029d105eSJ. Bruce Fields 		struct nfs_getaclargs *args)
2191029d105eSJ. Bruce Fields {
2192029d105eSJ. Bruce Fields 	struct xdr_stream xdr;
2193029d105eSJ. Bruce Fields 	struct compound_hdr hdr = {
219466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
2195029d105eSJ. Bruce Fields 	};
219628f56694SBenny Halevy 	uint32_t replen;
2197029d105eSJ. Bruce Fields 
2198029d105eSJ. Bruce Fields 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
21990c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22009b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2201cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2202d327cf74SJ. Bruce Fields 	replen = hdr.replen + op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz + 1;
2203cf8cdbe5SAndy Adamson 	encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
2204cf8cdbe5SAndy Adamson 
220528f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
2206029d105eSJ. Bruce Fields 		args->acl_pages, args->acl_pgbase, args->acl_len);
2207d017931cSAndy Adamson 	encode_nops(&hdr);
2208cf8cdbe5SAndy Adamson 	return 0;
2209029d105eSJ. Bruce Fields }
2210029d105eSJ. Bruce Fields 
2211029d105eSJ. Bruce Fields /*
22121da177e4SLinus Torvalds  * Encode a WRITE request
22131da177e4SLinus Torvalds  */
22148687b63aSAl Viro static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
22151da177e4SLinus Torvalds {
22161da177e4SLinus Torvalds 	struct xdr_stream xdr;
22171da177e4SLinus Torvalds 	struct compound_hdr hdr = {
221866cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22191da177e4SLinus Torvalds 	};
22201da177e4SLinus Torvalds 
22211da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22220c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22239b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2224cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2225cf8cdbe5SAndy Adamson 	encode_write(&xdr, args, &hdr);
22264f22ccc3S\"Talpey, Thomas\ 	req->rq_snd_buf.flags |= XDRBUF_WRITE;
2227cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2228d017931cSAndy Adamson 	encode_nops(&hdr);
2229cf8cdbe5SAndy Adamson 	return 0;
22301da177e4SLinus Torvalds }
22311da177e4SLinus Torvalds 
22321da177e4SLinus Torvalds /*
22331da177e4SLinus Torvalds  *  a COMMIT request
22341da177e4SLinus Torvalds  */
22358687b63aSAl Viro static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
22361da177e4SLinus Torvalds {
22371da177e4SLinus Torvalds 	struct xdr_stream xdr;
22381da177e4SLinus Torvalds 	struct compound_hdr hdr = {
223966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22401da177e4SLinus Torvalds 	};
22411da177e4SLinus Torvalds 
22421da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22430c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22449b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2245cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2246cf8cdbe5SAndy Adamson 	encode_commit(&xdr, args, &hdr);
2247cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2248d017931cSAndy Adamson 	encode_nops(&hdr);
2249cf8cdbe5SAndy Adamson 	return 0;
22501da177e4SLinus Torvalds }
22511da177e4SLinus Torvalds 
22521da177e4SLinus Torvalds /*
22531da177e4SLinus Torvalds  * FSINFO request
22541da177e4SLinus Torvalds  */
22558687b63aSAl Viro static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
22561da177e4SLinus Torvalds {
22571da177e4SLinus Torvalds 	struct xdr_stream xdr;
22581da177e4SLinus Torvalds 	struct compound_hdr hdr = {
225966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22601da177e4SLinus Torvalds 	};
22611da177e4SLinus Torvalds 
22621da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22630c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22649b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2265cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2266cf8cdbe5SAndy Adamson 	encode_fsinfo(&xdr, args->bitmask, &hdr);
2267d017931cSAndy Adamson 	encode_nops(&hdr);
2268cf8cdbe5SAndy Adamson 	return 0;
22691da177e4SLinus Torvalds }
22701da177e4SLinus Torvalds 
22711da177e4SLinus Torvalds /*
22721da177e4SLinus Torvalds  * a PATHCONF request
22731da177e4SLinus Torvalds  */
22748687b63aSAl Viro static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
22751da177e4SLinus Torvalds {
22761da177e4SLinus Torvalds 	struct xdr_stream xdr;
22771da177e4SLinus Torvalds 	struct compound_hdr hdr = {
227866cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22791da177e4SLinus Torvalds 	};
22801da177e4SLinus Torvalds 
22811da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
22820c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
22839b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2284cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2285cf8cdbe5SAndy Adamson 	encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
2286d017931cSAndy Adamson 			   &hdr);
2287d017931cSAndy Adamson 	encode_nops(&hdr);
2288cf8cdbe5SAndy Adamson 	return 0;
22891da177e4SLinus Torvalds }
22901da177e4SLinus Torvalds 
22911da177e4SLinus Torvalds /*
22921da177e4SLinus Torvalds  * a STATFS request
22931da177e4SLinus Torvalds  */
22948687b63aSAl Viro static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
22951da177e4SLinus Torvalds {
22961da177e4SLinus Torvalds 	struct xdr_stream xdr;
22971da177e4SLinus Torvalds 	struct compound_hdr hdr = {
229866cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
22991da177e4SLinus Torvalds 	};
23001da177e4SLinus Torvalds 
23011da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23020c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
23039b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2304cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
2305cf8cdbe5SAndy Adamson 	encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
2306d017931cSAndy Adamson 			   args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
2307d017931cSAndy Adamson 	encode_nops(&hdr);
2308cf8cdbe5SAndy Adamson 	return 0;
23091da177e4SLinus Torvalds }
23101da177e4SLinus Torvalds 
23111da177e4SLinus Torvalds /*
23121da177e4SLinus Torvalds  * GETATTR_BITMAP request
23131da177e4SLinus Torvalds  */
231443652ad5SBenny Halevy static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
231543652ad5SBenny Halevy 				    struct nfs4_server_caps_arg *args)
23161da177e4SLinus Torvalds {
23171da177e4SLinus Torvalds 	struct xdr_stream xdr;
23181da177e4SLinus Torvalds 	struct compound_hdr hdr = {
231966cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
23201da177e4SLinus Torvalds 	};
23211da177e4SLinus Torvalds 
23221da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23230c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
23249b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
232543652ad5SBenny Halevy 	encode_putfh(&xdr, args->fhandle, &hdr);
2326cf8cdbe5SAndy Adamson 	encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
23271da177e4SLinus Torvalds 			   FATTR4_WORD0_LINK_SUPPORT|
23281da177e4SLinus Torvalds 			   FATTR4_WORD0_SYMLINK_SUPPORT|
2329d017931cSAndy Adamson 			   FATTR4_WORD0_ACLSUPPORT, &hdr);
2330d017931cSAndy Adamson 	encode_nops(&hdr);
2331cf8cdbe5SAndy Adamson 	return 0;
23321da177e4SLinus Torvalds }
23331da177e4SLinus Torvalds 
23341da177e4SLinus Torvalds /*
23351da177e4SLinus Torvalds  * a RENEW request
23361da177e4SLinus Torvalds  */
23378687b63aSAl Viro static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
23381da177e4SLinus Torvalds {
23391da177e4SLinus Torvalds 	struct xdr_stream xdr;
23401da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2341d017931cSAndy Adamson 		.nops	= 0,
23421da177e4SLinus Torvalds 	};
23431da177e4SLinus Torvalds 
23441da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23450c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2346cf8cdbe5SAndy Adamson 	encode_renew(&xdr, clp, &hdr);
2347d017931cSAndy Adamson 	encode_nops(&hdr);
2348cf8cdbe5SAndy Adamson 	return 0;
23491da177e4SLinus Torvalds }
23501da177e4SLinus Torvalds 
23511da177e4SLinus Torvalds /*
23521da177e4SLinus Torvalds  * a SETCLIENTID request
23531da177e4SLinus Torvalds  */
23548687b63aSAl Viro static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid *sc)
23551da177e4SLinus Torvalds {
23561da177e4SLinus Torvalds 	struct xdr_stream xdr;
23571da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2358d017931cSAndy Adamson 		.nops	= 0,
23591da177e4SLinus Torvalds 	};
23601da177e4SLinus Torvalds 
23611da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23620c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2363cf8cdbe5SAndy Adamson 	encode_setclientid(&xdr, sc, &hdr);
2364d017931cSAndy Adamson 	encode_nops(&hdr);
2365cf8cdbe5SAndy Adamson 	return 0;
23661da177e4SLinus Torvalds }
23671da177e4SLinus Torvalds 
23681da177e4SLinus Torvalds /*
23691da177e4SLinus Torvalds  * a SETCLIENTID_CONFIRM request
23701da177e4SLinus Torvalds  */
2371bb8b27e5STrond Myklebust static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid_res *arg)
23721da177e4SLinus Torvalds {
23731da177e4SLinus Torvalds 	struct xdr_stream xdr;
23741da177e4SLinus Torvalds 	struct compound_hdr hdr = {
2375d017931cSAndy Adamson 		.nops	= 0,
23761da177e4SLinus Torvalds 	};
23771da177e4SLinus Torvalds 	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
23781da177e4SLinus Torvalds 
23791da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23800c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
2381bb8b27e5STrond Myklebust 	encode_setclientid_confirm(&xdr, arg, &hdr);
2382cf8cdbe5SAndy Adamson 	encode_putrootfh(&xdr, &hdr);
2383cf8cdbe5SAndy Adamson 	encode_fsinfo(&xdr, lease_bitmap, &hdr);
2384d017931cSAndy Adamson 	encode_nops(&hdr);
2385cf8cdbe5SAndy Adamson 	return 0;
23861da177e4SLinus Torvalds }
23871da177e4SLinus Torvalds 
23881da177e4SLinus Torvalds /*
23891da177e4SLinus Torvalds  * DELEGRETURN request
23901da177e4SLinus Torvalds  */
23918687b63aSAl Viro static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
23921da177e4SLinus Torvalds {
23931da177e4SLinus Torvalds 	struct xdr_stream xdr;
23941da177e4SLinus Torvalds 	struct compound_hdr hdr = {
239566cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
23961da177e4SLinus Torvalds 	};
23971da177e4SLinus Torvalds 
23981da177e4SLinus Torvalds 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
23990c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
24009b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2401cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fhandle, &hdr);
2402cf8cdbe5SAndy Adamson 	encode_delegreturn(&xdr, args->stateid, &hdr);
2403cf8cdbe5SAndy Adamson 	encode_getfattr(&xdr, args->bitmask, &hdr);
2404d017931cSAndy Adamson 	encode_nops(&hdr);
2405cf8cdbe5SAndy Adamson 	return 0;
24061da177e4SLinus Torvalds }
24071da177e4SLinus Torvalds 
24081da177e4SLinus Torvalds /*
2409683b57b4STrond Myklebust  * Encode FS_LOCATIONS request
2410683b57b4STrond Myklebust  */
24118687b63aSAl Viro static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
2412683b57b4STrond Myklebust {
2413683b57b4STrond Myklebust 	struct xdr_stream xdr;
2414683b57b4STrond Myklebust 	struct compound_hdr hdr = {
241566cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
2416683b57b4STrond Myklebust 	};
241728f56694SBenny Halevy 	uint32_t replen;
2418683b57b4STrond Myklebust 
2419683b57b4STrond Myklebust 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
24200c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
24219b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
2422cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->dir_fh, &hdr);
2423cf8cdbe5SAndy Adamson 	encode_lookup(&xdr, args->name, &hdr);
242428f56694SBenny Halevy 	replen = hdr.replen;	/* get the attribute into args->page */
2425cf8cdbe5SAndy Adamson 	encode_fs_locations(&xdr, args->bitmask, &hdr);
2426cf8cdbe5SAndy Adamson 
242728f56694SBenny Halevy 	xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
2428683b57b4STrond Myklebust 			0, PAGE_SIZE);
2429d017931cSAndy Adamson 	encode_nops(&hdr);
2430cf8cdbe5SAndy Adamson 	return 0;
2431683b57b4STrond Myklebust }
2432683b57b4STrond Myklebust 
243399fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
243499fe60d0SBenny Halevy /*
243599fe60d0SBenny Halevy  * EXCHANGE_ID request
243699fe60d0SBenny Halevy  */
243799fe60d0SBenny Halevy static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
243899fe60d0SBenny Halevy 				    struct nfs41_exchange_id_args *args)
243999fe60d0SBenny Halevy {
244099fe60d0SBenny Halevy 	struct xdr_stream xdr;
244199fe60d0SBenny Halevy 	struct compound_hdr hdr = {
2442a4432345STrond Myklebust 		.minorversion = args->client->cl_mvops->minor_version,
244399fe60d0SBenny Halevy 	};
244499fe60d0SBenny Halevy 
244599fe60d0SBenny Halevy 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
244699fe60d0SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
244799fe60d0SBenny Halevy 	encode_exchange_id(&xdr, args, &hdr);
244899fe60d0SBenny Halevy 	encode_nops(&hdr);
244999fe60d0SBenny Halevy 	return 0;
245099fe60d0SBenny Halevy }
24512050f0ccSAndy Adamson 
24522050f0ccSAndy Adamson /*
2453fc931582SAndy Adamson  * a CREATE_SESSION request
2454fc931582SAndy Adamson  */
2455fc931582SAndy Adamson static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
2456fc931582SAndy Adamson 				       struct nfs41_create_session_args *args)
2457fc931582SAndy Adamson {
2458fc931582SAndy Adamson 	struct xdr_stream xdr;
2459fc931582SAndy Adamson 	struct compound_hdr hdr = {
2460a4432345STrond Myklebust 		.minorversion = args->client->cl_mvops->minor_version,
2461fc931582SAndy Adamson 	};
2462fc931582SAndy Adamson 
2463fc931582SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2464fc931582SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
2465fc931582SAndy Adamson 	encode_create_session(&xdr, args, &hdr);
2466fc931582SAndy Adamson 	encode_nops(&hdr);
2467fc931582SAndy Adamson 	return 0;
2468fc931582SAndy Adamson }
2469fc931582SAndy Adamson 
2470fc931582SAndy Adamson /*
24710f3e66c6SAndy Adamson  * a DESTROY_SESSION request
24720f3e66c6SAndy Adamson  */
24730f3e66c6SAndy Adamson static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
24740f3e66c6SAndy Adamson 					struct nfs4_session *session)
24750f3e66c6SAndy Adamson {
24760f3e66c6SAndy Adamson 	struct xdr_stream xdr;
24770f3e66c6SAndy Adamson 	struct compound_hdr hdr = {
2478a4432345STrond Myklebust 		.minorversion = session->clp->cl_mvops->minor_version,
24790f3e66c6SAndy Adamson 	};
24800f3e66c6SAndy Adamson 
24810f3e66c6SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
24820f3e66c6SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
24830f3e66c6SAndy Adamson 	encode_destroy_session(&xdr, session, &hdr);
24840f3e66c6SAndy Adamson 	encode_nops(&hdr);
24850f3e66c6SAndy Adamson 	return 0;
24860f3e66c6SAndy Adamson }
24870f3e66c6SAndy Adamson 
24880f3e66c6SAndy Adamson /*
2489fc01cea9SAndy Adamson  * a SEQUENCE request
2490fc01cea9SAndy Adamson  */
2491fc01cea9SAndy Adamson static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
2492fc01cea9SAndy Adamson 				 struct nfs4_sequence_args *args)
2493fc01cea9SAndy Adamson {
2494fc01cea9SAndy Adamson 	struct xdr_stream xdr;
2495fc01cea9SAndy Adamson 	struct compound_hdr hdr = {
2496fc01cea9SAndy Adamson 		.minorversion = nfs4_xdr_minorversion(args),
2497fc01cea9SAndy Adamson 	};
2498fc01cea9SAndy Adamson 
2499fc01cea9SAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2500fc01cea9SAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
2501fc01cea9SAndy Adamson 	encode_sequence(&xdr, args, &hdr);
2502fc01cea9SAndy Adamson 	encode_nops(&hdr);
2503fc01cea9SAndy Adamson 	return 0;
2504fc01cea9SAndy Adamson }
2505fc01cea9SAndy Adamson 
2506fc01cea9SAndy Adamson /*
25072050f0ccSAndy Adamson  * a GET_LEASE_TIME request
25082050f0ccSAndy Adamson  */
25092050f0ccSAndy Adamson static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
25102050f0ccSAndy Adamson 				       struct nfs4_get_lease_time_args *args)
25112050f0ccSAndy Adamson {
25122050f0ccSAndy Adamson 	struct xdr_stream xdr;
25132050f0ccSAndy Adamson 	struct compound_hdr hdr = {
25142050f0ccSAndy Adamson 		.minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
25152050f0ccSAndy Adamson 	};
25162050f0ccSAndy Adamson 	const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
25172050f0ccSAndy Adamson 
25182050f0ccSAndy Adamson 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
25192050f0ccSAndy Adamson 	encode_compound_hdr(&xdr, req, &hdr);
25202050f0ccSAndy Adamson 	encode_sequence(&xdr, &args->la_seq_args, &hdr);
25212050f0ccSAndy Adamson 	encode_putrootfh(&xdr, &hdr);
25222050f0ccSAndy Adamson 	encode_fsinfo(&xdr, lease_bitmap, &hdr);
25232050f0ccSAndy Adamson 	encode_nops(&hdr);
25242050f0ccSAndy Adamson 	return 0;
25252050f0ccSAndy Adamson }
252618019753SRicardo Labiaga 
252718019753SRicardo Labiaga /*
252818019753SRicardo Labiaga  * a RECLAIM_COMPLETE request
252918019753SRicardo Labiaga  */
253018019753SRicardo Labiaga static int nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req, uint32_t *p,
253118019753SRicardo Labiaga 				     struct nfs41_reclaim_complete_args *args)
253218019753SRicardo Labiaga {
253318019753SRicardo Labiaga 	struct xdr_stream xdr;
253418019753SRicardo Labiaga 	struct compound_hdr hdr = {
253518019753SRicardo Labiaga 		.minorversion = nfs4_xdr_minorversion(&args->seq_args)
253618019753SRicardo Labiaga 	};
253718019753SRicardo Labiaga 
253818019753SRicardo Labiaga 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
253918019753SRicardo Labiaga 	encode_compound_hdr(&xdr, req, &hdr);
254018019753SRicardo Labiaga 	encode_sequence(&xdr, &args->seq_args, &hdr);
254118019753SRicardo Labiaga 	encode_reclaim_complete(&xdr, args, &hdr);
254218019753SRicardo Labiaga 	encode_nops(&hdr);
254318019753SRicardo Labiaga 	return 0;
254418019753SRicardo Labiaga }
254518019753SRicardo Labiaga 
254699fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
254799fe60d0SBenny Halevy 
2548686841b3SBenny Halevy static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
2549686841b3SBenny Halevy {
2550686841b3SBenny Halevy 	dprintk("nfs: %s: prematurely hit end of receive buffer. "
2551686841b3SBenny Halevy 		"Remaining buffer length is %tu words.\n",
2552686841b3SBenny Halevy 		func, xdr->end - xdr->p);
2553686841b3SBenny Halevy }
25541da177e4SLinus Torvalds 
2555683b57b4STrond Myklebust static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
25561da177e4SLinus Torvalds {
25578687b63aSAl Viro 	__be32 *p;
25581da177e4SLinus Torvalds 
2559c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2560c0eae66eSBenny Halevy 	if (unlikely(!p))
2561c0eae66eSBenny Halevy 		goto out_overflow;
2562cccddf4fSBenny Halevy 	*len = be32_to_cpup(p);
2563c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, *len);
2564c0eae66eSBenny Halevy 	if (unlikely(!p))
2565c0eae66eSBenny Halevy 		goto out_overflow;
25661da177e4SLinus Torvalds 	*string = (char *)p;
25671da177e4SLinus Torvalds 	return 0;
2568c0eae66eSBenny Halevy out_overflow:
2569c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2570c0eae66eSBenny Halevy 	return -EIO;
25711da177e4SLinus Torvalds }
25721da177e4SLinus Torvalds 
25731da177e4SLinus Torvalds static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
25741da177e4SLinus Torvalds {
25758687b63aSAl Viro 	__be32 *p;
25761da177e4SLinus Torvalds 
2577c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
2578c0eae66eSBenny Halevy 	if (unlikely(!p))
2579c0eae66eSBenny Halevy 		goto out_overflow;
25806f723f77SBenny Halevy 	hdr->status = be32_to_cpup(p++);
2581cccddf4fSBenny Halevy 	hdr->taglen = be32_to_cpup(p);
25821da177e4SLinus Torvalds 
2583c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, hdr->taglen + 4);
2584c0eae66eSBenny Halevy 	if (unlikely(!p))
2585c0eae66eSBenny Halevy 		goto out_overflow;
25861da177e4SLinus Torvalds 	hdr->tag = (char *)p;
25871da177e4SLinus Torvalds 	p += XDR_QUADLEN(hdr->taglen);
2588cccddf4fSBenny Halevy 	hdr->nops = be32_to_cpup(p);
2589aadf6152SBenny Halevy 	if (unlikely(hdr->nops < 1))
2590aadf6152SBenny Halevy 		return nfs4_stat_to_errno(hdr->status);
25911da177e4SLinus Torvalds 	return 0;
2592c0eae66eSBenny Halevy out_overflow:
2593c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2594c0eae66eSBenny Halevy 	return -EIO;
25951da177e4SLinus Torvalds }
25961da177e4SLinus Torvalds 
25971da177e4SLinus Torvalds static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
25981da177e4SLinus Torvalds {
25998687b63aSAl Viro 	__be32 *p;
26001da177e4SLinus Torvalds 	uint32_t opnum;
26011da177e4SLinus Torvalds 	int32_t nfserr;
26021da177e4SLinus Torvalds 
2603c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
2604c0eae66eSBenny Halevy 	if (unlikely(!p))
2605c0eae66eSBenny Halevy 		goto out_overflow;
26066f723f77SBenny Halevy 	opnum = be32_to_cpup(p++);
26071da177e4SLinus Torvalds 	if (opnum != expected) {
2608fe82a183SChuck Lever 		dprintk("nfs: Server returned operation"
26091da177e4SLinus Torvalds 			" %d but we issued a request for %d\n",
26101da177e4SLinus Torvalds 				opnum, expected);
26111da177e4SLinus Torvalds 		return -EIO;
26121da177e4SLinus Torvalds 	}
2613cccddf4fSBenny Halevy 	nfserr = be32_to_cpup(p);
26141da177e4SLinus Torvalds 	if (nfserr != NFS_OK)
2615856dff3dSBenny Halevy 		return nfs4_stat_to_errno(nfserr);
26161da177e4SLinus Torvalds 	return 0;
2617c0eae66eSBenny Halevy out_overflow:
2618c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2619c0eae66eSBenny Halevy 	return -EIO;
26201da177e4SLinus Torvalds }
26211da177e4SLinus Torvalds 
26221da177e4SLinus Torvalds /* Dummy routine */
2623adfa6f98SDavid Howells static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
26241da177e4SLinus Torvalds {
26258687b63aSAl Viro 	__be32 *p;
2626683b57b4STrond Myklebust 	unsigned int strlen;
26271da177e4SLinus Torvalds 	char *str;
26281da177e4SLinus Torvalds 
2629c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
2630c0eae66eSBenny Halevy 	if (likely(p))
26311da177e4SLinus Torvalds 		return decode_opaque_inline(xdr, &strlen, &str);
2632c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2633c0eae66eSBenny Halevy 	return -EIO;
26341da177e4SLinus Torvalds }
26351da177e4SLinus Torvalds 
26361da177e4SLinus Torvalds static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
26371da177e4SLinus Torvalds {
26388687b63aSAl Viro 	uint32_t bmlen;
26398687b63aSAl Viro 	__be32 *p;
26401da177e4SLinus Torvalds 
2641c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2642c0eae66eSBenny Halevy 	if (unlikely(!p))
2643c0eae66eSBenny Halevy 		goto out_overflow;
2644cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
26451da177e4SLinus Torvalds 
26461da177e4SLinus Torvalds 	bitmap[0] = bitmap[1] = 0;
2647c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, (bmlen << 2));
2648c0eae66eSBenny Halevy 	if (unlikely(!p))
2649c0eae66eSBenny Halevy 		goto out_overflow;
26501da177e4SLinus Torvalds 	if (bmlen > 0) {
26516f723f77SBenny Halevy 		bitmap[0] = be32_to_cpup(p++);
26521da177e4SLinus Torvalds 		if (bmlen > 1)
2653cccddf4fSBenny Halevy 			bitmap[1] = be32_to_cpup(p);
26541da177e4SLinus Torvalds 	}
26551da177e4SLinus Torvalds 	return 0;
2656c0eae66eSBenny Halevy out_overflow:
2657c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2658c0eae66eSBenny Halevy 	return -EIO;
26591da177e4SLinus Torvalds }
26601da177e4SLinus Torvalds 
26618687b63aSAl Viro static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep)
26621da177e4SLinus Torvalds {
26638687b63aSAl Viro 	__be32 *p;
26641da177e4SLinus Torvalds 
2665c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2666c0eae66eSBenny Halevy 	if (unlikely(!p))
2667c0eae66eSBenny Halevy 		goto out_overflow;
2668cccddf4fSBenny Halevy 	*attrlen = be32_to_cpup(p);
26691da177e4SLinus Torvalds 	*savep = xdr->p;
26701da177e4SLinus Torvalds 	return 0;
2671c0eae66eSBenny Halevy out_overflow:
2672c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2673c0eae66eSBenny Halevy 	return -EIO;
26741da177e4SLinus Torvalds }
26751da177e4SLinus Torvalds 
26761da177e4SLinus Torvalds static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
26771da177e4SLinus Torvalds {
26781da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
26791da177e4SLinus Torvalds 		decode_attr_bitmap(xdr, bitmask);
26801da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
26811da177e4SLinus Torvalds 	} else
26821da177e4SLinus Torvalds 		bitmask[0] = bitmask[1] = 0;
268344109241SFred Isaman 	dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
26841da177e4SLinus Torvalds 	return 0;
26851da177e4SLinus Torvalds }
26861da177e4SLinus Torvalds 
26871da177e4SLinus Torvalds static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
26881da177e4SLinus Torvalds {
26898687b63aSAl Viro 	__be32 *p;
2690409924e4STrond Myklebust 	int ret = 0;
26911da177e4SLinus Torvalds 
26921da177e4SLinus Torvalds 	*type = 0;
26931da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
26941da177e4SLinus Torvalds 		return -EIO;
26951da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
2696c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2697c0eae66eSBenny Halevy 		if (unlikely(!p))
2698c0eae66eSBenny Halevy 			goto out_overflow;
2699cccddf4fSBenny Halevy 		*type = be32_to_cpup(p);
27001da177e4SLinus Torvalds 		if (*type < NF4REG || *type > NF4NAMEDATTR) {
27013110ff80SHarvey Harrison 			dprintk("%s: bad type %d\n", __func__, *type);
27021da177e4SLinus Torvalds 			return -EIO;
27031da177e4SLinus Torvalds 		}
27041da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_TYPE;
2705409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_TYPE;
27061da177e4SLinus Torvalds 	}
2707bca79478STrond Myklebust 	dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
2708409924e4STrond Myklebust 	return ret;
2709c0eae66eSBenny Halevy out_overflow:
2710c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2711c0eae66eSBenny Halevy 	return -EIO;
27121da177e4SLinus Torvalds }
27131da177e4SLinus Torvalds 
27141da177e4SLinus Torvalds static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
27151da177e4SLinus Torvalds {
27168687b63aSAl Viro 	__be32 *p;
2717409924e4STrond Myklebust 	int ret = 0;
27181da177e4SLinus Torvalds 
27191da177e4SLinus Torvalds 	*change = 0;
27201da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
27211da177e4SLinus Torvalds 		return -EIO;
27221da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
2723c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2724c0eae66eSBenny Halevy 		if (unlikely(!p))
2725c0eae66eSBenny Halevy 			goto out_overflow;
2726cccddf4fSBenny Halevy 		xdr_decode_hyper(p, change);
27271da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_CHANGE;
2728409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_CHANGE;
27291da177e4SLinus Torvalds 	}
27303110ff80SHarvey Harrison 	dprintk("%s: change attribute=%Lu\n", __func__,
27311da177e4SLinus Torvalds 			(unsigned long long)*change);
2732409924e4STrond Myklebust 	return ret;
2733c0eae66eSBenny Halevy out_overflow:
2734c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2735c0eae66eSBenny Halevy 	return -EIO;
27361da177e4SLinus Torvalds }
27371da177e4SLinus Torvalds 
27381da177e4SLinus Torvalds static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
27391da177e4SLinus Torvalds {
27408687b63aSAl Viro 	__be32 *p;
2741409924e4STrond Myklebust 	int ret = 0;
27421da177e4SLinus Torvalds 
27431da177e4SLinus Torvalds 	*size = 0;
27441da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
27451da177e4SLinus Torvalds 		return -EIO;
27461da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
2747c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2748c0eae66eSBenny Halevy 		if (unlikely(!p))
2749c0eae66eSBenny Halevy 			goto out_overflow;
2750cccddf4fSBenny Halevy 		xdr_decode_hyper(p, size);
27511da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SIZE;
2752409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_SIZE;
27531da177e4SLinus Torvalds 	}
27543110ff80SHarvey Harrison 	dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
2755409924e4STrond Myklebust 	return ret;
2756c0eae66eSBenny Halevy out_overflow:
2757c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2758c0eae66eSBenny Halevy 	return -EIO;
27591da177e4SLinus Torvalds }
27601da177e4SLinus Torvalds 
27611da177e4SLinus Torvalds static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
27621da177e4SLinus Torvalds {
27638687b63aSAl Viro 	__be32 *p;
27641da177e4SLinus Torvalds 
27651da177e4SLinus Torvalds 	*res = 0;
27661da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
27671da177e4SLinus Torvalds 		return -EIO;
27681da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
2769c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2770c0eae66eSBenny Halevy 		if (unlikely(!p))
2771c0eae66eSBenny Halevy 			goto out_overflow;
2772cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
27731da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
27741da177e4SLinus Torvalds 	}
27753110ff80SHarvey Harrison 	dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
27761da177e4SLinus Torvalds 	return 0;
2777c0eae66eSBenny Halevy out_overflow:
2778c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2779c0eae66eSBenny Halevy 	return -EIO;
27801da177e4SLinus Torvalds }
27811da177e4SLinus Torvalds 
27821da177e4SLinus Torvalds static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
27831da177e4SLinus Torvalds {
27848687b63aSAl Viro 	__be32 *p;
27851da177e4SLinus Torvalds 
27861da177e4SLinus Torvalds 	*res = 0;
27871da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
27881da177e4SLinus Torvalds 		return -EIO;
27891da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
2790c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2791c0eae66eSBenny Halevy 		if (unlikely(!p))
2792c0eae66eSBenny Halevy 			goto out_overflow;
2793cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
27941da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
27951da177e4SLinus Torvalds 	}
27963110ff80SHarvey Harrison 	dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
27971da177e4SLinus Torvalds 	return 0;
2798c0eae66eSBenny Halevy out_overflow:
2799c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2800c0eae66eSBenny Halevy 	return -EIO;
28011da177e4SLinus Torvalds }
28021da177e4SLinus Torvalds 
28038b4bdcf8STrond Myklebust static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
28041da177e4SLinus Torvalds {
28058687b63aSAl Viro 	__be32 *p;
2806409924e4STrond Myklebust 	int ret = 0;
28071da177e4SLinus Torvalds 
28081da177e4SLinus Torvalds 	fsid->major = 0;
28091da177e4SLinus Torvalds 	fsid->minor = 0;
28101da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
28111da177e4SLinus Torvalds 		return -EIO;
28121da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
2813c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 16);
2814c0eae66eSBenny Halevy 		if (unlikely(!p))
2815c0eae66eSBenny Halevy 			goto out_overflow;
28163ceb4dbbSBenny Halevy 		p = xdr_decode_hyper(p, &fsid->major);
2817cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &fsid->minor);
28181da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FSID;
2819409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FSID;
28201da177e4SLinus Torvalds 	}
28213110ff80SHarvey Harrison 	dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
28221da177e4SLinus Torvalds 			(unsigned long long)fsid->major,
28231da177e4SLinus Torvalds 			(unsigned long long)fsid->minor);
2824409924e4STrond Myklebust 	return ret;
2825c0eae66eSBenny Halevy out_overflow:
2826c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2827c0eae66eSBenny Halevy 	return -EIO;
28281da177e4SLinus Torvalds }
28291da177e4SLinus Torvalds 
28301da177e4SLinus Torvalds static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
28311da177e4SLinus Torvalds {
28328687b63aSAl Viro 	__be32 *p;
28331da177e4SLinus Torvalds 
28341da177e4SLinus Torvalds 	*res = 60;
28351da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
28361da177e4SLinus Torvalds 		return -EIO;
28371da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
2838c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2839c0eae66eSBenny Halevy 		if (unlikely(!p))
2840c0eae66eSBenny Halevy 			goto out_overflow;
2841cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
28421da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
28431da177e4SLinus Torvalds 	}
28443110ff80SHarvey Harrison 	dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
28451da177e4SLinus Torvalds 	return 0;
2846c0eae66eSBenny Halevy out_overflow:
2847c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2848c0eae66eSBenny Halevy 	return -EIO;
28491da177e4SLinus Torvalds }
28501da177e4SLinus Torvalds 
28511da177e4SLinus Torvalds static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
28521da177e4SLinus Torvalds {
28538687b63aSAl Viro 	__be32 *p;
28541da177e4SLinus Torvalds 
28551da177e4SLinus Torvalds 	*res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
28561da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
28571da177e4SLinus Torvalds 		return -EIO;
28581da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
2859c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
2860c0eae66eSBenny Halevy 		if (unlikely(!p))
2861c0eae66eSBenny Halevy 			goto out_overflow;
2862cccddf4fSBenny Halevy 		*res = be32_to_cpup(p);
28631da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
28641da177e4SLinus Torvalds 	}
28653110ff80SHarvey Harrison 	dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
28661da177e4SLinus Torvalds 	return 0;
2867c0eae66eSBenny Halevy out_overflow:
2868c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2869c0eae66eSBenny Halevy 	return -EIO;
28701da177e4SLinus Torvalds }
28711da177e4SLinus Torvalds 
28721da177e4SLinus Torvalds static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
28731da177e4SLinus Torvalds {
28748687b63aSAl Viro 	__be32 *p;
2875409924e4STrond Myklebust 	int ret = 0;
28761da177e4SLinus Torvalds 
28771da177e4SLinus Torvalds 	*fileid = 0;
28781da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
28791da177e4SLinus Torvalds 		return -EIO;
28801da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
2881c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2882c0eae66eSBenny Halevy 		if (unlikely(!p))
2883c0eae66eSBenny Halevy 			goto out_overflow;
2884cccddf4fSBenny Halevy 		xdr_decode_hyper(p, fileid);
28851da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILEID;
2886409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FILEID;
28871da177e4SLinus Torvalds 	}
28883110ff80SHarvey Harrison 	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
2889409924e4STrond Myklebust 	return ret;
2890c0eae66eSBenny Halevy out_overflow:
2891c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2892c0eae66eSBenny Halevy 	return -EIO;
28931da177e4SLinus Torvalds }
28941da177e4SLinus Torvalds 
289599baf625SManoj Naik static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
289699baf625SManoj Naik {
28978687b63aSAl Viro 	__be32 *p;
2898409924e4STrond Myklebust 	int ret = 0;
289999baf625SManoj Naik 
290099baf625SManoj Naik 	*fileid = 0;
290199baf625SManoj Naik 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
290299baf625SManoj Naik 		return -EIO;
290399baf625SManoj Naik 	if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
2904c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2905c0eae66eSBenny Halevy 		if (unlikely(!p))
2906c0eae66eSBenny Halevy 			goto out_overflow;
2907cccddf4fSBenny Halevy 		xdr_decode_hyper(p, fileid);
290899baf625SManoj Naik 		bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
2909409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_FILEID;
291099baf625SManoj Naik 	}
29113110ff80SHarvey Harrison 	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
2912409924e4STrond Myklebust 	return ret;
2913c0eae66eSBenny Halevy out_overflow:
2914c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2915c0eae66eSBenny Halevy 	return -EIO;
291699baf625SManoj Naik }
291799baf625SManoj Naik 
29181da177e4SLinus Torvalds static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
29191da177e4SLinus Torvalds {
29208687b63aSAl Viro 	__be32 *p;
29211da177e4SLinus Torvalds 	int status = 0;
29221da177e4SLinus Torvalds 
29231da177e4SLinus Torvalds 	*res = 0;
29241da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
29251da177e4SLinus Torvalds 		return -EIO;
29261da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
2927c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2928c0eae66eSBenny Halevy 		if (unlikely(!p))
2929c0eae66eSBenny Halevy 			goto out_overflow;
2930cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
29311da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
29321da177e4SLinus Torvalds 	}
29333110ff80SHarvey Harrison 	dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
29341da177e4SLinus Torvalds 	return status;
2935c0eae66eSBenny Halevy out_overflow:
2936c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2937c0eae66eSBenny Halevy 	return -EIO;
29381da177e4SLinus Torvalds }
29391da177e4SLinus Torvalds 
29401da177e4SLinus Torvalds static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
29411da177e4SLinus Torvalds {
29428687b63aSAl Viro 	__be32 *p;
29431da177e4SLinus Torvalds 	int status = 0;
29441da177e4SLinus Torvalds 
29451da177e4SLinus Torvalds 	*res = 0;
29461da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
29471da177e4SLinus Torvalds 		return -EIO;
29481da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
2949c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2950c0eae66eSBenny Halevy 		if (unlikely(!p))
2951c0eae66eSBenny Halevy 			goto out_overflow;
2952cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
29531da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
29541da177e4SLinus Torvalds 	}
29553110ff80SHarvey Harrison 	dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
29561da177e4SLinus Torvalds 	return status;
2957c0eae66eSBenny Halevy out_overflow:
2958c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2959c0eae66eSBenny Halevy 	return -EIO;
29601da177e4SLinus Torvalds }
29611da177e4SLinus Torvalds 
29621da177e4SLinus Torvalds static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
29631da177e4SLinus Torvalds {
29648687b63aSAl Viro 	__be32 *p;
29651da177e4SLinus Torvalds 	int status = 0;
29661da177e4SLinus Torvalds 
29671da177e4SLinus Torvalds 	*res = 0;
29681da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
29691da177e4SLinus Torvalds 		return -EIO;
29701da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
2971c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
2972c0eae66eSBenny Halevy 		if (unlikely(!p))
2973c0eae66eSBenny Halevy 			goto out_overflow;
2974cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
29751da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
29761da177e4SLinus Torvalds 	}
29773110ff80SHarvey Harrison 	dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
29781da177e4SLinus Torvalds 	return status;
2979c0eae66eSBenny Halevy out_overflow:
2980c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
2981c0eae66eSBenny Halevy 	return -EIO;
29821da177e4SLinus Torvalds }
29831da177e4SLinus Torvalds 
29847aaa0b3bSManoj Naik static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
29857aaa0b3bSManoj Naik {
2986464ad6b1SChuck Lever 	u32 n;
29878687b63aSAl Viro 	__be32 *p;
29887aaa0b3bSManoj Naik 	int status = 0;
29897aaa0b3bSManoj Naik 
2990c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
2991c0eae66eSBenny Halevy 	if (unlikely(!p))
2992c0eae66eSBenny Halevy 		goto out_overflow;
2993cccddf4fSBenny Halevy 	n = be32_to_cpup(p);
299433a43f28SAndy Adamson 	if (n == 0)
299533a43f28SAndy Adamson 		goto root_path;
29967aaa0b3bSManoj Naik 	dprintk("path ");
29977aaa0b3bSManoj Naik 	path->ncomponents = 0;
29987aaa0b3bSManoj Naik 	while (path->ncomponents < n) {
29997aaa0b3bSManoj Naik 		struct nfs4_string *component = &path->components[path->ncomponents];
30007aaa0b3bSManoj Naik 		status = decode_opaque_inline(xdr, &component->len, &component->data);
30017aaa0b3bSManoj Naik 		if (unlikely(status != 0))
30027aaa0b3bSManoj Naik 			goto out_eio;
30037aaa0b3bSManoj Naik 		if (path->ncomponents != n)
30047aaa0b3bSManoj Naik 			dprintk("/");
30057aaa0b3bSManoj Naik 		dprintk("%s", component->data);
30067aaa0b3bSManoj Naik 		if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
30077aaa0b3bSManoj Naik 			path->ncomponents++;
30087aaa0b3bSManoj Naik 		else {
30097aaa0b3bSManoj Naik 			dprintk("cannot parse %d components in path\n", n);
30107aaa0b3bSManoj Naik 			goto out_eio;
30117aaa0b3bSManoj Naik 		}
30127aaa0b3bSManoj Naik 	}
30137aaa0b3bSManoj Naik out:
30147aaa0b3bSManoj Naik 	dprintk("\n");
30157aaa0b3bSManoj Naik 	return status;
301633a43f28SAndy Adamson root_path:
301733a43f28SAndy Adamson /* a root pathname is sent as a zero component4 */
301833a43f28SAndy Adamson 	path->ncomponents = 1;
301933a43f28SAndy Adamson 	path->components[0].len=0;
302033a43f28SAndy Adamson 	path->components[0].data=NULL;
302133a43f28SAndy Adamson 	dprintk("path /\n");
302233a43f28SAndy Adamson 	goto out;
30237aaa0b3bSManoj Naik out_eio:
30247aaa0b3bSManoj Naik 	dprintk(" status %d", status);
30257aaa0b3bSManoj Naik 	status = -EIO;
30267aaa0b3bSManoj Naik 	goto out;
3027c0eae66eSBenny Halevy out_overflow:
3028c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3029c0eae66eSBenny Halevy 	return -EIO;
30307aaa0b3bSManoj Naik }
30317aaa0b3bSManoj Naik 
30327aaa0b3bSManoj Naik static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
3033683b57b4STrond Myklebust {
3034683b57b4STrond Myklebust 	int n;
30358687b63aSAl Viro 	__be32 *p;
3036683b57b4STrond Myklebust 	int status = -EIO;
3037683b57b4STrond Myklebust 
3038683b57b4STrond Myklebust 	if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
3039683b57b4STrond Myklebust 		goto out;
3040683b57b4STrond Myklebust 	status = 0;
3041683b57b4STrond Myklebust 	if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
3042683b57b4STrond Myklebust 		goto out;
30433110ff80SHarvey Harrison 	dprintk("%s: fsroot ", __func__);
30447aaa0b3bSManoj Naik 	status = decode_pathname(xdr, &res->fs_path);
3045683b57b4STrond Myklebust 	if (unlikely(status != 0))
3046683b57b4STrond Myklebust 		goto out;
3047c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3048c0eae66eSBenny Halevy 	if (unlikely(!p))
3049c0eae66eSBenny Halevy 		goto out_overflow;
3050cccddf4fSBenny Halevy 	n = be32_to_cpup(p);
3051683b57b4STrond Myklebust 	if (n <= 0)
3052683b57b4STrond Myklebust 		goto out_eio;
3053683b57b4STrond Myklebust 	res->nlocations = 0;
3054683b57b4STrond Myklebust 	while (res->nlocations < n) {
3055464ad6b1SChuck Lever 		u32 m;
30567aaa0b3bSManoj Naik 		struct nfs4_fs_location *loc = &res->locations[res->nlocations];
3057683b57b4STrond Myklebust 
3058c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3059c0eae66eSBenny Halevy 		if (unlikely(!p))
3060c0eae66eSBenny Halevy 			goto out_overflow;
3061cccddf4fSBenny Halevy 		m = be32_to_cpup(p);
30627aaa0b3bSManoj Naik 
30637aaa0b3bSManoj Naik 		loc->nservers = 0;
30643110ff80SHarvey Harrison 		dprintk("%s: servers ", __func__);
30657aaa0b3bSManoj Naik 		while (loc->nservers < m) {
30667aaa0b3bSManoj Naik 			struct nfs4_string *server = &loc->servers[loc->nservers];
30677aaa0b3bSManoj Naik 			status = decode_opaque_inline(xdr, &server->len, &server->data);
3068683b57b4STrond Myklebust 			if (unlikely(status != 0))
3069683b57b4STrond Myklebust 				goto out_eio;
30707aaa0b3bSManoj Naik 			dprintk("%s ", server->data);
30717aaa0b3bSManoj Naik 			if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
30727aaa0b3bSManoj Naik 				loc->nservers++;
30737aaa0b3bSManoj Naik 			else {
3074464ad6b1SChuck Lever 				unsigned int i;
3075464ad6b1SChuck Lever 				dprintk("%s: using first %u of %u servers "
3076464ad6b1SChuck Lever 					"returned for location %u\n",
30773110ff80SHarvey Harrison 						__func__,
3078464ad6b1SChuck Lever 						NFS4_FS_LOCATION_MAXSERVERS,
3079464ad6b1SChuck Lever 						m, res->nlocations);
30807aaa0b3bSManoj Naik 				for (i = loc->nservers; i < m; i++) {
30812e42c3e2STrond Myklebust 					unsigned int len;
30827aaa0b3bSManoj Naik 					char *data;
30837aaa0b3bSManoj Naik 					status = decode_opaque_inline(xdr, &len, &data);
3084683b57b4STrond Myklebust 					if (unlikely(status != 0))
3085683b57b4STrond Myklebust 						goto out_eio;
30867aaa0b3bSManoj Naik 				}
30877aaa0b3bSManoj Naik 			}
30887aaa0b3bSManoj Naik 		}
30897aaa0b3bSManoj Naik 		status = decode_pathname(xdr, &loc->rootpath);
30907aaa0b3bSManoj Naik 		if (unlikely(status != 0))
30917aaa0b3bSManoj Naik 			goto out_eio;
30927aaa0b3bSManoj Naik 		if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
3093683b57b4STrond Myklebust 			res->nlocations++;
3094683b57b4STrond Myklebust 	}
3095409924e4STrond Myklebust 	if (res->nlocations != 0)
3096409924e4STrond Myklebust 		status = NFS_ATTR_FATTR_V4_REFERRAL;
3097683b57b4STrond Myklebust out:
30983110ff80SHarvey Harrison 	dprintk("%s: fs_locations done, error = %d\n", __func__, status);
3099683b57b4STrond Myklebust 	return status;
3100c0eae66eSBenny Halevy out_overflow:
3101c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3102683b57b4STrond Myklebust out_eio:
3103683b57b4STrond Myklebust 	status = -EIO;
3104683b57b4STrond Myklebust 	goto out;
3105683b57b4STrond Myklebust }
3106683b57b4STrond Myklebust 
31071da177e4SLinus Torvalds static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
31081da177e4SLinus Torvalds {
31098687b63aSAl Viro 	__be32 *p;
31101da177e4SLinus Torvalds 	int status = 0;
31111da177e4SLinus Torvalds 
31121da177e4SLinus Torvalds 	*res = 0;
31131da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
31141da177e4SLinus Torvalds 		return -EIO;
31151da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
3116c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3117c0eae66eSBenny Halevy 		if (unlikely(!p))
3118c0eae66eSBenny Halevy 			goto out_overflow;
3119cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
31201da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
31211da177e4SLinus Torvalds 	}
31223110ff80SHarvey Harrison 	dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
31231da177e4SLinus Torvalds 	return status;
3124c0eae66eSBenny Halevy out_overflow:
3125c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3126c0eae66eSBenny Halevy 	return -EIO;
31271da177e4SLinus Torvalds }
31281da177e4SLinus Torvalds 
31291da177e4SLinus Torvalds static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
31301da177e4SLinus Torvalds {
31318687b63aSAl Viro 	__be32 *p;
31321da177e4SLinus Torvalds 	int status = 0;
31331da177e4SLinus Torvalds 
31341da177e4SLinus Torvalds 	*maxlink = 1;
31351da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
31361da177e4SLinus Torvalds 		return -EIO;
31371da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
3138c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3139c0eae66eSBenny Halevy 		if (unlikely(!p))
3140c0eae66eSBenny Halevy 			goto out_overflow;
3141cccddf4fSBenny Halevy 		*maxlink = be32_to_cpup(p);
31421da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
31431da177e4SLinus Torvalds 	}
31443110ff80SHarvey Harrison 	dprintk("%s: maxlink=%u\n", __func__, *maxlink);
31451da177e4SLinus Torvalds 	return status;
3146c0eae66eSBenny Halevy out_overflow:
3147c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3148c0eae66eSBenny Halevy 	return -EIO;
31491da177e4SLinus Torvalds }
31501da177e4SLinus Torvalds 
31511da177e4SLinus Torvalds static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
31521da177e4SLinus Torvalds {
31538687b63aSAl Viro 	__be32 *p;
31541da177e4SLinus Torvalds 	int status = 0;
31551da177e4SLinus Torvalds 
31561da177e4SLinus Torvalds 	*maxname = 1024;
31571da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
31581da177e4SLinus Torvalds 		return -EIO;
31591da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
3160c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3161c0eae66eSBenny Halevy 		if (unlikely(!p))
3162c0eae66eSBenny Halevy 			goto out_overflow;
3163cccddf4fSBenny Halevy 		*maxname = be32_to_cpup(p);
31641da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
31651da177e4SLinus Torvalds 	}
31663110ff80SHarvey Harrison 	dprintk("%s: maxname=%u\n", __func__, *maxname);
31671da177e4SLinus Torvalds 	return status;
3168c0eae66eSBenny Halevy out_overflow:
3169c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3170c0eae66eSBenny Halevy 	return -EIO;
31711da177e4SLinus Torvalds }
31721da177e4SLinus Torvalds 
31731da177e4SLinus Torvalds static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
31741da177e4SLinus Torvalds {
31758687b63aSAl Viro 	__be32 *p;
31761da177e4SLinus Torvalds 	int status = 0;
31771da177e4SLinus Torvalds 
31781da177e4SLinus Torvalds 	*res = 1024;
31791da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
31801da177e4SLinus Torvalds 		return -EIO;
31811da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
31821da177e4SLinus Torvalds 		uint64_t maxread;
3183c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3184c0eae66eSBenny Halevy 		if (unlikely(!p))
3185c0eae66eSBenny Halevy 			goto out_overflow;
3186cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &maxread);
31871da177e4SLinus Torvalds 		if (maxread > 0x7FFFFFFF)
31881da177e4SLinus Torvalds 			maxread = 0x7FFFFFFF;
31891da177e4SLinus Torvalds 		*res = (uint32_t)maxread;
31901da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
31911da177e4SLinus Torvalds 	}
31923110ff80SHarvey Harrison 	dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
31931da177e4SLinus Torvalds 	return status;
3194c0eae66eSBenny Halevy out_overflow:
3195c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3196c0eae66eSBenny Halevy 	return -EIO;
31971da177e4SLinus Torvalds }
31981da177e4SLinus Torvalds 
31991da177e4SLinus Torvalds static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
32001da177e4SLinus Torvalds {
32018687b63aSAl Viro 	__be32 *p;
32021da177e4SLinus Torvalds 	int status = 0;
32031da177e4SLinus Torvalds 
32041da177e4SLinus Torvalds 	*res = 1024;
32051da177e4SLinus Torvalds 	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
32061da177e4SLinus Torvalds 		return -EIO;
32071da177e4SLinus Torvalds 	if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
32081da177e4SLinus Torvalds 		uint64_t maxwrite;
3209c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3210c0eae66eSBenny Halevy 		if (unlikely(!p))
3211c0eae66eSBenny Halevy 			goto out_overflow;
3212cccddf4fSBenny Halevy 		xdr_decode_hyper(p, &maxwrite);
32131da177e4SLinus Torvalds 		if (maxwrite > 0x7FFFFFFF)
32141da177e4SLinus Torvalds 			maxwrite = 0x7FFFFFFF;
32151da177e4SLinus Torvalds 		*res = (uint32_t)maxwrite;
32161da177e4SLinus Torvalds 		bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
32171da177e4SLinus Torvalds 	}
32183110ff80SHarvey Harrison 	dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
32191da177e4SLinus Torvalds 	return status;
3220c0eae66eSBenny Halevy out_overflow:
3221c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3222c0eae66eSBenny Halevy 	return -EIO;
32231da177e4SLinus Torvalds }
32241da177e4SLinus Torvalds 
3225bca79478STrond Myklebust static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
32261da177e4SLinus Torvalds {
3227bca79478STrond Myklebust 	uint32_t tmp;
32288687b63aSAl Viro 	__be32 *p;
3229409924e4STrond Myklebust 	int ret = 0;
32301da177e4SLinus Torvalds 
32311da177e4SLinus Torvalds 	*mode = 0;
32321da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
32331da177e4SLinus Torvalds 		return -EIO;
32341da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
3235c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3236c0eae66eSBenny Halevy 		if (unlikely(!p))
3237c0eae66eSBenny Halevy 			goto out_overflow;
3238cccddf4fSBenny Halevy 		tmp = be32_to_cpup(p);
3239bca79478STrond Myklebust 		*mode = tmp & ~S_IFMT;
32401da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_MODE;
3241409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_MODE;
32421da177e4SLinus Torvalds 	}
32433110ff80SHarvey Harrison 	dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
3244409924e4STrond Myklebust 	return ret;
3245c0eae66eSBenny Halevy out_overflow:
3246c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3247c0eae66eSBenny Halevy 	return -EIO;
32481da177e4SLinus Torvalds }
32491da177e4SLinus Torvalds 
32501da177e4SLinus Torvalds static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
32511da177e4SLinus Torvalds {
32528687b63aSAl Viro 	__be32 *p;
3253409924e4STrond Myklebust 	int ret = 0;
32541da177e4SLinus Torvalds 
32551da177e4SLinus Torvalds 	*nlink = 1;
32561da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
32571da177e4SLinus Torvalds 		return -EIO;
32581da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
3259c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3260c0eae66eSBenny Halevy 		if (unlikely(!p))
3261c0eae66eSBenny Halevy 			goto out_overflow;
3262cccddf4fSBenny Halevy 		*nlink = be32_to_cpup(p);
32631da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
3264409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_NLINK;
32651da177e4SLinus Torvalds 	}
32663110ff80SHarvey Harrison 	dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
3267409924e4STrond Myklebust 	return ret;
3268c0eae66eSBenny Halevy out_overflow:
3269c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3270c0eae66eSBenny Halevy 	return -EIO;
32711da177e4SLinus Torvalds }
32721da177e4SLinus Torvalds 
327380e52aceSTrond Myklebust static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
327480e52aceSTrond Myklebust 		struct nfs_client *clp, uint32_t *uid, int may_sleep)
32751da177e4SLinus Torvalds {
32768687b63aSAl Viro 	uint32_t len;
32778687b63aSAl Viro 	__be32 *p;
3278409924e4STrond Myklebust 	int ret = 0;
32791da177e4SLinus Torvalds 
32801da177e4SLinus Torvalds 	*uid = -2;
32811da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
32821da177e4SLinus Torvalds 		return -EIO;
32831da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
3284c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3285c0eae66eSBenny Halevy 		if (unlikely(!p))
3286c0eae66eSBenny Halevy 			goto out_overflow;
3287cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
3288c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
3289c0eae66eSBenny Halevy 		if (unlikely(!p))
3290c0eae66eSBenny Halevy 			goto out_overflow;
329180e52aceSTrond Myklebust 		if (!may_sleep) {
329280e52aceSTrond Myklebust 			/* do nothing */
329380e52aceSTrond Myklebust 		} else if (len < XDR_MAX_NETOBJ) {
3294409924e4STrond Myklebust 			if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0)
3295409924e4STrond Myklebust 				ret = NFS_ATTR_FATTR_OWNER;
3296409924e4STrond Myklebust 			else
32971da177e4SLinus Torvalds 				dprintk("%s: nfs_map_name_to_uid failed!\n",
32983110ff80SHarvey Harrison 						__func__);
32991da177e4SLinus Torvalds 		} else
3300fe82a183SChuck Lever 			dprintk("%s: name too long (%u)!\n",
33013110ff80SHarvey Harrison 					__func__, len);
33021da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_OWNER;
33031da177e4SLinus Torvalds 	}
33043110ff80SHarvey Harrison 	dprintk("%s: uid=%d\n", __func__, (int)*uid);
3305409924e4STrond Myklebust 	return ret;
3306c0eae66eSBenny Halevy out_overflow:
3307c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3308c0eae66eSBenny Halevy 	return -EIO;
33091da177e4SLinus Torvalds }
33101da177e4SLinus Torvalds 
331180e52aceSTrond Myklebust static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
331280e52aceSTrond Myklebust 		struct nfs_client *clp, uint32_t *gid, int may_sleep)
33131da177e4SLinus Torvalds {
33148687b63aSAl Viro 	uint32_t len;
33158687b63aSAl Viro 	__be32 *p;
3316409924e4STrond Myklebust 	int ret = 0;
33171da177e4SLinus Torvalds 
33181da177e4SLinus Torvalds 	*gid = -2;
33191da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
33201da177e4SLinus Torvalds 		return -EIO;
33211da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
3322c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
3323c0eae66eSBenny Halevy 		if (unlikely(!p))
3324c0eae66eSBenny Halevy 			goto out_overflow;
3325cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
3326c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
3327c0eae66eSBenny Halevy 		if (unlikely(!p))
3328c0eae66eSBenny Halevy 			goto out_overflow;
332980e52aceSTrond Myklebust 		if (!may_sleep) {
333080e52aceSTrond Myklebust 			/* do nothing */
333180e52aceSTrond Myklebust 		} else if (len < XDR_MAX_NETOBJ) {
3332409924e4STrond Myklebust 			if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0)
3333409924e4STrond Myklebust 				ret = NFS_ATTR_FATTR_GROUP;
3334409924e4STrond Myklebust 			else
33351da177e4SLinus Torvalds 				dprintk("%s: nfs_map_group_to_gid failed!\n",
33363110ff80SHarvey Harrison 						__func__);
33371da177e4SLinus Torvalds 		} else
3338fe82a183SChuck Lever 			dprintk("%s: name too long (%u)!\n",
33393110ff80SHarvey Harrison 					__func__, len);
33401da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
33411da177e4SLinus Torvalds 	}
33423110ff80SHarvey Harrison 	dprintk("%s: gid=%d\n", __func__, (int)*gid);
3343409924e4STrond Myklebust 	return ret;
3344c0eae66eSBenny Halevy out_overflow:
3345c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3346c0eae66eSBenny Halevy 	return -EIO;
33471da177e4SLinus Torvalds }
33481da177e4SLinus Torvalds 
33491da177e4SLinus Torvalds static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
33501da177e4SLinus Torvalds {
33518687b63aSAl Viro 	uint32_t major = 0, minor = 0;
33528687b63aSAl Viro 	__be32 *p;
3353409924e4STrond Myklebust 	int ret = 0;
33541da177e4SLinus Torvalds 
33551da177e4SLinus Torvalds 	*rdev = MKDEV(0,0);
33561da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
33571da177e4SLinus Torvalds 		return -EIO;
33581da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
33591da177e4SLinus Torvalds 		dev_t tmp;
33601da177e4SLinus Torvalds 
3361c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3362c0eae66eSBenny Halevy 		if (unlikely(!p))
3363c0eae66eSBenny Halevy 			goto out_overflow;
33646f723f77SBenny Halevy 		major = be32_to_cpup(p++);
3365cccddf4fSBenny Halevy 		minor = be32_to_cpup(p);
33661da177e4SLinus Torvalds 		tmp = MKDEV(major, minor);
33671da177e4SLinus Torvalds 		if (MAJOR(tmp) == major && MINOR(tmp) == minor)
33681da177e4SLinus Torvalds 			*rdev = tmp;
33691da177e4SLinus Torvalds 		bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
3370409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_RDEV;
33711da177e4SLinus Torvalds 	}
33723110ff80SHarvey Harrison 	dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
3373409924e4STrond Myklebust 	return ret;
3374c0eae66eSBenny Halevy out_overflow:
3375c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3376c0eae66eSBenny Halevy 	return -EIO;
33771da177e4SLinus Torvalds }
33781da177e4SLinus Torvalds 
33791da177e4SLinus Torvalds static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
33801da177e4SLinus Torvalds {
33818687b63aSAl Viro 	__be32 *p;
33821da177e4SLinus Torvalds 	int status = 0;
33831da177e4SLinus Torvalds 
33841da177e4SLinus Torvalds 	*res = 0;
33851da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
33861da177e4SLinus Torvalds 		return -EIO;
33871da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
3388c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3389c0eae66eSBenny Halevy 		if (unlikely(!p))
3390c0eae66eSBenny Halevy 			goto out_overflow;
3391cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
33921da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
33931da177e4SLinus Torvalds 	}
33943110ff80SHarvey Harrison 	dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
33951da177e4SLinus Torvalds 	return status;
3396c0eae66eSBenny Halevy out_overflow:
3397c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3398c0eae66eSBenny Halevy 	return -EIO;
33991da177e4SLinus Torvalds }
34001da177e4SLinus Torvalds 
34011da177e4SLinus Torvalds static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
34021da177e4SLinus Torvalds {
34038687b63aSAl Viro 	__be32 *p;
34041da177e4SLinus Torvalds 	int status = 0;
34051da177e4SLinus Torvalds 
34061da177e4SLinus Torvalds 	*res = 0;
34071da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
34081da177e4SLinus Torvalds 		return -EIO;
34091da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
3410c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3411c0eae66eSBenny Halevy 		if (unlikely(!p))
3412c0eae66eSBenny Halevy 			goto out_overflow;
3413cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
34141da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
34151da177e4SLinus Torvalds 	}
34163110ff80SHarvey Harrison 	dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
34171da177e4SLinus Torvalds 	return status;
3418c0eae66eSBenny Halevy out_overflow:
3419c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3420c0eae66eSBenny Halevy 	return -EIO;
34211da177e4SLinus Torvalds }
34221da177e4SLinus Torvalds 
34231da177e4SLinus Torvalds static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
34241da177e4SLinus Torvalds {
34258687b63aSAl Viro 	__be32 *p;
34261da177e4SLinus Torvalds 	int status = 0;
34271da177e4SLinus Torvalds 
34281da177e4SLinus Torvalds 	*res = 0;
34291da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
34301da177e4SLinus Torvalds 		return -EIO;
34311da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
3432c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3433c0eae66eSBenny Halevy 		if (unlikely(!p))
3434c0eae66eSBenny Halevy 			goto out_overflow;
3435cccddf4fSBenny Halevy 		xdr_decode_hyper(p, res);
34361da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
34371da177e4SLinus Torvalds 	}
34383110ff80SHarvey Harrison 	dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
34391da177e4SLinus Torvalds 	return status;
3440c0eae66eSBenny Halevy out_overflow:
3441c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3442c0eae66eSBenny Halevy 	return -EIO;
34431da177e4SLinus Torvalds }
34441da177e4SLinus Torvalds 
34451da177e4SLinus Torvalds static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
34461da177e4SLinus Torvalds {
34478687b63aSAl Viro 	__be32 *p;
3448409924e4STrond Myklebust 	int ret = 0;
34491da177e4SLinus Torvalds 
34501da177e4SLinus Torvalds 	*used = 0;
34511da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
34521da177e4SLinus Torvalds 		return -EIO;
34531da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
3454c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8);
3455c0eae66eSBenny Halevy 		if (unlikely(!p))
3456c0eae66eSBenny Halevy 			goto out_overflow;
3457cccddf4fSBenny Halevy 		xdr_decode_hyper(p, used);
34581da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
3459409924e4STrond Myklebust 		ret = NFS_ATTR_FATTR_SPACE_USED;
34601da177e4SLinus Torvalds 	}
34613110ff80SHarvey Harrison 	dprintk("%s: space used=%Lu\n", __func__,
34621da177e4SLinus Torvalds 			(unsigned long long)*used);
3463409924e4STrond Myklebust 	return ret;
3464c0eae66eSBenny Halevy out_overflow:
3465c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3466c0eae66eSBenny Halevy 	return -EIO;
34671da177e4SLinus Torvalds }
34681da177e4SLinus Torvalds 
34691da177e4SLinus Torvalds static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
34701da177e4SLinus Torvalds {
34718687b63aSAl Viro 	__be32 *p;
34721da177e4SLinus Torvalds 	uint64_t sec;
34731da177e4SLinus Torvalds 	uint32_t nsec;
34741da177e4SLinus Torvalds 
3475c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
3476c0eae66eSBenny Halevy 	if (unlikely(!p))
3477c0eae66eSBenny Halevy 		goto out_overflow;
34783ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &sec);
3479cccddf4fSBenny Halevy 	nsec = be32_to_cpup(p);
34801da177e4SLinus Torvalds 	time->tv_sec = (time_t)sec;
34811da177e4SLinus Torvalds 	time->tv_nsec = (long)nsec;
34821da177e4SLinus Torvalds 	return 0;
3483c0eae66eSBenny Halevy out_overflow:
3484c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3485c0eae66eSBenny Halevy 	return -EIO;
34861da177e4SLinus Torvalds }
34871da177e4SLinus Torvalds 
34881da177e4SLinus Torvalds static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
34891da177e4SLinus Torvalds {
34901da177e4SLinus Torvalds 	int status = 0;
34911da177e4SLinus Torvalds 
34921da177e4SLinus Torvalds 	time->tv_sec = 0;
34931da177e4SLinus Torvalds 	time->tv_nsec = 0;
34941da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
34951da177e4SLinus Torvalds 		return -EIO;
34961da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
34971da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3498409924e4STrond Myklebust 		if (status == 0)
3499409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_ATIME;
35001da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
35011da177e4SLinus Torvalds 	}
35023110ff80SHarvey Harrison 	dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec);
35031da177e4SLinus Torvalds 	return status;
35041da177e4SLinus Torvalds }
35051da177e4SLinus Torvalds 
35061da177e4SLinus Torvalds static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
35071da177e4SLinus Torvalds {
35081da177e4SLinus Torvalds 	int status = 0;
35091da177e4SLinus Torvalds 
35101da177e4SLinus Torvalds 	time->tv_sec = 0;
35111da177e4SLinus Torvalds 	time->tv_nsec = 0;
35121da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
35131da177e4SLinus Torvalds 		return -EIO;
35141da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
35151da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3516409924e4STrond Myklebust 		if (status == 0)
3517409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_CTIME;
35181da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
35191da177e4SLinus Torvalds 	}
35203110ff80SHarvey Harrison 	dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec);
35211da177e4SLinus Torvalds 	return status;
35221da177e4SLinus Torvalds }
35231da177e4SLinus Torvalds 
35241da177e4SLinus Torvalds static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
35251da177e4SLinus Torvalds {
35261da177e4SLinus Torvalds 	int status = 0;
35271da177e4SLinus Torvalds 
35281da177e4SLinus Torvalds 	time->tv_sec = 0;
35291da177e4SLinus Torvalds 	time->tv_nsec = 0;
35301da177e4SLinus Torvalds 	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
35311da177e4SLinus Torvalds 		return -EIO;
35321da177e4SLinus Torvalds 	if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
35331da177e4SLinus Torvalds 		status = decode_attr_time(xdr, time);
3534409924e4STrond Myklebust 		if (status == 0)
3535409924e4STrond Myklebust 			status = NFS_ATTR_FATTR_MTIME;
35361da177e4SLinus Torvalds 		bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
35371da177e4SLinus Torvalds 	}
35383110ff80SHarvey Harrison 	dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec);
35391da177e4SLinus Torvalds 	return status;
35401da177e4SLinus Torvalds }
35411da177e4SLinus Torvalds 
35428687b63aSAl Viro static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
35431da177e4SLinus Torvalds {
35441da177e4SLinus Torvalds 	unsigned int attrwords = XDR_QUADLEN(attrlen);
35451da177e4SLinus Torvalds 	unsigned int nwords = xdr->p - savep;
35461da177e4SLinus Torvalds 
35471da177e4SLinus Torvalds 	if (unlikely(attrwords != nwords)) {
3548fe82a183SChuck Lever 		dprintk("%s: server returned incorrect attribute length: "
3549fe82a183SChuck Lever 			"%u %c %u\n",
35503110ff80SHarvey Harrison 				__func__,
35511da177e4SLinus Torvalds 				attrwords << 2,
35521da177e4SLinus Torvalds 				(attrwords < nwords) ? '<' : '>',
35531da177e4SLinus Torvalds 				nwords << 2);
35541da177e4SLinus Torvalds 		return -EIO;
35551da177e4SLinus Torvalds 	}
35561da177e4SLinus Torvalds 	return 0;
35571da177e4SLinus Torvalds }
35581da177e4SLinus Torvalds 
35591da177e4SLinus Torvalds static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
35601da177e4SLinus Torvalds {
35618687b63aSAl Viro 	__be32 *p;
35621da177e4SLinus Torvalds 
3563c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 20);
3564c0eae66eSBenny Halevy 	if (unlikely(!p))
3565c0eae66eSBenny Halevy 		goto out_overflow;
35666f723f77SBenny Halevy 	cinfo->atomic = be32_to_cpup(p++);
35673ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &cinfo->before);
3568cccddf4fSBenny Halevy 	xdr_decode_hyper(p, &cinfo->after);
35691da177e4SLinus Torvalds 	return 0;
3570c0eae66eSBenny Halevy out_overflow:
3571c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3572c0eae66eSBenny Halevy 	return -EIO;
35731da177e4SLinus Torvalds }
35741da177e4SLinus Torvalds 
35751da177e4SLinus Torvalds static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
35761da177e4SLinus Torvalds {
35778687b63aSAl Viro 	__be32 *p;
35781da177e4SLinus Torvalds 	uint32_t supp, acc;
35791da177e4SLinus Torvalds 	int status;
35801da177e4SLinus Torvalds 
35811da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_ACCESS);
35821da177e4SLinus Torvalds 	if (status)
35831da177e4SLinus Torvalds 		return status;
3584c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
3585c0eae66eSBenny Halevy 	if (unlikely(!p))
3586c0eae66eSBenny Halevy 		goto out_overflow;
35876f723f77SBenny Halevy 	supp = be32_to_cpup(p++);
3588cccddf4fSBenny Halevy 	acc = be32_to_cpup(p);
35891da177e4SLinus Torvalds 	access->supported = supp;
35901da177e4SLinus Torvalds 	access->access = acc;
35911da177e4SLinus Torvalds 	return 0;
3592c0eae66eSBenny Halevy out_overflow:
3593c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3594c0eae66eSBenny Halevy 	return -EIO;
35951da177e4SLinus Torvalds }
35961da177e4SLinus Torvalds 
359707d30434SBenny Halevy static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
35981da177e4SLinus Torvalds {
35998687b63aSAl Viro 	__be32 *p;
360007d30434SBenny Halevy 
360107d30434SBenny Halevy 	p = xdr_inline_decode(xdr, len);
360207d30434SBenny Halevy 	if (likely(p)) {
360307d30434SBenny Halevy 		memcpy(buf, p, len);
360407d30434SBenny Halevy 		return 0;
360507d30434SBenny Halevy 	}
360607d30434SBenny Halevy 	print_overflow_msg(__func__, xdr);
360707d30434SBenny Halevy 	return -EIO;
360807d30434SBenny Halevy }
360907d30434SBenny Halevy 
361007d30434SBenny Halevy static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
361107d30434SBenny Halevy {
361207d30434SBenny Halevy 	return decode_opaque_fixed(xdr, stateid->data, NFS4_STATEID_SIZE);
36131da177e4SLinus Torvalds }
36141da177e4SLinus Torvalds 
36151da177e4SLinus Torvalds static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
36161da177e4SLinus Torvalds {
36171da177e4SLinus Torvalds 	int status;
36181da177e4SLinus Torvalds 
36191da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_CLOSE);
3620c1d51931STrond Myklebust 	if (status != -EIO)
3621c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
362207d30434SBenny Halevy 	if (!status)
362307d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
36241da177e4SLinus Torvalds 	return status;
36251da177e4SLinus Torvalds }
36261da177e4SLinus Torvalds 
3627db942bbdSBenny Halevy static int decode_verifier(struct xdr_stream *xdr, void *verifier)
3628db942bbdSBenny Halevy {
3629db942bbdSBenny Halevy 	return decode_opaque_fixed(xdr, verifier, 8);
36301da177e4SLinus Torvalds }
36311da177e4SLinus Torvalds 
36321da177e4SLinus Torvalds static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
36331da177e4SLinus Torvalds {
36341da177e4SLinus Torvalds 	int status;
36351da177e4SLinus Torvalds 
36361da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_COMMIT);
3637db942bbdSBenny Halevy 	if (!status)
3638db942bbdSBenny Halevy 		status = decode_verifier(xdr, res->verf->verifier);
36391da177e4SLinus Torvalds 	return status;
36401da177e4SLinus Torvalds }
36411da177e4SLinus Torvalds 
36421da177e4SLinus Torvalds static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
36431da177e4SLinus Torvalds {
36448687b63aSAl Viro 	__be32 *p;
36451da177e4SLinus Torvalds 	uint32_t bmlen;
36461da177e4SLinus Torvalds 	int status;
36471da177e4SLinus Torvalds 
36481da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_CREATE);
36491da177e4SLinus Torvalds 	if (status)
36501da177e4SLinus Torvalds 		return status;
36511da177e4SLinus Torvalds 	if ((status = decode_change_info(xdr, cinfo)))
36521da177e4SLinus Torvalds 		return status;
3653c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3654c0eae66eSBenny Halevy 	if (unlikely(!p))
3655c0eae66eSBenny Halevy 		goto out_overflow;
3656cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
3657c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
3658c0eae66eSBenny Halevy 	if (likely(p))
36591da177e4SLinus Torvalds 		return 0;
3660c0eae66eSBenny Halevy out_overflow:
3661c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3662c0eae66eSBenny Halevy 	return -EIO;
36631da177e4SLinus Torvalds }
36641da177e4SLinus Torvalds 
36651da177e4SLinus Torvalds static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
36661da177e4SLinus Torvalds {
36678687b63aSAl Viro 	__be32 *savep;
36686c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
36691da177e4SLinus Torvalds 	int status;
36701da177e4SLinus Torvalds 
36711da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
36721da177e4SLinus Torvalds 		goto xdr_error;
36731da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
36741da177e4SLinus Torvalds 		goto xdr_error;
36751da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
36761da177e4SLinus Torvalds 		goto xdr_error;
36771da177e4SLinus Torvalds 	if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
36781da177e4SLinus Torvalds 		goto xdr_error;
36791da177e4SLinus Torvalds 	if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
36801da177e4SLinus Torvalds 		goto xdr_error;
36811da177e4SLinus Torvalds 	if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
36821da177e4SLinus Torvalds 		goto xdr_error;
36831da177e4SLinus Torvalds 	if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
36841da177e4SLinus Torvalds 		goto xdr_error;
36851da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
36861da177e4SLinus Torvalds xdr_error:
36873110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
36881da177e4SLinus Torvalds 	return status;
36891da177e4SLinus Torvalds }
36901da177e4SLinus Torvalds 
36911da177e4SLinus Torvalds static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
36921da177e4SLinus Torvalds {
36938687b63aSAl Viro 	__be32 *savep;
36946c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
36951da177e4SLinus Torvalds 	int status;
36961da177e4SLinus Torvalds 
36971da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
36981da177e4SLinus Torvalds 		goto xdr_error;
36991da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
37001da177e4SLinus Torvalds 		goto xdr_error;
37011da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
37021da177e4SLinus Torvalds 		goto xdr_error;
37031da177e4SLinus Torvalds 
37041da177e4SLinus Torvalds 	if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
37051da177e4SLinus Torvalds 		goto xdr_error;
37061da177e4SLinus Torvalds 	if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
37071da177e4SLinus Torvalds 		goto xdr_error;
37081da177e4SLinus Torvalds 	if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
37091da177e4SLinus Torvalds 		goto xdr_error;
37101da177e4SLinus Torvalds 	if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
37111da177e4SLinus Torvalds 		goto xdr_error;
37121da177e4SLinus Torvalds 	if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
37131da177e4SLinus Torvalds 		goto xdr_error;
37141da177e4SLinus Torvalds 	if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
37151da177e4SLinus Torvalds 		goto xdr_error;
37161da177e4SLinus Torvalds 
37171da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
37181da177e4SLinus Torvalds xdr_error:
37193110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
37201da177e4SLinus Torvalds 	return status;
37211da177e4SLinus Torvalds }
37221da177e4SLinus Torvalds 
37231da177e4SLinus Torvalds static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
37241da177e4SLinus Torvalds {
37258687b63aSAl Viro 	__be32 *savep;
37266c0195a4SAndy Adamson 	uint32_t attrlen, bitmap[2] = {0};
37271da177e4SLinus Torvalds 	int status;
37281da177e4SLinus Torvalds 
37291da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
37301da177e4SLinus Torvalds 		goto xdr_error;
37311da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
37321da177e4SLinus Torvalds 		goto xdr_error;
37331da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
37341da177e4SLinus Torvalds 		goto xdr_error;
37351da177e4SLinus Torvalds 
37361da177e4SLinus Torvalds 	if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
37371da177e4SLinus Torvalds 		goto xdr_error;
37381da177e4SLinus Torvalds 	if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
37391da177e4SLinus Torvalds 		goto xdr_error;
37401da177e4SLinus Torvalds 
37411da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
37421da177e4SLinus Torvalds xdr_error:
37433110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
37441da177e4SLinus Torvalds 	return status;
37451da177e4SLinus Torvalds }
37461da177e4SLinus Torvalds 
374780e52aceSTrond Myklebust static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
374880e52aceSTrond Myklebust 		const struct nfs_server *server, int may_sleep)
37491da177e4SLinus Torvalds {
37508687b63aSAl Viro 	__be32 *savep;
37511da177e4SLinus Torvalds 	uint32_t attrlen,
37521da177e4SLinus Torvalds 		 bitmap[2] = {0},
37531da177e4SLinus Torvalds 		 type;
3754bca79478STrond Myklebust 	int status;
3755bca79478STrond Myklebust 	umode_t fmode = 0;
375699baf625SManoj Naik 	uint64_t fileid;
37571da177e4SLinus Torvalds 
3758f26c7a78STrond Myklebust 	status = decode_op_hdr(xdr, OP_GETATTR);
3759f26c7a78STrond Myklebust 	if (status < 0)
37601da177e4SLinus Torvalds 		goto xdr_error;
37611da177e4SLinus Torvalds 
3762f26c7a78STrond Myklebust 	status = decode_attr_bitmap(xdr, bitmap);
3763f26c7a78STrond Myklebust 	if (status < 0)
3764f26c7a78STrond Myklebust 		goto xdr_error;
3765f26c7a78STrond Myklebust 
3766f26c7a78STrond Myklebust 	status = decode_attr_length(xdr, &attrlen, &savep);
3767f26c7a78STrond Myklebust 	if (status < 0)
37681da177e4SLinus Torvalds 		goto xdr_error;
37691da177e4SLinus Torvalds 
37701da177e4SLinus Torvalds 
3771f26c7a78STrond Myklebust 	status = decode_attr_type(xdr, bitmap, &type);
3772f26c7a78STrond Myklebust 	if (status < 0)
37731da177e4SLinus Torvalds 		goto xdr_error;
3774409924e4STrond Myklebust 	fattr->mode = 0;
3775409924e4STrond Myklebust 	if (status != 0) {
3776409924e4STrond Myklebust 		fattr->mode |= nfs_type2fmt[type];
3777409924e4STrond Myklebust 		fattr->valid |= status;
3778409924e4STrond Myklebust 	}
37791da177e4SLinus Torvalds 
3780f26c7a78STrond Myklebust 	status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
3781f26c7a78STrond Myklebust 	if (status < 0)
37821da177e4SLinus Torvalds 		goto xdr_error;
3783409924e4STrond Myklebust 	fattr->valid |= status;
3784f26c7a78STrond Myklebust 
3785f26c7a78STrond Myklebust 	status = decode_attr_size(xdr, bitmap, &fattr->size);
3786f26c7a78STrond Myklebust 	if (status < 0)
37871da177e4SLinus Torvalds 		goto xdr_error;
3788409924e4STrond Myklebust 	fattr->valid |= status;
3789f26c7a78STrond Myklebust 
3790f26c7a78STrond Myklebust 	status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
3791f26c7a78STrond Myklebust 	if (status < 0)
37921da177e4SLinus Torvalds 		goto xdr_error;
3793409924e4STrond Myklebust 	fattr->valid |= status;
3794f26c7a78STrond Myklebust 
3795f26c7a78STrond Myklebust 	status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
3796f26c7a78STrond Myklebust 	if (status < 0)
37971da177e4SLinus Torvalds 		goto xdr_error;
3798409924e4STrond Myklebust 	fattr->valid |= status;
3799f26c7a78STrond Myklebust 
3800f26c7a78STrond Myklebust 	status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
38017aaa0b3bSManoj Naik 						struct nfs4_fs_locations,
3802f26c7a78STrond Myklebust 						fattr));
3803f26c7a78STrond Myklebust 	if (status < 0)
3804683b57b4STrond Myklebust 		goto xdr_error;
3805409924e4STrond Myklebust 	fattr->valid |= status;
3806f26c7a78STrond Myklebust 
3807f26c7a78STrond Myklebust 	status = decode_attr_mode(xdr, bitmap, &fmode);
3808f26c7a78STrond Myklebust 	if (status < 0)
38091da177e4SLinus Torvalds 		goto xdr_error;
3810409924e4STrond Myklebust 	if (status != 0) {
38111da177e4SLinus Torvalds 		fattr->mode |= fmode;
3812409924e4STrond Myklebust 		fattr->valid |= status;
3813409924e4STrond Myklebust 	}
3814f26c7a78STrond Myklebust 
3815f26c7a78STrond Myklebust 	status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
3816f26c7a78STrond Myklebust 	if (status < 0)
38171da177e4SLinus Torvalds 		goto xdr_error;
3818409924e4STrond Myklebust 	fattr->valid |= status;
3819f26c7a78STrond Myklebust 
382080e52aceSTrond Myklebust 	status = decode_attr_owner(xdr, bitmap, server->nfs_client,
382180e52aceSTrond Myklebust 			&fattr->uid, may_sleep);
3822f26c7a78STrond Myklebust 	if (status < 0)
38231da177e4SLinus Torvalds 		goto xdr_error;
3824409924e4STrond Myklebust 	fattr->valid |= status;
3825f26c7a78STrond Myklebust 
382680e52aceSTrond Myklebust 	status = decode_attr_group(xdr, bitmap, server->nfs_client,
382780e52aceSTrond Myklebust 			&fattr->gid, may_sleep);
3828f26c7a78STrond Myklebust 	if (status < 0)
38291da177e4SLinus Torvalds 		goto xdr_error;
3830409924e4STrond Myklebust 	fattr->valid |= status;
3831f26c7a78STrond Myklebust 
3832f26c7a78STrond Myklebust 	status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
3833f26c7a78STrond Myklebust 	if (status < 0)
38341da177e4SLinus Torvalds 		goto xdr_error;
3835409924e4STrond Myklebust 	fattr->valid |= status;
3836f26c7a78STrond Myklebust 
3837f26c7a78STrond Myklebust 	status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
3838f26c7a78STrond Myklebust 	if (status < 0)
38391da177e4SLinus Torvalds 		goto xdr_error;
3840409924e4STrond Myklebust 	fattr->valid |= status;
3841f26c7a78STrond Myklebust 
3842f26c7a78STrond Myklebust 	status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
3843f26c7a78STrond Myklebust 	if (status < 0)
38441da177e4SLinus Torvalds 		goto xdr_error;
3845409924e4STrond Myklebust 	fattr->valid |= status;
3846f26c7a78STrond Myklebust 
3847f26c7a78STrond Myklebust 	status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
3848f26c7a78STrond Myklebust 	if (status < 0)
38491da177e4SLinus Torvalds 		goto xdr_error;
3850409924e4STrond Myklebust 	fattr->valid |= status;
3851f26c7a78STrond Myklebust 
3852f26c7a78STrond Myklebust 	status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
3853f26c7a78STrond Myklebust 	if (status < 0)
38541da177e4SLinus Torvalds 		goto xdr_error;
3855409924e4STrond Myklebust 	fattr->valid |= status;
3856f26c7a78STrond Myklebust 
3857f26c7a78STrond Myklebust 	status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid);
3858f26c7a78STrond Myklebust 	if (status < 0)
385999baf625SManoj Naik 		goto xdr_error;
3860409924e4STrond Myklebust 	if (status != 0 && !(fattr->valid & status)) {
386199baf625SManoj Naik 		fattr->fileid = fileid;
3862409924e4STrond Myklebust 		fattr->valid |= status;
3863409924e4STrond Myklebust 	}
3864f26c7a78STrond Myklebust 
3865f26c7a78STrond Myklebust 	status = verify_attr_len(xdr, savep, attrlen);
38661da177e4SLinus Torvalds xdr_error:
38673110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d\n", __func__, -status);
38681da177e4SLinus Torvalds 	return status;
38691da177e4SLinus Torvalds }
38701da177e4SLinus Torvalds 
38711da177e4SLinus Torvalds 
38721da177e4SLinus Torvalds static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
38731da177e4SLinus Torvalds {
38748687b63aSAl Viro 	__be32 *savep;
38751da177e4SLinus Torvalds 	uint32_t attrlen, bitmap[2];
38761da177e4SLinus Torvalds 	int status;
38771da177e4SLinus Torvalds 
38781da177e4SLinus Torvalds 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
38791da177e4SLinus Torvalds 		goto xdr_error;
38801da177e4SLinus Torvalds 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
38811da177e4SLinus Torvalds 		goto xdr_error;
38821da177e4SLinus Torvalds 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
38831da177e4SLinus Torvalds 		goto xdr_error;
38841da177e4SLinus Torvalds 
38851da177e4SLinus Torvalds 	fsinfo->rtmult = fsinfo->wtmult = 512;	/* ??? */
38861da177e4SLinus Torvalds 
38871da177e4SLinus Torvalds 	if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
38881da177e4SLinus Torvalds 		goto xdr_error;
38891da177e4SLinus Torvalds 	if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
38901da177e4SLinus Torvalds 		goto xdr_error;
38911da177e4SLinus Torvalds 	if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
38921da177e4SLinus Torvalds 		goto xdr_error;
38931da177e4SLinus Torvalds 	fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
38941da177e4SLinus Torvalds 	if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
38951da177e4SLinus Torvalds 		goto xdr_error;
38961da177e4SLinus Torvalds 	fsinfo->wtpref = fsinfo->wtmax;
38971da177e4SLinus Torvalds 
38981da177e4SLinus Torvalds 	status = verify_attr_len(xdr, savep, attrlen);
38991da177e4SLinus Torvalds xdr_error:
39003110ff80SHarvey Harrison 	dprintk("%s: xdr returned %d!\n", __func__, -status);
39011da177e4SLinus Torvalds 	return status;
39021da177e4SLinus Torvalds }
39031da177e4SLinus Torvalds 
39041da177e4SLinus Torvalds static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
39051da177e4SLinus Torvalds {
39068687b63aSAl Viro 	__be32 *p;
39071da177e4SLinus Torvalds 	uint32_t len;
39081da177e4SLinus Torvalds 	int status;
39091da177e4SLinus Torvalds 
39109936781dSTrond Myklebust 	/* Zero handle first to allow comparisons */
39119936781dSTrond Myklebust 	memset(fh, 0, sizeof(*fh));
39129936781dSTrond Myklebust 
39131da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_GETFH);
39141da177e4SLinus Torvalds 	if (status)
39151da177e4SLinus Torvalds 		return status;
39161da177e4SLinus Torvalds 
3917c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
3918c0eae66eSBenny Halevy 	if (unlikely(!p))
3919c0eae66eSBenny Halevy 		goto out_overflow;
3920cccddf4fSBenny Halevy 	len = be32_to_cpup(p);
39211da177e4SLinus Torvalds 	if (len > NFS4_FHSIZE)
39221da177e4SLinus Torvalds 		return -EIO;
39231da177e4SLinus Torvalds 	fh->size = len;
3924c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, len);
3925c0eae66eSBenny Halevy 	if (unlikely(!p))
3926c0eae66eSBenny Halevy 		goto out_overflow;
392799398d06SBenny Halevy 	memcpy(fh->data, p, len);
39281da177e4SLinus Torvalds 	return 0;
3929c0eae66eSBenny Halevy out_overflow:
3930c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3931c0eae66eSBenny Halevy 	return -EIO;
39321da177e4SLinus Torvalds }
39331da177e4SLinus Torvalds 
39341da177e4SLinus Torvalds static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
39351da177e4SLinus Torvalds {
39361da177e4SLinus Torvalds 	int status;
39371da177e4SLinus Torvalds 
39381da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LINK);
39391da177e4SLinus Torvalds 	if (status)
39401da177e4SLinus Torvalds 		return status;
39411da177e4SLinus Torvalds 	return decode_change_info(xdr, cinfo);
39421da177e4SLinus Torvalds }
39431da177e4SLinus Torvalds 
39441da177e4SLinus Torvalds /*
39451da177e4SLinus Torvalds  * We create the owner, so we know a proper owner.id length is 4.
39461da177e4SLinus Torvalds  */
3947911d1aafSTrond Myklebust static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
39481da177e4SLinus Torvalds {
3949911d1aafSTrond Myklebust 	uint64_t offset, length, clientid;
39508687b63aSAl Viro 	__be32 *p;
3951911d1aafSTrond Myklebust 	uint32_t namelen, type;
39521da177e4SLinus Torvalds 
3953c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 32);
3954c0eae66eSBenny Halevy 	if (unlikely(!p))
3955c0eae66eSBenny Halevy 		goto out_overflow;
39563ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &offset);
39573ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &length);
39586f723f77SBenny Halevy 	type = be32_to_cpup(p++);
3959911d1aafSTrond Myklebust 	if (fl != NULL) {
3960911d1aafSTrond Myklebust 		fl->fl_start = (loff_t)offset;
3961911d1aafSTrond Myklebust 		fl->fl_end = fl->fl_start + (loff_t)length - 1;
3962911d1aafSTrond Myklebust 		if (length == ~(uint64_t)0)
3963911d1aafSTrond Myklebust 			fl->fl_end = OFFSET_MAX;
3964911d1aafSTrond Myklebust 		fl->fl_type = F_WRLCK;
3965911d1aafSTrond Myklebust 		if (type & 1)
3966911d1aafSTrond Myklebust 			fl->fl_type = F_RDLCK;
3967911d1aafSTrond Myklebust 		fl->fl_pid = 0;
3968911d1aafSTrond Myklebust 	}
39693ceb4dbbSBenny Halevy 	p = xdr_decode_hyper(p, &clientid);
3970cccddf4fSBenny Halevy 	namelen = be32_to_cpup(p);
3971c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, namelen);
3972c0eae66eSBenny Halevy 	if (likely(p))
39731da177e4SLinus Torvalds 		return -NFS4ERR_DENIED;
3974c0eae66eSBenny Halevy out_overflow:
3975c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
3976c0eae66eSBenny Halevy 	return -EIO;
39771da177e4SLinus Torvalds }
39781da177e4SLinus Torvalds 
3979911d1aafSTrond Myklebust static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
39801da177e4SLinus Torvalds {
39811da177e4SLinus Torvalds 	int status;
39821da177e4SLinus Torvalds 
39831da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCK);
3984c1d51931STrond Myklebust 	if (status == -EIO)
3985c1d51931STrond Myklebust 		goto out;
39861da177e4SLinus Torvalds 	if (status == 0) {
398707d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
398807d30434SBenny Halevy 		if (unlikely(status))
398907d30434SBenny Halevy 			goto out;
39901da177e4SLinus Torvalds 	} else if (status == -NFS4ERR_DENIED)
3991c1d51931STrond Myklebust 		status = decode_lock_denied(xdr, NULL);
3992c1d51931STrond Myklebust 	if (res->open_seqid != NULL)
3993c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->open_seqid);
3994c1d51931STrond Myklebust 	nfs_increment_lock_seqid(status, res->lock_seqid);
3995c1d51931STrond Myklebust out:
39961da177e4SLinus Torvalds 	return status;
39971da177e4SLinus Torvalds }
39981da177e4SLinus Torvalds 
3999911d1aafSTrond Myklebust static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
40001da177e4SLinus Torvalds {
40011da177e4SLinus Torvalds 	int status;
40021da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCKT);
40031da177e4SLinus Torvalds 	if (status == -NFS4ERR_DENIED)
4004911d1aafSTrond Myklebust 		return decode_lock_denied(xdr, res->denied);
40051da177e4SLinus Torvalds 	return status;
40061da177e4SLinus Torvalds }
40071da177e4SLinus Torvalds 
4008911d1aafSTrond Myklebust static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
40091da177e4SLinus Torvalds {
40101da177e4SLinus Torvalds 	int status;
40111da177e4SLinus Torvalds 
40121da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_LOCKU);
4013c1d51931STrond Myklebust 	if (status != -EIO)
4014c1d51931STrond Myklebust 		nfs_increment_lock_seqid(status, res->seqid);
401507d30434SBenny Halevy 	if (status == 0)
401607d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
40171da177e4SLinus Torvalds 	return status;
40181da177e4SLinus Torvalds }
40191da177e4SLinus Torvalds 
4020d3c7b7ccSTrond Myklebust static int decode_release_lockowner(struct xdr_stream *xdr)
4021d3c7b7ccSTrond Myklebust {
4022d3c7b7ccSTrond Myklebust 	return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
4023d3c7b7ccSTrond Myklebust }
4024d3c7b7ccSTrond Myklebust 
40251da177e4SLinus Torvalds static int decode_lookup(struct xdr_stream *xdr)
40261da177e4SLinus Torvalds {
40271da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_LOOKUP);
40281da177e4SLinus Torvalds }
40291da177e4SLinus Torvalds 
40301da177e4SLinus Torvalds /* This is too sick! */
40311da177e4SLinus Torvalds static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
40321da177e4SLinus Torvalds {
40338687b63aSAl Viro 	__be32 *p;
40341da177e4SLinus Torvalds 	uint32_t limit_type, nblocks, blocksize;
40351da177e4SLinus Torvalds 
4036c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
4037c0eae66eSBenny Halevy 	if (unlikely(!p))
4038c0eae66eSBenny Halevy 		goto out_overflow;
40396f723f77SBenny Halevy 	limit_type = be32_to_cpup(p++);
40401da177e4SLinus Torvalds 	switch (limit_type) {
40411da177e4SLinus Torvalds 	case 1:
4042cccddf4fSBenny Halevy 		xdr_decode_hyper(p, maxsize);
40431da177e4SLinus Torvalds 		break;
40441da177e4SLinus Torvalds 	case 2:
40456f723f77SBenny Halevy 		nblocks = be32_to_cpup(p++);
4046cccddf4fSBenny Halevy 		blocksize = be32_to_cpup(p);
40471da177e4SLinus Torvalds 		*maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
40481da177e4SLinus Torvalds 	}
40491da177e4SLinus Torvalds 	return 0;
4050c0eae66eSBenny Halevy out_overflow:
4051c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4052c0eae66eSBenny Halevy 	return -EIO;
40531da177e4SLinus Torvalds }
40541da177e4SLinus Torvalds 
40551da177e4SLinus Torvalds static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
40561da177e4SLinus Torvalds {
40578687b63aSAl Viro 	__be32 *p;
40581da177e4SLinus Torvalds 	uint32_t delegation_type;
405907d30434SBenny Halevy 	int status;
40601da177e4SLinus Torvalds 
4061c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4062c0eae66eSBenny Halevy 	if (unlikely(!p))
4063c0eae66eSBenny Halevy 		goto out_overflow;
4064cccddf4fSBenny Halevy 	delegation_type = be32_to_cpup(p);
40651da177e4SLinus Torvalds 	if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
40661da177e4SLinus Torvalds 		res->delegation_type = 0;
40671da177e4SLinus Torvalds 		return 0;
40681da177e4SLinus Torvalds 	}
406907d30434SBenny Halevy 	status = decode_stateid(xdr, &res->delegation);
407007d30434SBenny Halevy 	if (unlikely(status))
407107d30434SBenny Halevy 		return status;
4072c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4073c0eae66eSBenny Halevy 	if (unlikely(!p))
4074c0eae66eSBenny Halevy 		goto out_overflow;
4075cccddf4fSBenny Halevy 	res->do_recall = be32_to_cpup(p);
407605d564feSAndy Adamson 
40771da177e4SLinus Torvalds 	switch (delegation_type) {
40781da177e4SLinus Torvalds 	case NFS4_OPEN_DELEGATE_READ:
40791da177e4SLinus Torvalds 		res->delegation_type = FMODE_READ;
40801da177e4SLinus Torvalds 		break;
40811da177e4SLinus Torvalds 	case NFS4_OPEN_DELEGATE_WRITE:
40821da177e4SLinus Torvalds 		res->delegation_type = FMODE_WRITE|FMODE_READ;
40831da177e4SLinus Torvalds 		if (decode_space_limit(xdr, &res->maxsize) < 0)
40841da177e4SLinus Torvalds 				return -EIO;
40851da177e4SLinus Torvalds 	}
40867539bbabSDavid Howells 	return decode_ace(xdr, NULL, res->server->nfs_client);
4087c0eae66eSBenny Halevy out_overflow:
4088c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4089c0eae66eSBenny Halevy 	return -EIO;
40901da177e4SLinus Torvalds }
40911da177e4SLinus Torvalds 
40921da177e4SLinus Torvalds static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
40931da177e4SLinus Torvalds {
40948687b63aSAl Viro 	__be32 *p;
4095aa53ed54SJeff Layton 	uint32_t savewords, bmlen, i;
40961da177e4SLinus Torvalds 	int status;
40971da177e4SLinus Torvalds 
40981da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN);
4099c1d51931STrond Myklebust 	if (status != -EIO)
4100c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
410107d30434SBenny Halevy 	if (!status)
410207d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
410307d30434SBenny Halevy 	if (unlikely(status))
41041da177e4SLinus Torvalds 		return status;
41051da177e4SLinus Torvalds 
41061da177e4SLinus Torvalds 	decode_change_info(xdr, &res->cinfo);
41071da177e4SLinus Torvalds 
4108c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4109c0eae66eSBenny Halevy 	if (unlikely(!p))
4110c0eae66eSBenny Halevy 		goto out_overflow;
41116f723f77SBenny Halevy 	res->rflags = be32_to_cpup(p++);
4112cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
41131da177e4SLinus Torvalds 	if (bmlen > 10)
41141da177e4SLinus Torvalds 		goto xdr_error;
41151da177e4SLinus Torvalds 
4116c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
4117c0eae66eSBenny Halevy 	if (unlikely(!p))
4118c0eae66eSBenny Halevy 		goto out_overflow;
4119aa53ed54SJeff Layton 	savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
4120aa53ed54SJeff Layton 	for (i = 0; i < savewords; ++i)
41216f723f77SBenny Halevy 		res->attrset[i] = be32_to_cpup(p++);
4122aa53ed54SJeff Layton 	for (; i < NFS4_BITMAP_SIZE; i++)
4123aa53ed54SJeff Layton 		res->attrset[i] = 0;
4124aa53ed54SJeff Layton 
41251da177e4SLinus Torvalds 	return decode_delegation(xdr, res);
41261da177e4SLinus Torvalds xdr_error:
41273110ff80SHarvey Harrison 	dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
41281da177e4SLinus Torvalds 	return -EIO;
4129c0eae66eSBenny Halevy out_overflow:
4130c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4131c0eae66eSBenny Halevy 	return -EIO;
41321da177e4SLinus Torvalds }
41331da177e4SLinus Torvalds 
41341da177e4SLinus Torvalds static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
41351da177e4SLinus Torvalds {
41361da177e4SLinus Torvalds 	int status;
41371da177e4SLinus Torvalds 
41381da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
4139c1d51931STrond Myklebust 	if (status != -EIO)
4140c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
414107d30434SBenny Halevy 	if (!status)
414207d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
41431da177e4SLinus Torvalds 	return status;
41441da177e4SLinus Torvalds }
41451da177e4SLinus Torvalds 
41461da177e4SLinus Torvalds static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
41471da177e4SLinus Torvalds {
41481da177e4SLinus Torvalds 	int status;
41491da177e4SLinus Torvalds 
41501da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
4151c1d51931STrond Myklebust 	if (status != -EIO)
4152c1d51931STrond Myklebust 		nfs_increment_open_seqid(status, res->seqid);
415307d30434SBenny Halevy 	if (!status)
415407d30434SBenny Halevy 		status = decode_stateid(xdr, &res->stateid);
41551da177e4SLinus Torvalds 	return status;
41561da177e4SLinus Torvalds }
41571da177e4SLinus Torvalds 
41581da177e4SLinus Torvalds static int decode_putfh(struct xdr_stream *xdr)
41591da177e4SLinus Torvalds {
41601da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_PUTFH);
41611da177e4SLinus Torvalds }
41621da177e4SLinus Torvalds 
41631da177e4SLinus Torvalds static int decode_putrootfh(struct xdr_stream *xdr)
41641da177e4SLinus Torvalds {
41651da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_PUTROOTFH);
41661da177e4SLinus Torvalds }
41671da177e4SLinus Torvalds 
41681da177e4SLinus Torvalds static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
41691da177e4SLinus Torvalds {
41701da177e4SLinus Torvalds 	struct kvec *iov = req->rq_rcv_buf.head;
41718687b63aSAl Viro 	__be32 *p;
41721da177e4SLinus Torvalds 	uint32_t count, eof, recvd, hdrlen;
41731da177e4SLinus Torvalds 	int status;
41741da177e4SLinus Torvalds 
41751da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READ);
41761da177e4SLinus Torvalds 	if (status)
41771da177e4SLinus Torvalds 		return status;
4178c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4179c0eae66eSBenny Halevy 	if (unlikely(!p))
4180c0eae66eSBenny Halevy 		goto out_overflow;
41816f723f77SBenny Halevy 	eof = be32_to_cpup(p++);
4182cccddf4fSBenny Halevy 	count = be32_to_cpup(p);
41831da177e4SLinus Torvalds 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
41841da177e4SLinus Torvalds 	recvd = req->rq_rcv_buf.len - hdrlen;
41851da177e4SLinus Torvalds 	if (count > recvd) {
4186fe82a183SChuck Lever 		dprintk("NFS: server cheating in read reply: "
41871da177e4SLinus Torvalds 				"count %u > recvd %u\n", count, recvd);
41881da177e4SLinus Torvalds 		count = recvd;
41891da177e4SLinus Torvalds 		eof = 0;
41901da177e4SLinus Torvalds 	}
41911da177e4SLinus Torvalds 	xdr_read_pages(xdr, count);
41921da177e4SLinus Torvalds 	res->eof = eof;
41931da177e4SLinus Torvalds 	res->count = count;
41941da177e4SLinus Torvalds 	return 0;
4195c0eae66eSBenny Halevy out_overflow:
4196c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4197c0eae66eSBenny Halevy 	return -EIO;
41981da177e4SLinus Torvalds }
41991da177e4SLinus Torvalds 
42001da177e4SLinus Torvalds static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
42011da177e4SLinus Torvalds {
42021da177e4SLinus Torvalds 	struct xdr_buf	*rcvbuf = &req->rq_rcv_buf;
42031da177e4SLinus Torvalds 	struct page	*page = *rcvbuf->pages;
42041da177e4SLinus Torvalds 	struct kvec	*iov = rcvbuf->head;
4205bcecff77SChuck Lever 	size_t		hdrlen;
4206bcecff77SChuck Lever 	u32		recvd, pglen = rcvbuf->page_len;
42078687b63aSAl Viro 	__be32		*end, *entry, *p, *kaddr;
42087bda2cdfSJeff Layton 	unsigned int	nr = 0;
4209bcecff77SChuck Lever 	int		status;
42101da177e4SLinus Torvalds 
42111da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READDIR);
4212db942bbdSBenny Halevy 	if (!status)
4213db942bbdSBenny Halevy 		status = decode_verifier(xdr, readdir->verifier.data);
4214db942bbdSBenny Halevy 	if (unlikely(status))
42151da177e4SLinus Torvalds 		return status;
421644109241SFred Isaman 	dprintk("%s: verifier = %08x:%08x\n",
421744109241SFred Isaman 			__func__,
4218eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[0],
4219eadf4598STrond Myklebust 			((u32 *)readdir->verifier.data)[1]);
4220eadf4598STrond Myklebust 
42211da177e4SLinus Torvalds 
4222db942bbdSBenny Halevy 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
42231da177e4SLinus Torvalds 	recvd = rcvbuf->len - hdrlen;
42241da177e4SLinus Torvalds 	if (pglen > recvd)
42251da177e4SLinus Torvalds 		pglen = recvd;
42261da177e4SLinus Torvalds 	xdr_read_pages(xdr, pglen);
42271da177e4SLinus Torvalds 
42281da177e4SLinus Torvalds 	BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
42298687b63aSAl Viro 	kaddr = p = kmap_atomic(page, KM_USER0);
4230e8896495SDavid Howells 	end = p + ((pglen + readdir->pgbase) >> 2);
42311da177e4SLinus Torvalds 	entry = p;
42327bda2cdfSJeff Layton 
42337bda2cdfSJeff Layton 	/* Make sure the packet actually has a value_follows and EOF entry */
42347bda2cdfSJeff Layton 	if ((entry + 1) > end)
42357bda2cdfSJeff Layton 		goto short_pkt;
42367bda2cdfSJeff Layton 
42377bda2cdfSJeff Layton 	for (; *p++; nr++) {
4238bcecff77SChuck Lever 		u32 len, attrlen, xlen;
4239e8896495SDavid Howells 		if (end - p < 3)
42401da177e4SLinus Torvalds 			goto short_pkt;
4241eadf4598STrond Myklebust 		dprintk("cookie = %Lu, ", *((unsigned long long *)p));
42421da177e4SLinus Torvalds 		p += 2;			/* cookie */
42431da177e4SLinus Torvalds 		len = ntohl(*p++);	/* filename length */
42441da177e4SLinus Torvalds 		if (len > NFS4_MAXNAMLEN) {
4245fe82a183SChuck Lever 			dprintk("NFS: giant filename in readdir (len 0x%x)\n",
4246fe82a183SChuck Lever 					len);
42471da177e4SLinus Torvalds 			goto err_unmap;
42481da177e4SLinus Torvalds 		}
4249e8896495SDavid Howells 		xlen = XDR_QUADLEN(len);
4250e8896495SDavid Howells 		if (end - p < xlen + 1)
4251e8896495SDavid Howells 			goto short_pkt;
4252eadf4598STrond Myklebust 		dprintk("filename = %*s\n", len, (char *)p);
4253e8896495SDavid Howells 		p += xlen;
42541da177e4SLinus Torvalds 		len = ntohl(*p++);	/* bitmap length */
4255e8896495SDavid Howells 		if (end - p < len + 1)
4256e8896495SDavid Howells 			goto short_pkt;
42571da177e4SLinus Torvalds 		p += len;
42581da177e4SLinus Torvalds 		attrlen = XDR_QUADLEN(ntohl(*p++));
4259e8896495SDavid Howells 		if (end - p < attrlen + 2)
42601da177e4SLinus Torvalds 			goto short_pkt;
4261e8896495SDavid Howells 		p += attrlen;		/* attributes */
42621da177e4SLinus Torvalds 		entry = p;
42631da177e4SLinus Torvalds 	}
42647bda2cdfSJeff Layton 	/*
42657bda2cdfSJeff Layton 	 * Apparently some server sends responses that are a valid size, but
42667bda2cdfSJeff Layton 	 * contain no entries, and have value_follows==0 and EOF==0. For
42677bda2cdfSJeff Layton 	 * those, just set the EOF marker.
42687bda2cdfSJeff Layton 	 */
42697bda2cdfSJeff Layton 	if (!nr && entry[1] == 0) {
42707bda2cdfSJeff Layton 		dprintk("NFS: readdir reply truncated!\n");
42717bda2cdfSJeff Layton 		entry[1] = 1;
42727bda2cdfSJeff Layton 	}
42731da177e4SLinus Torvalds out:
42741da177e4SLinus Torvalds 	kunmap_atomic(kaddr, KM_USER0);
42751da177e4SLinus Torvalds 	return 0;
42761da177e4SLinus Torvalds short_pkt:
42777bda2cdfSJeff Layton 	/*
42787bda2cdfSJeff Layton 	 * When we get a short packet there are 2 possibilities. We can
42797bda2cdfSJeff Layton 	 * return an error, or fix up the response to look like a valid
42807bda2cdfSJeff Layton 	 * response and return what we have so far. If there are no
42817bda2cdfSJeff Layton 	 * entries and the packet was short, then return -EIO. If there
42827bda2cdfSJeff Layton 	 * are valid entries in the response, return them and pretend that
42837bda2cdfSJeff Layton 	 * the call was successful, but incomplete. The caller can retry the
42847bda2cdfSJeff Layton 	 * readdir starting at the last cookie.
42857bda2cdfSJeff Layton 	 */
42863110ff80SHarvey Harrison 	dprintk("%s: short packet at entry %d\n", __func__, nr);
42871da177e4SLinus Torvalds 	entry[0] = entry[1] = 0;
42887bda2cdfSJeff Layton 	if (nr)
42891da177e4SLinus Torvalds 		goto out;
42901da177e4SLinus Torvalds err_unmap:
42911da177e4SLinus Torvalds 	kunmap_atomic(kaddr, KM_USER0);
42921da177e4SLinus Torvalds 	return -errno_NFSERR_IO;
42931da177e4SLinus Torvalds }
42941da177e4SLinus Torvalds 
42951da177e4SLinus Torvalds static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
42961da177e4SLinus Torvalds {
42971da177e4SLinus Torvalds 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
42981da177e4SLinus Torvalds 	struct kvec *iov = rcvbuf->head;
4299bcecff77SChuck Lever 	size_t hdrlen;
4300bcecff77SChuck Lever 	u32 len, recvd;
43018687b63aSAl Viro 	__be32 *p;
43021da177e4SLinus Torvalds 	char *kaddr;
43031da177e4SLinus Torvalds 	int status;
43041da177e4SLinus Torvalds 
43051da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_READLINK);
43061da177e4SLinus Torvalds 	if (status)
43071da177e4SLinus Torvalds 		return status;
43081da177e4SLinus Torvalds 
43091da177e4SLinus Torvalds 	/* Convert length of symlink */
4310c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4311c0eae66eSBenny Halevy 	if (unlikely(!p))
4312c0eae66eSBenny Halevy 		goto out_overflow;
4313cccddf4fSBenny Halevy 	len = be32_to_cpup(p);
43141da177e4SLinus Torvalds 	if (len >= rcvbuf->page_len || len <= 0) {
4315fe82a183SChuck Lever 		dprintk("nfs: server returned giant symlink!\n");
43161da177e4SLinus Torvalds 		return -ENAMETOOLONG;
43171da177e4SLinus Torvalds 	}
43181da177e4SLinus Torvalds 	hdrlen = (char *) xdr->p - (char *) iov->iov_base;
43191da177e4SLinus Torvalds 	recvd = req->rq_rcv_buf.len - hdrlen;
43201da177e4SLinus Torvalds 	if (recvd < len) {
4321fe82a183SChuck Lever 		dprintk("NFS: server cheating in readlink reply: "
43221da177e4SLinus Torvalds 				"count %u > recvd %u\n", len, recvd);
43231da177e4SLinus Torvalds 		return -EIO;
43241da177e4SLinus Torvalds 	}
43251da177e4SLinus Torvalds 	xdr_read_pages(xdr, len);
43261da177e4SLinus Torvalds 	/*
43271da177e4SLinus Torvalds 	 * The XDR encode routine has set things up so that
43281da177e4SLinus Torvalds 	 * the link text will be copied directly into the
43291da177e4SLinus Torvalds 	 * buffer.  We just have to do overflow-checking,
43301da177e4SLinus Torvalds 	 * and and null-terminate the text (the VFS expects
43311da177e4SLinus Torvalds 	 * null-termination).
43321da177e4SLinus Torvalds 	 */
43331da177e4SLinus Torvalds 	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
43341da177e4SLinus Torvalds 	kaddr[len+rcvbuf->page_base] = '\0';
43351da177e4SLinus Torvalds 	kunmap_atomic(kaddr, KM_USER0);
43361da177e4SLinus Torvalds 	return 0;
4337c0eae66eSBenny Halevy out_overflow:
4338c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4339c0eae66eSBenny Halevy 	return -EIO;
43401da177e4SLinus Torvalds }
43411da177e4SLinus Torvalds 
43421da177e4SLinus Torvalds static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
43431da177e4SLinus Torvalds {
43441da177e4SLinus Torvalds 	int status;
43451da177e4SLinus Torvalds 
43461da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_REMOVE);
43471da177e4SLinus Torvalds 	if (status)
43481da177e4SLinus Torvalds 		goto out;
43491da177e4SLinus Torvalds 	status = decode_change_info(xdr, cinfo);
43501da177e4SLinus Torvalds out:
43511da177e4SLinus Torvalds 	return status;
43521da177e4SLinus Torvalds }
43531da177e4SLinus Torvalds 
43541da177e4SLinus Torvalds static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
43551da177e4SLinus Torvalds 	      struct nfs4_change_info *new_cinfo)
43561da177e4SLinus Torvalds {
43571da177e4SLinus Torvalds 	int status;
43581da177e4SLinus Torvalds 
43591da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_RENAME);
43601da177e4SLinus Torvalds 	if (status)
43611da177e4SLinus Torvalds 		goto out;
43621da177e4SLinus Torvalds 	if ((status = decode_change_info(xdr, old_cinfo)))
43631da177e4SLinus Torvalds 		goto out;
43641da177e4SLinus Torvalds 	status = decode_change_info(xdr, new_cinfo);
43651da177e4SLinus Torvalds out:
43661da177e4SLinus Torvalds 	return status;
43671da177e4SLinus Torvalds }
43681da177e4SLinus Torvalds 
43691da177e4SLinus Torvalds static int decode_renew(struct xdr_stream *xdr)
43701da177e4SLinus Torvalds {
43711da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_RENEW);
43721da177e4SLinus Torvalds }
43731da177e4SLinus Torvalds 
437456ae19f3STrond Myklebust static int
437556ae19f3STrond Myklebust decode_restorefh(struct xdr_stream *xdr)
437656ae19f3STrond Myklebust {
437756ae19f3STrond Myklebust 	return decode_op_hdr(xdr, OP_RESTOREFH);
437856ae19f3STrond Myklebust }
437956ae19f3STrond Myklebust 
4380029d105eSJ. Bruce Fields static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
4381029d105eSJ. Bruce Fields 		size_t *acl_len)
4382029d105eSJ. Bruce Fields {
43838687b63aSAl Viro 	__be32 *savep;
4384029d105eSJ. Bruce Fields 	uint32_t attrlen,
4385029d105eSJ. Bruce Fields 		 bitmap[2] = {0};
4386029d105eSJ. Bruce Fields 	struct kvec *iov = req->rq_rcv_buf.head;
4387029d105eSJ. Bruce Fields 	int status;
4388029d105eSJ. Bruce Fields 
4389029d105eSJ. Bruce Fields 	*acl_len = 0;
4390029d105eSJ. Bruce Fields 	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4391029d105eSJ. Bruce Fields 		goto out;
4392029d105eSJ. Bruce Fields 	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4393029d105eSJ. Bruce Fields 		goto out;
4394029d105eSJ. Bruce Fields 	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4395029d105eSJ. Bruce Fields 		goto out;
4396029d105eSJ. Bruce Fields 
4397029d105eSJ. Bruce Fields 	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
4398029d105eSJ. Bruce Fields 		return -EIO;
4399029d105eSJ. Bruce Fields 	if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
4400bcecff77SChuck Lever 		size_t hdrlen;
4401bcecff77SChuck Lever 		u32 recvd;
4402029d105eSJ. Bruce Fields 
4403029d105eSJ. Bruce Fields 		/* We ignore &savep and don't do consistency checks on
4404029d105eSJ. Bruce Fields 		 * the attr length.  Let userspace figure it out.... */
4405029d105eSJ. Bruce Fields 		hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
4406029d105eSJ. Bruce Fields 		recvd = req->rq_rcv_buf.len - hdrlen;
4407029d105eSJ. Bruce Fields 		if (attrlen > recvd) {
4408fe82a183SChuck Lever 			dprintk("NFS: server cheating in getattr"
4409029d105eSJ. Bruce Fields 					" acl reply: attrlen %u > recvd %u\n",
4410029d105eSJ. Bruce Fields 					attrlen, recvd);
4411029d105eSJ. Bruce Fields 			return -EINVAL;
4412029d105eSJ. Bruce Fields 		}
4413029d105eSJ. Bruce Fields 		xdr_read_pages(xdr, attrlen);
4414029d105eSJ. Bruce Fields 		*acl_len = attrlen;
44158c233cf9SJ. Bruce Fields 	} else
44168c233cf9SJ. Bruce Fields 		status = -EOPNOTSUPP;
4417029d105eSJ. Bruce Fields 
4418029d105eSJ. Bruce Fields out:
4419029d105eSJ. Bruce Fields 	return status;
4420029d105eSJ. Bruce Fields }
4421029d105eSJ. Bruce Fields 
44221da177e4SLinus Torvalds static int
44231da177e4SLinus Torvalds decode_savefh(struct xdr_stream *xdr)
44241da177e4SLinus Torvalds {
44251da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_SAVEFH);
44261da177e4SLinus Torvalds }
44271da177e4SLinus Torvalds 
44289e9ecc03SBenny Halevy static int decode_setattr(struct xdr_stream *xdr)
44291da177e4SLinus Torvalds {
44308687b63aSAl Viro 	__be32 *p;
44311da177e4SLinus Torvalds 	uint32_t bmlen;
44321da177e4SLinus Torvalds 	int status;
44331da177e4SLinus Torvalds 
44341da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_SETATTR);
44351da177e4SLinus Torvalds 	if (status)
44361da177e4SLinus Torvalds 		return status;
4437c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 4);
4438c0eae66eSBenny Halevy 	if (unlikely(!p))
4439c0eae66eSBenny Halevy 		goto out_overflow;
4440cccddf4fSBenny Halevy 	bmlen = be32_to_cpup(p);
4441c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, bmlen << 2);
4442c0eae66eSBenny Halevy 	if (likely(p))
44431da177e4SLinus Torvalds 		return 0;
4444c0eae66eSBenny Halevy out_overflow:
4445c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4446c0eae66eSBenny Halevy 	return -EIO;
44471da177e4SLinus Torvalds }
44481da177e4SLinus Torvalds 
4449bb8b27e5STrond Myklebust static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res)
44501da177e4SLinus Torvalds {
44518687b63aSAl Viro 	__be32 *p;
44521da177e4SLinus Torvalds 	uint32_t opnum;
44531da177e4SLinus Torvalds 	int32_t nfserr;
44541da177e4SLinus Torvalds 
4455c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4456c0eae66eSBenny Halevy 	if (unlikely(!p))
4457c0eae66eSBenny Halevy 		goto out_overflow;
44586f723f77SBenny Halevy 	opnum = be32_to_cpup(p++);
44591da177e4SLinus Torvalds 	if (opnum != OP_SETCLIENTID) {
4460fe82a183SChuck Lever 		dprintk("nfs: decode_setclientid: Server returned operation"
44611da177e4SLinus Torvalds 			" %d\n", opnum);
44621da177e4SLinus Torvalds 		return -EIO;
44631da177e4SLinus Torvalds 	}
4464cccddf4fSBenny Halevy 	nfserr = be32_to_cpup(p);
44651da177e4SLinus Torvalds 	if (nfserr == NFS_OK) {
4466c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
4467c0eae66eSBenny Halevy 		if (unlikely(!p))
4468c0eae66eSBenny Halevy 			goto out_overflow;
4469bb8b27e5STrond Myklebust 		p = xdr_decode_hyper(p, &res->clientid);
4470bb8b27e5STrond Myklebust 		memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
44711da177e4SLinus Torvalds 	} else if (nfserr == NFSERR_CLID_INUSE) {
44721da177e4SLinus Torvalds 		uint32_t len;
44731da177e4SLinus Torvalds 
44741da177e4SLinus Torvalds 		/* skip netid string */
4475c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
4476c0eae66eSBenny Halevy 		if (unlikely(!p))
4477c0eae66eSBenny Halevy 			goto out_overflow;
4478cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
4479c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
4480c0eae66eSBenny Halevy 		if (unlikely(!p))
4481c0eae66eSBenny Halevy 			goto out_overflow;
44821da177e4SLinus Torvalds 
44831da177e4SLinus Torvalds 		/* skip uaddr string */
4484c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4);
4485c0eae66eSBenny Halevy 		if (unlikely(!p))
4486c0eae66eSBenny Halevy 			goto out_overflow;
4487cccddf4fSBenny Halevy 		len = be32_to_cpup(p);
4488c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, len);
4489c0eae66eSBenny Halevy 		if (unlikely(!p))
4490c0eae66eSBenny Halevy 			goto out_overflow;
44911da177e4SLinus Torvalds 		return -NFSERR_CLID_INUSE;
44921da177e4SLinus Torvalds 	} else
4493856dff3dSBenny Halevy 		return nfs4_stat_to_errno(nfserr);
44941da177e4SLinus Torvalds 
44951da177e4SLinus Torvalds 	return 0;
4496c0eae66eSBenny Halevy out_overflow:
4497c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4498c0eae66eSBenny Halevy 	return -EIO;
44991da177e4SLinus Torvalds }
45001da177e4SLinus Torvalds 
45011da177e4SLinus Torvalds static int decode_setclientid_confirm(struct xdr_stream *xdr)
45021da177e4SLinus Torvalds {
45031da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
45041da177e4SLinus Torvalds }
45051da177e4SLinus Torvalds 
45061da177e4SLinus Torvalds static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
45071da177e4SLinus Torvalds {
45088687b63aSAl Viro 	__be32 *p;
45091da177e4SLinus Torvalds 	int status;
45101da177e4SLinus Torvalds 
45111da177e4SLinus Torvalds 	status = decode_op_hdr(xdr, OP_WRITE);
45121da177e4SLinus Torvalds 	if (status)
45131da177e4SLinus Torvalds 		return status;
45141da177e4SLinus Torvalds 
4515c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 16);
4516c0eae66eSBenny Halevy 	if (unlikely(!p))
4517c0eae66eSBenny Halevy 		goto out_overflow;
45186f723f77SBenny Halevy 	res->count = be32_to_cpup(p++);
45196f723f77SBenny Halevy 	res->verf->committed = be32_to_cpup(p++);
452099398d06SBenny Halevy 	memcpy(res->verf->verifier, p, 8);
45211da177e4SLinus Torvalds 	return 0;
4522c0eae66eSBenny Halevy out_overflow:
4523c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4524c0eae66eSBenny Halevy 	return -EIO;
45251da177e4SLinus Torvalds }
45261da177e4SLinus Torvalds 
45271da177e4SLinus Torvalds static int decode_delegreturn(struct xdr_stream *xdr)
45281da177e4SLinus Torvalds {
45291da177e4SLinus Torvalds 	return decode_op_hdr(xdr, OP_DELEGRETURN);
45301da177e4SLinus Torvalds }
45311da177e4SLinus Torvalds 
453299fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
453399fe60d0SBenny Halevy static int decode_exchange_id(struct xdr_stream *xdr,
453499fe60d0SBenny Halevy 			      struct nfs41_exchange_id_res *res)
453599fe60d0SBenny Halevy {
453699fe60d0SBenny Halevy 	__be32 *p;
453799fe60d0SBenny Halevy 	uint32_t dummy;
45382460ba57SBenny Halevy 	char *dummy_str;
453999fe60d0SBenny Halevy 	int status;
454099fe60d0SBenny Halevy 	struct nfs_client *clp = res->client;
454199fe60d0SBenny Halevy 
454299fe60d0SBenny Halevy 	status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
454399fe60d0SBenny Halevy 	if (status)
454499fe60d0SBenny Halevy 		return status;
454599fe60d0SBenny Halevy 
4546c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4547c0eae66eSBenny Halevy 	if (unlikely(!p))
4548c0eae66eSBenny Halevy 		goto out_overflow;
4549cccddf4fSBenny Halevy 	xdr_decode_hyper(p, &clp->cl_ex_clid);
4550c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 12);
4551c0eae66eSBenny Halevy 	if (unlikely(!p))
4552c0eae66eSBenny Halevy 		goto out_overflow;
45536f723f77SBenny Halevy 	clp->cl_seqid = be32_to_cpup(p++);
45546f723f77SBenny Halevy 	clp->cl_exchange_flags = be32_to_cpup(p++);
455599fe60d0SBenny Halevy 
455699fe60d0SBenny Halevy 	/* We ask for SP4_NONE */
4557cccddf4fSBenny Halevy 	dummy = be32_to_cpup(p);
455899fe60d0SBenny Halevy 	if (dummy != SP4_NONE)
455999fe60d0SBenny Halevy 		return -EIO;
456099fe60d0SBenny Halevy 
456199fe60d0SBenny Halevy 	/* Throw away minor_id */
4562c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4563c0eae66eSBenny Halevy 	if (unlikely(!p))
4564c0eae66eSBenny Halevy 		goto out_overflow;
456599fe60d0SBenny Halevy 
456699fe60d0SBenny Halevy 	/* Throw away Major id */
45672460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45682460ba57SBenny Halevy 	if (unlikely(status))
45692460ba57SBenny Halevy 		return status;
457099fe60d0SBenny Halevy 
457199fe60d0SBenny Halevy 	/* Throw away server_scope */
45722460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45732460ba57SBenny Halevy 	if (unlikely(status))
45742460ba57SBenny Halevy 		return status;
457599fe60d0SBenny Halevy 
457699fe60d0SBenny Halevy 	/* Throw away Implementation id array */
45772460ba57SBenny Halevy 	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
45782460ba57SBenny Halevy 	if (unlikely(status))
45792460ba57SBenny Halevy 		return status;
458099fe60d0SBenny Halevy 
458199fe60d0SBenny Halevy 	return 0;
4582c0eae66eSBenny Halevy out_overflow:
4583c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4584c0eae66eSBenny Halevy 	return -EIO;
458599fe60d0SBenny Halevy }
4586fc931582SAndy Adamson 
4587fc931582SAndy Adamson static int decode_chan_attrs(struct xdr_stream *xdr,
4588fc931582SAndy Adamson 			     struct nfs4_channel_attrs *attrs)
4589fc931582SAndy Adamson {
4590fc931582SAndy Adamson 	__be32 *p;
4591fc931582SAndy Adamson 	u32 nr_attrs;
4592fc931582SAndy Adamson 
4593c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 28);
4594c0eae66eSBenny Halevy 	if (unlikely(!p))
4595c0eae66eSBenny Halevy 		goto out_overflow;
45966f723f77SBenny Halevy 	attrs->headerpadsz = be32_to_cpup(p++);
45976f723f77SBenny Halevy 	attrs->max_rqst_sz = be32_to_cpup(p++);
45986f723f77SBenny Halevy 	attrs->max_resp_sz = be32_to_cpup(p++);
45996f723f77SBenny Halevy 	attrs->max_resp_sz_cached = be32_to_cpup(p++);
46006f723f77SBenny Halevy 	attrs->max_ops = be32_to_cpup(p++);
46016f723f77SBenny Halevy 	attrs->max_reqs = be32_to_cpup(p++);
4602cccddf4fSBenny Halevy 	nr_attrs = be32_to_cpup(p);
4603fc931582SAndy Adamson 	if (unlikely(nr_attrs > 1)) {
4604fc931582SAndy Adamson 		printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n",
4605fc931582SAndy Adamson 			__func__, nr_attrs);
4606fc931582SAndy Adamson 		return -EINVAL;
4607fc931582SAndy Adamson 	}
4608c0eae66eSBenny Halevy 	if (nr_attrs == 1) {
4609c0eae66eSBenny Halevy 		p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
4610c0eae66eSBenny Halevy 		if (unlikely(!p))
4611c0eae66eSBenny Halevy 			goto out_overflow;
4612c0eae66eSBenny Halevy 	}
4613fc931582SAndy Adamson 	return 0;
4614c0eae66eSBenny Halevy out_overflow:
4615c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4616c0eae66eSBenny Halevy 	return -EIO;
4617fc931582SAndy Adamson }
4618fc931582SAndy Adamson 
4619e78291e4SBenny Halevy static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
4620e78291e4SBenny Halevy {
4621e78291e4SBenny Halevy 	return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
4622fc931582SAndy Adamson }
4623fc931582SAndy Adamson 
4624fc931582SAndy Adamson static int decode_create_session(struct xdr_stream *xdr,
4625fc931582SAndy Adamson 				 struct nfs41_create_session_res *res)
4626fc931582SAndy Adamson {
4627fc931582SAndy Adamson 	__be32 *p;
4628fc931582SAndy Adamson 	int status;
4629fc931582SAndy Adamson 	struct nfs_client *clp = res->client;
4630fc931582SAndy Adamson 	struct nfs4_session *session = clp->cl_session;
4631fc931582SAndy Adamson 
4632fc931582SAndy Adamson 	status = decode_op_hdr(xdr, OP_CREATE_SESSION);
4633e78291e4SBenny Halevy 	if (!status)
4634e78291e4SBenny Halevy 		status = decode_sessionid(xdr, &session->sess_id);
4635e78291e4SBenny Halevy 	if (unlikely(status))
4636fc931582SAndy Adamson 		return status;
4637fc931582SAndy Adamson 
4638fc931582SAndy Adamson 	/* seqid, flags */
4639c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 8);
4640c0eae66eSBenny Halevy 	if (unlikely(!p))
4641c0eae66eSBenny Halevy 		goto out_overflow;
46426f723f77SBenny Halevy 	clp->cl_seqid = be32_to_cpup(p++);
4643cccddf4fSBenny Halevy 	session->flags = be32_to_cpup(p);
4644fc931582SAndy Adamson 
4645fc931582SAndy Adamson 	/* Channel attributes */
4646fc931582SAndy Adamson 	status = decode_chan_attrs(xdr, &session->fc_attrs);
4647fc931582SAndy Adamson 	if (!status)
4648fc931582SAndy Adamson 		status = decode_chan_attrs(xdr, &session->bc_attrs);
4649fc931582SAndy Adamson 	return status;
4650c0eae66eSBenny Halevy out_overflow:
4651c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4652c0eae66eSBenny Halevy 	return -EIO;
4653fc931582SAndy Adamson }
46540f3e66c6SAndy Adamson 
46550f3e66c6SAndy Adamson static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
46560f3e66c6SAndy Adamson {
46570f3e66c6SAndy Adamson 	return decode_op_hdr(xdr, OP_DESTROY_SESSION);
46580f3e66c6SAndy Adamson }
465918019753SRicardo Labiaga 
466018019753SRicardo Labiaga static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
466118019753SRicardo Labiaga {
466218019753SRicardo Labiaga 	return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
466318019753SRicardo Labiaga }
466499fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
466599fe60d0SBenny Halevy 
46669b7b9fccSAndy Adamson static int decode_sequence(struct xdr_stream *xdr,
46679b7b9fccSAndy Adamson 			   struct nfs4_sequence_res *res,
46689b7b9fccSAndy Adamson 			   struct rpc_rqst *rqstp)
46699b7b9fccSAndy Adamson {
46709b7b9fccSAndy Adamson #if defined(CONFIG_NFS_V4_1)
4671fc01cea9SAndy Adamson 	struct nfs4_slot *slot;
4672fc01cea9SAndy Adamson 	struct nfs4_sessionid id;
4673fc01cea9SAndy Adamson 	u32 dummy;
4674fc01cea9SAndy Adamson 	int status;
4675fc01cea9SAndy Adamson 	__be32 *p;
4676fc01cea9SAndy Adamson 
46779b7b9fccSAndy Adamson 	if (!res->sr_session)
46789b7b9fccSAndy Adamson 		return 0;
46799b7b9fccSAndy Adamson 
4680fc01cea9SAndy Adamson 	status = decode_op_hdr(xdr, OP_SEQUENCE);
4681e78291e4SBenny Halevy 	if (!status)
4682e78291e4SBenny Halevy 		status = decode_sessionid(xdr, &id);
4683e78291e4SBenny Halevy 	if (unlikely(status))
4684fc01cea9SAndy Adamson 		goto out_err;
46859b7b9fccSAndy Adamson 
4686fc01cea9SAndy Adamson 	/*
4687fc01cea9SAndy Adamson 	 * If the server returns different values for sessionID, slotID or
4688fc01cea9SAndy Adamson 	 * sequence number, the server is looney tunes.
4689fc01cea9SAndy Adamson 	 */
4690fdcb4577STrond Myklebust 	status = -EREMOTEIO;
4691fc01cea9SAndy Adamson 
4692fc01cea9SAndy Adamson 	if (memcmp(id.data, res->sr_session->sess_id.data,
4693fc01cea9SAndy Adamson 		   NFS4_MAX_SESSIONID_LEN)) {
4694fc01cea9SAndy Adamson 		dprintk("%s Invalid session id\n", __func__);
4695fc01cea9SAndy Adamson 		goto out_err;
4696fc01cea9SAndy Adamson 	}
4697e78291e4SBenny Halevy 
4698c0eae66eSBenny Halevy 	p = xdr_inline_decode(xdr, 20);
4699c0eae66eSBenny Halevy 	if (unlikely(!p))
4700c0eae66eSBenny Halevy 		goto out_overflow;
4701e78291e4SBenny Halevy 
4702fc01cea9SAndy Adamson 	/* seqid */
4703e78291e4SBenny Halevy 	slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
47046f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4705fc01cea9SAndy Adamson 	if (dummy != slot->seq_nr) {
4706fc01cea9SAndy Adamson 		dprintk("%s Invalid sequence number\n", __func__);
4707fc01cea9SAndy Adamson 		goto out_err;
4708fc01cea9SAndy Adamson 	}
4709fc01cea9SAndy Adamson 	/* slot id */
47106f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4711fc01cea9SAndy Adamson 	if (dummy != res->sr_slotid) {
4712fc01cea9SAndy Adamson 		dprintk("%s Invalid slot id\n", __func__);
4713fc01cea9SAndy Adamson 		goto out_err;
4714fc01cea9SAndy Adamson 	}
4715fc01cea9SAndy Adamson 	/* highest slot id - currently not processed */
47166f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
4717fc01cea9SAndy Adamson 	/* target highest slot id - currently not processed */
47186f723f77SBenny Halevy 	dummy = be32_to_cpup(p++);
47190629e370SAlexandros Batsakis 	/* result flags */
47200629e370SAlexandros Batsakis 	res->sr_status_flags = be32_to_cpup(p);
4721fc01cea9SAndy Adamson 	status = 0;
4722fc01cea9SAndy Adamson out_err:
4723fc01cea9SAndy Adamson 	res->sr_status = status;
4724fc01cea9SAndy Adamson 	return status;
4725c0eae66eSBenny Halevy out_overflow:
4726c0eae66eSBenny Halevy 	print_overflow_msg(__func__, xdr);
4727c0eae66eSBenny Halevy 	status = -EIO;
4728c0eae66eSBenny Halevy 	goto out_err;
4729fc01cea9SAndy Adamson #else  /* CONFIG_NFS_V4_1 */
47309b7b9fccSAndy Adamson 	return 0;
4731fc01cea9SAndy Adamson #endif /* CONFIG_NFS_V4_1 */
47329b7b9fccSAndy Adamson }
47339b7b9fccSAndy Adamson 
47341da177e4SLinus Torvalds /*
473549c2559eSBenny Halevy  * END OF "GENERIC" DECODE ROUTINES.
473649c2559eSBenny Halevy  */
473749c2559eSBenny Halevy 
473849c2559eSBenny Halevy /*
47391da177e4SLinus Torvalds  * Decode OPEN_DOWNGRADE response
47401da177e4SLinus Torvalds  */
47418687b63aSAl Viro static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
47421da177e4SLinus Torvalds {
47431da177e4SLinus Torvalds 	struct xdr_stream xdr;
47441da177e4SLinus Torvalds 	struct compound_hdr hdr;
47451da177e4SLinus Torvalds 	int status;
47461da177e4SLinus Torvalds 
47471da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
47481da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
47491da177e4SLinus Torvalds 	if (status)
47501da177e4SLinus Torvalds 		goto out;
47519b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
47529b7b9fccSAndy Adamson 	if (status)
47539b7b9fccSAndy Adamson 		goto out;
47541da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
47551da177e4SLinus Torvalds 	if (status)
47561da177e4SLinus Torvalds 		goto out;
47571da177e4SLinus Torvalds 	status = decode_open_downgrade(&xdr, res);
4758516a6af6STrond Myklebust 	if (status != 0)
4759516a6af6STrond Myklebust 		goto out;
476080e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
476180e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
47621da177e4SLinus Torvalds out:
47631da177e4SLinus Torvalds 	return status;
47641da177e4SLinus Torvalds }
47651da177e4SLinus Torvalds 
47661da177e4SLinus Torvalds /*
47671da177e4SLinus Torvalds  * Decode ACCESS response
47681da177e4SLinus Torvalds  */
47698687b63aSAl Viro static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
47701da177e4SLinus Torvalds {
47711da177e4SLinus Torvalds 	struct xdr_stream xdr;
47721da177e4SLinus Torvalds 	struct compound_hdr hdr;
47731da177e4SLinus Torvalds 	int status;
47741da177e4SLinus Torvalds 
47751da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
47769b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
47779b7b9fccSAndy Adamson 	if (status)
47789b7b9fccSAndy Adamson 		goto out;
47799b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
47809b7b9fccSAndy Adamson 	if (status)
47811da177e4SLinus Torvalds 		goto out;
478276b32999STrond Myklebust 	status = decode_putfh(&xdr);
478376b32999STrond Myklebust 	if (status != 0)
478476b32999STrond Myklebust 		goto out;
47851da177e4SLinus Torvalds 	status = decode_access(&xdr, res);
478676b32999STrond Myklebust 	if (status != 0)
478776b32999STrond Myklebust 		goto out;
478880e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
478980e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
47901da177e4SLinus Torvalds out:
47911da177e4SLinus Torvalds 	return status;
47921da177e4SLinus Torvalds }
47931da177e4SLinus Torvalds 
47941da177e4SLinus Torvalds /*
47951da177e4SLinus Torvalds  * Decode LOOKUP response
47961da177e4SLinus Torvalds  */
47978687b63aSAl Viro static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
47981da177e4SLinus Torvalds {
47991da177e4SLinus Torvalds 	struct xdr_stream xdr;
48001da177e4SLinus Torvalds 	struct compound_hdr hdr;
48011da177e4SLinus Torvalds 	int status;
48021da177e4SLinus Torvalds 
48031da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48049b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48059b7b9fccSAndy Adamson 	if (status)
48069b7b9fccSAndy Adamson 		goto out;
48079b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48089b7b9fccSAndy Adamson 	if (status)
48091da177e4SLinus Torvalds 		goto out;
48101da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
48111da177e4SLinus Torvalds 		goto out;
48121da177e4SLinus Torvalds 	if ((status = decode_lookup(&xdr)) != 0)
48131da177e4SLinus Torvalds 		goto out;
48141da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
48151da177e4SLinus Torvalds 		goto out;
481680e52aceSTrond Myklebust 	status = decode_getfattr(&xdr, res->fattr, res->server
481780e52aceSTrond Myklebust 			,!RPC_IS_ASYNC(rqstp->rq_task));
48181da177e4SLinus Torvalds out:
48191da177e4SLinus Torvalds 	return status;
48201da177e4SLinus Torvalds }
48211da177e4SLinus Torvalds 
48221da177e4SLinus Torvalds /*
48231da177e4SLinus Torvalds  * Decode LOOKUP_ROOT response
48241da177e4SLinus Torvalds  */
48258687b63aSAl Viro static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
48261da177e4SLinus Torvalds {
48271da177e4SLinus Torvalds 	struct xdr_stream xdr;
48281da177e4SLinus Torvalds 	struct compound_hdr hdr;
48291da177e4SLinus Torvalds 	int status;
48301da177e4SLinus Torvalds 
48311da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48329b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48339b7b9fccSAndy Adamson 	if (status)
48349b7b9fccSAndy Adamson 		goto out;
48359b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48369b7b9fccSAndy Adamson 	if (status)
48371da177e4SLinus Torvalds 		goto out;
48381da177e4SLinus Torvalds 	if ((status = decode_putrootfh(&xdr)) != 0)
48391da177e4SLinus Torvalds 		goto out;
48401da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) == 0)
484180e52aceSTrond Myklebust 		status = decode_getfattr(&xdr, res->fattr, res->server,
484280e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task));
48431da177e4SLinus Torvalds out:
48441da177e4SLinus Torvalds 	return status;
48451da177e4SLinus Torvalds }
48461da177e4SLinus Torvalds 
48471da177e4SLinus Torvalds /*
48481da177e4SLinus Torvalds  * Decode REMOVE response
48491da177e4SLinus Torvalds  */
48504fdc17b2STrond Myklebust static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
48511da177e4SLinus Torvalds {
48521da177e4SLinus Torvalds 	struct xdr_stream xdr;
48531da177e4SLinus Torvalds 	struct compound_hdr hdr;
48541da177e4SLinus Torvalds 	int status;
48551da177e4SLinus Torvalds 
48561da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48579b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48589b7b9fccSAndy Adamson 	if (status)
48599b7b9fccSAndy Adamson 		goto out;
48609b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48619b7b9fccSAndy Adamson 	if (status)
48621da177e4SLinus Torvalds 		goto out;
486316e42959STrond Myklebust 	if ((status = decode_putfh(&xdr)) != 0)
486416e42959STrond Myklebust 		goto out;
486516e42959STrond Myklebust 	if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
486616e42959STrond Myklebust 		goto out;
4867d346890bSTrond Myklebust 	decode_getfattr(&xdr, res->dir_attr, res->server,
486880e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
48691da177e4SLinus Torvalds out:
48701da177e4SLinus Torvalds 	return status;
48711da177e4SLinus Torvalds }
48721da177e4SLinus Torvalds 
48731da177e4SLinus Torvalds /*
48741da177e4SLinus Torvalds  * Decode RENAME response
48751da177e4SLinus Torvalds  */
4876e8582a8bSJeff Layton static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs_renameres *res)
48771da177e4SLinus Torvalds {
48781da177e4SLinus Torvalds 	struct xdr_stream xdr;
48791da177e4SLinus Torvalds 	struct compound_hdr hdr;
48801da177e4SLinus Torvalds 	int status;
48811da177e4SLinus Torvalds 
48821da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
48839b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
48849b7b9fccSAndy Adamson 	if (status)
48859b7b9fccSAndy Adamson 		goto out;
48869b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
48879b7b9fccSAndy Adamson 	if (status)
48881da177e4SLinus Torvalds 		goto out;
48891da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
48901da177e4SLinus Torvalds 		goto out;
48911da177e4SLinus Torvalds 	if ((status = decode_savefh(&xdr)) != 0)
48921da177e4SLinus Torvalds 		goto out;
48931da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
48941da177e4SLinus Torvalds 		goto out;
48956caf2c82STrond Myklebust 	if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
48966caf2c82STrond Myklebust 		goto out;
48976caf2c82STrond Myklebust 	/* Current FH is target directory */
489880e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->new_fattr, res->server,
489980e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
49006caf2c82STrond Myklebust 		goto out;
49016caf2c82STrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
49026caf2c82STrond Myklebust 		goto out;
490380e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->old_fattr, res->server,
490480e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49051da177e4SLinus Torvalds out:
49061da177e4SLinus Torvalds 	return status;
49071da177e4SLinus Torvalds }
49081da177e4SLinus Torvalds 
49091da177e4SLinus Torvalds /*
49101da177e4SLinus Torvalds  * Decode LINK response
49111da177e4SLinus Torvalds  */
49128687b63aSAl Viro static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
49131da177e4SLinus Torvalds {
49141da177e4SLinus Torvalds 	struct xdr_stream xdr;
49151da177e4SLinus Torvalds 	struct compound_hdr hdr;
49161da177e4SLinus Torvalds 	int status;
49171da177e4SLinus Torvalds 
49181da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
49199b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
49209b7b9fccSAndy Adamson 	if (status)
49219b7b9fccSAndy Adamson 		goto out;
49229b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
49239b7b9fccSAndy Adamson 	if (status)
49241da177e4SLinus Torvalds 		goto out;
49251da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49261da177e4SLinus Torvalds 		goto out;
49271da177e4SLinus Torvalds 	if ((status = decode_savefh(&xdr)) != 0)
49281da177e4SLinus Torvalds 		goto out;
49291da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49301da177e4SLinus Torvalds 		goto out;
493191ba2eeeSTrond Myklebust 	if ((status = decode_link(&xdr, &res->cinfo)) != 0)
493291ba2eeeSTrond Myklebust 		goto out;
493391ba2eeeSTrond Myklebust 	/*
493491ba2eeeSTrond Myklebust 	 * Note order: OP_LINK leaves the directory as the current
493591ba2eeeSTrond Myklebust 	 *             filehandle.
493691ba2eeeSTrond Myklebust 	 */
493780e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->dir_attr, res->server,
493880e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
493991ba2eeeSTrond Myklebust 		goto out;
494091ba2eeeSTrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
494191ba2eeeSTrond Myklebust 		goto out;
494280e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
494380e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49441da177e4SLinus Torvalds out:
49451da177e4SLinus Torvalds 	return status;
49461da177e4SLinus Torvalds }
49471da177e4SLinus Torvalds 
49481da177e4SLinus Torvalds /*
49491da177e4SLinus Torvalds  * Decode CREATE response
49501da177e4SLinus Torvalds  */
49518687b63aSAl Viro static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
49521da177e4SLinus Torvalds {
49531da177e4SLinus Torvalds 	struct xdr_stream xdr;
49541da177e4SLinus Torvalds 	struct compound_hdr hdr;
49551da177e4SLinus Torvalds 	int status;
49561da177e4SLinus Torvalds 
49571da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
49589b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
49599b7b9fccSAndy Adamson 	if (status)
49609b7b9fccSAndy Adamson 		goto out;
49619b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
49629b7b9fccSAndy Adamson 	if (status)
49631da177e4SLinus Torvalds 		goto out;
49641da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
49651da177e4SLinus Torvalds 		goto out;
496656ae19f3STrond Myklebust 	if ((status = decode_savefh(&xdr)) != 0)
496756ae19f3STrond Myklebust 		goto out;
49681da177e4SLinus Torvalds 	if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
49691da177e4SLinus Torvalds 		goto out;
49701da177e4SLinus Torvalds 	if ((status = decode_getfh(&xdr, res->fh)) != 0)
49711da177e4SLinus Torvalds 		goto out;
497280e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->fattr, res->server,
497380e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
497456ae19f3STrond Myklebust 		goto out;
497556ae19f3STrond Myklebust 	if ((status = decode_restorefh(&xdr)) != 0)
497656ae19f3STrond Myklebust 		goto out;
497780e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->dir_fattr, res->server,
497880e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
49791da177e4SLinus Torvalds out:
49801da177e4SLinus Torvalds 	return status;
49811da177e4SLinus Torvalds }
49821da177e4SLinus Torvalds 
49831da177e4SLinus Torvalds /*
49841da177e4SLinus Torvalds  * Decode SYMLINK response
49851da177e4SLinus Torvalds  */
49868687b63aSAl Viro static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
49871da177e4SLinus Torvalds {
49881da177e4SLinus Torvalds 	return nfs4_xdr_dec_create(rqstp, p, res);
49891da177e4SLinus Torvalds }
49901da177e4SLinus Torvalds 
49911da177e4SLinus Torvalds /*
49921da177e4SLinus Torvalds  * Decode GETATTR response
49931da177e4SLinus Torvalds  */
49948687b63aSAl Viro static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
49951da177e4SLinus Torvalds {
49961da177e4SLinus Torvalds 	struct xdr_stream xdr;
49971da177e4SLinus Torvalds 	struct compound_hdr hdr;
49981da177e4SLinus Torvalds 	int status;
49991da177e4SLinus Torvalds 
50001da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
50011da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
50021da177e4SLinus Torvalds 	if (status)
50031da177e4SLinus Torvalds 		goto out;
50049b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50059b7b9fccSAndy Adamson 	if (status)
50069b7b9fccSAndy Adamson 		goto out;
50071da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
50081da177e4SLinus Torvalds 	if (status)
50091da177e4SLinus Torvalds 		goto out;
501080e52aceSTrond Myklebust 	status = decode_getfattr(&xdr, res->fattr, res->server,
501180e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
50121da177e4SLinus Torvalds out:
50131da177e4SLinus Torvalds 	return status;
50141da177e4SLinus Torvalds }
50151da177e4SLinus Torvalds 
501623ec6965SJ. Bruce Fields /*
501723ec6965SJ. Bruce Fields  * Encode an SETACL request
501823ec6965SJ. Bruce Fields  */
501923ec6965SJ. Bruce Fields static int
50208687b63aSAl Viro nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
502123ec6965SJ. Bruce Fields {
502223ec6965SJ. Bruce Fields 	struct xdr_stream xdr;
502323ec6965SJ. Bruce Fields 	struct compound_hdr hdr = {
502466cc0429SBenny Halevy 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
502523ec6965SJ. Bruce Fields 	};
502623ec6965SJ. Bruce Fields 	int status;
502723ec6965SJ. Bruce Fields 
502823ec6965SJ. Bruce Fields 	xdr_init_encode(&xdr, &req->rq_snd_buf, p);
50290c4e8c18SBenny Halevy 	encode_compound_hdr(&xdr, req, &hdr);
50309b7b9fccSAndy Adamson 	encode_sequence(&xdr, &args->seq_args, &hdr);
5031cf8cdbe5SAndy Adamson 	encode_putfh(&xdr, args->fh, &hdr);
5032d017931cSAndy Adamson 	status = encode_setacl(&xdr, args, &hdr);
5033d017931cSAndy Adamson 	encode_nops(&hdr);
503423ec6965SJ. Bruce Fields 	return status;
503523ec6965SJ. Bruce Fields }
503605d564feSAndy Adamson 
503723ec6965SJ. Bruce Fields /*
503823ec6965SJ. Bruce Fields  * Decode SETACL response
503923ec6965SJ. Bruce Fields  */
504023ec6965SJ. Bruce Fields static int
504173c403a9SBenny Halevy nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
504273c403a9SBenny Halevy 		    struct nfs_setaclres *res)
504323ec6965SJ. Bruce Fields {
504423ec6965SJ. Bruce Fields 	struct xdr_stream xdr;
504523ec6965SJ. Bruce Fields 	struct compound_hdr hdr;
504623ec6965SJ. Bruce Fields 	int status;
504723ec6965SJ. Bruce Fields 
504823ec6965SJ. Bruce Fields 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
504923ec6965SJ. Bruce Fields 	status = decode_compound_hdr(&xdr, &hdr);
505023ec6965SJ. Bruce Fields 	if (status)
505123ec6965SJ. Bruce Fields 		goto out;
50529b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50539b7b9fccSAndy Adamson 	if (status)
50549b7b9fccSAndy Adamson 		goto out;
505523ec6965SJ. Bruce Fields 	status = decode_putfh(&xdr);
505623ec6965SJ. Bruce Fields 	if (status)
505723ec6965SJ. Bruce Fields 		goto out;
50589e9ecc03SBenny Halevy 	status = decode_setattr(&xdr);
505923ec6965SJ. Bruce Fields out:
506023ec6965SJ. Bruce Fields 	return status;
506123ec6965SJ. Bruce Fields }
50621da177e4SLinus Torvalds 
50631da177e4SLinus Torvalds /*
5064029d105eSJ. Bruce Fields  * Decode GETACL response
5065029d105eSJ. Bruce Fields  */
5066029d105eSJ. Bruce Fields static int
5067663c79b3SBenny Halevy nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
5068663c79b3SBenny Halevy 		    struct nfs_getaclres *res)
5069029d105eSJ. Bruce Fields {
5070029d105eSJ. Bruce Fields 	struct xdr_stream xdr;
5071029d105eSJ. Bruce Fields 	struct compound_hdr hdr;
5072029d105eSJ. Bruce Fields 	int status;
5073029d105eSJ. Bruce Fields 
5074029d105eSJ. Bruce Fields 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5075029d105eSJ. Bruce Fields 	status = decode_compound_hdr(&xdr, &hdr);
5076029d105eSJ. Bruce Fields 	if (status)
5077029d105eSJ. Bruce Fields 		goto out;
50789b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
50799b7b9fccSAndy Adamson 	if (status)
50809b7b9fccSAndy Adamson 		goto out;
5081029d105eSJ. Bruce Fields 	status = decode_putfh(&xdr);
5082029d105eSJ. Bruce Fields 	if (status)
5083029d105eSJ. Bruce Fields 		goto out;
5084663c79b3SBenny Halevy 	status = decode_getacl(&xdr, rqstp, &res->acl_len);
5085029d105eSJ. Bruce Fields 
5086029d105eSJ. Bruce Fields out:
5087029d105eSJ. Bruce Fields 	return status;
5088029d105eSJ. Bruce Fields }
5089029d105eSJ. Bruce Fields 
5090029d105eSJ. Bruce Fields /*
50911da177e4SLinus Torvalds  * Decode CLOSE response
50921da177e4SLinus Torvalds  */
50938687b63aSAl Viro static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
50941da177e4SLinus Torvalds {
50951da177e4SLinus Torvalds 	struct xdr_stream xdr;
50961da177e4SLinus Torvalds 	struct compound_hdr hdr;
50971da177e4SLinus Torvalds 	int status;
50981da177e4SLinus Torvalds 
50991da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51001da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51011da177e4SLinus Torvalds 	if (status)
51021da177e4SLinus Torvalds 		goto out;
51039b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
51049b7b9fccSAndy Adamson 	if (status)
51059b7b9fccSAndy Adamson 		goto out;
51061da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51071da177e4SLinus Torvalds 	if (status)
51081da177e4SLinus Torvalds 		goto out;
51091da177e4SLinus Torvalds 	status = decode_close(&xdr, res);
5110516a6af6STrond Myklebust 	if (status != 0)
5111516a6af6STrond Myklebust 		goto out;
5112516a6af6STrond Myklebust 	/*
5113516a6af6STrond Myklebust 	 * Note: Server may do delete on close for this file
5114516a6af6STrond Myklebust 	 * 	in which case the getattr call will fail with
5115516a6af6STrond Myklebust 	 * 	an ESTALE error. Shouldn't be a problem,
5116516a6af6STrond Myklebust 	 * 	though, since fattr->valid will remain unset.
5117516a6af6STrond Myklebust 	 */
511880e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
511980e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
51201da177e4SLinus Torvalds out:
51211da177e4SLinus Torvalds 	return status;
51221da177e4SLinus Torvalds }
51231da177e4SLinus Torvalds 
51241da177e4SLinus Torvalds /*
51251da177e4SLinus Torvalds  * Decode OPEN response
51261da177e4SLinus Torvalds  */
51278687b63aSAl Viro static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
51281da177e4SLinus Torvalds {
51291da177e4SLinus Torvalds 	struct xdr_stream xdr;
51301da177e4SLinus Torvalds 	struct compound_hdr hdr;
51311da177e4SLinus Torvalds 	int status;
51321da177e4SLinus Torvalds 
51331da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51341da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51351da177e4SLinus Torvalds 	if (status)
51361da177e4SLinus Torvalds 		goto out;
51379b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
51389b7b9fccSAndy Adamson 	if (status)
51399b7b9fccSAndy Adamson 		goto out;
51401da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51411da177e4SLinus Torvalds 	if (status)
51421da177e4SLinus Torvalds 		goto out;
514356ae19f3STrond Myklebust 	status = decode_savefh(&xdr);
514456ae19f3STrond Myklebust 	if (status)
514556ae19f3STrond Myklebust 		goto out;
51461da177e4SLinus Torvalds 	status = decode_open(&xdr, res);
51471da177e4SLinus Torvalds 	if (status)
51481da177e4SLinus Torvalds 		goto out;
51499936781dSTrond Myklebust 	if (decode_getfh(&xdr, &res->fh) != 0)
51501da177e4SLinus Torvalds 		goto out;
515180e52aceSTrond Myklebust 	if (decode_getfattr(&xdr, res->f_attr, res->server,
515280e52aceSTrond Myklebust 				!RPC_IS_ASYNC(rqstp->rq_task)) != 0)
515356ae19f3STrond Myklebust 		goto out;
5154365c8f58STrond Myklebust 	if (decode_restorefh(&xdr) != 0)
515556ae19f3STrond Myklebust 		goto out;
515680e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->dir_attr, res->server,
515780e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
51581da177e4SLinus Torvalds out:
51591da177e4SLinus Torvalds 	return status;
51601da177e4SLinus Torvalds }
51611da177e4SLinus Torvalds 
51621da177e4SLinus Torvalds /*
51631da177e4SLinus Torvalds  * Decode OPEN_CONFIRM response
51641da177e4SLinus Torvalds  */
51658687b63aSAl Viro static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res)
51661da177e4SLinus Torvalds {
51671da177e4SLinus Torvalds 	struct xdr_stream xdr;
51681da177e4SLinus Torvalds 	struct compound_hdr hdr;
51691da177e4SLinus Torvalds 	int status;
51701da177e4SLinus Torvalds 
51711da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51721da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51731da177e4SLinus Torvalds 	if (status)
51741da177e4SLinus Torvalds 		goto out;
51751da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
51761da177e4SLinus Torvalds 	if (status)
51771da177e4SLinus Torvalds 		goto out;
51781da177e4SLinus Torvalds 	status = decode_open_confirm(&xdr, res);
51791da177e4SLinus Torvalds out:
51801da177e4SLinus Torvalds 	return status;
51811da177e4SLinus Torvalds }
51821da177e4SLinus Torvalds 
51831da177e4SLinus Torvalds /*
51841da177e4SLinus Torvalds  * Decode OPEN response
51851da177e4SLinus Torvalds  */
51868687b63aSAl Viro static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
51871da177e4SLinus Torvalds {
51881da177e4SLinus Torvalds 	struct xdr_stream xdr;
51891da177e4SLinus Torvalds 	struct compound_hdr hdr;
51901da177e4SLinus Torvalds 	int status;
51911da177e4SLinus Torvalds 
51921da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
51931da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
51941da177e4SLinus Torvalds 	if (status)
51951da177e4SLinus Torvalds 		goto out;
51969b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
51979b7b9fccSAndy Adamson 	if (status)
51989b7b9fccSAndy Adamson 		goto out;
51991da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52001da177e4SLinus Torvalds 	if (status)
52011da177e4SLinus Torvalds 		goto out;
52021da177e4SLinus Torvalds 	status = decode_open(&xdr, res);
5203864472e9STrond Myklebust 	if (status)
5204864472e9STrond Myklebust 		goto out;
520580e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->f_attr, res->server,
520680e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
52071da177e4SLinus Torvalds out:
52081da177e4SLinus Torvalds 	return status;
52091da177e4SLinus Torvalds }
52101da177e4SLinus Torvalds 
52111da177e4SLinus Torvalds /*
52121da177e4SLinus Torvalds  * Decode SETATTR response
52131da177e4SLinus Torvalds  */
52148687b63aSAl Viro static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
52151da177e4SLinus Torvalds {
52161da177e4SLinus Torvalds 	struct xdr_stream xdr;
52171da177e4SLinus Torvalds 	struct compound_hdr hdr;
52181da177e4SLinus Torvalds 	int status;
52191da177e4SLinus Torvalds 
52201da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52211da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52221da177e4SLinus Torvalds 	if (status)
52231da177e4SLinus Torvalds 		goto out;
52249b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52259b7b9fccSAndy Adamson 	if (status)
52269b7b9fccSAndy Adamson 		goto out;
52271da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52281da177e4SLinus Torvalds 	if (status)
52291da177e4SLinus Torvalds 		goto out;
52309e9ecc03SBenny Halevy 	status = decode_setattr(&xdr);
52311da177e4SLinus Torvalds 	if (status)
52321da177e4SLinus Torvalds 		goto out;
523380e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
523480e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
52351da177e4SLinus Torvalds out:
52361da177e4SLinus Torvalds 	return status;
52371da177e4SLinus Torvalds }
52381da177e4SLinus Torvalds 
52391da177e4SLinus Torvalds /*
52401da177e4SLinus Torvalds  * Decode LOCK response
52411da177e4SLinus Torvalds  */
52428687b63aSAl Viro static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
52431da177e4SLinus Torvalds {
52441da177e4SLinus Torvalds 	struct xdr_stream xdr;
52451da177e4SLinus Torvalds 	struct compound_hdr hdr;
52461da177e4SLinus Torvalds 	int status;
52471da177e4SLinus Torvalds 
52481da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52491da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52501da177e4SLinus Torvalds 	if (status)
52511da177e4SLinus Torvalds 		goto out;
52529b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52539b7b9fccSAndy Adamson 	if (status)
52549b7b9fccSAndy Adamson 		goto out;
52551da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52561da177e4SLinus Torvalds 	if (status)
52571da177e4SLinus Torvalds 		goto out;
52581da177e4SLinus Torvalds 	status = decode_lock(&xdr, res);
52591da177e4SLinus Torvalds out:
52601da177e4SLinus Torvalds 	return status;
52611da177e4SLinus Torvalds }
52621da177e4SLinus Torvalds 
52631da177e4SLinus Torvalds /*
52641da177e4SLinus Torvalds  * Decode LOCKT response
52651da177e4SLinus Torvalds  */
52668687b63aSAl Viro static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
52671da177e4SLinus Torvalds {
52681da177e4SLinus Torvalds 	struct xdr_stream xdr;
52691da177e4SLinus Torvalds 	struct compound_hdr hdr;
52701da177e4SLinus Torvalds 	int status;
52711da177e4SLinus Torvalds 
52721da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52731da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52741da177e4SLinus Torvalds 	if (status)
52751da177e4SLinus Torvalds 		goto out;
52769b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
52779b7b9fccSAndy Adamson 	if (status)
52789b7b9fccSAndy Adamson 		goto out;
52791da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
52801da177e4SLinus Torvalds 	if (status)
52811da177e4SLinus Torvalds 		goto out;
52821da177e4SLinus Torvalds 	status = decode_lockt(&xdr, res);
52831da177e4SLinus Torvalds out:
52841da177e4SLinus Torvalds 	return status;
52851da177e4SLinus Torvalds }
52861da177e4SLinus Torvalds 
52871da177e4SLinus Torvalds /*
52881da177e4SLinus Torvalds  * Decode LOCKU response
52891da177e4SLinus Torvalds  */
52908687b63aSAl Viro static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
52911da177e4SLinus Torvalds {
52921da177e4SLinus Torvalds 	struct xdr_stream xdr;
52931da177e4SLinus Torvalds 	struct compound_hdr hdr;
52941da177e4SLinus Torvalds 	int status;
52951da177e4SLinus Torvalds 
52961da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
52971da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
52981da177e4SLinus Torvalds 	if (status)
52991da177e4SLinus Torvalds 		goto out;
53009b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53019b7b9fccSAndy Adamson 	if (status)
53029b7b9fccSAndy Adamson 		goto out;
53031da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53041da177e4SLinus Torvalds 	if (status)
53051da177e4SLinus Torvalds 		goto out;
53061da177e4SLinus Torvalds 	status = decode_locku(&xdr, res);
53071da177e4SLinus Torvalds out:
53081da177e4SLinus Torvalds 	return status;
53091da177e4SLinus Torvalds }
53101da177e4SLinus Torvalds 
5311d3c7b7ccSTrond Myklebust static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
5312d3c7b7ccSTrond Myklebust {
5313d3c7b7ccSTrond Myklebust 	struct xdr_stream xdr;
5314d3c7b7ccSTrond Myklebust 	struct compound_hdr hdr;
5315d3c7b7ccSTrond Myklebust 	int status;
5316d3c7b7ccSTrond Myklebust 
5317d3c7b7ccSTrond Myklebust 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5318d3c7b7ccSTrond Myklebust 	status = decode_compound_hdr(&xdr, &hdr);
5319d3c7b7ccSTrond Myklebust 	if (!status)
5320d3c7b7ccSTrond Myklebust 		status = decode_release_lockowner(&xdr);
5321d3c7b7ccSTrond Myklebust 	return status;
5322d3c7b7ccSTrond Myklebust }
5323d3c7b7ccSTrond Myklebust 
53241da177e4SLinus Torvalds /*
53251da177e4SLinus Torvalds  * Decode READLINK response
53261da177e4SLinus Torvalds  */
5327f50c7000SBenny Halevy static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
5328f50c7000SBenny Halevy 				 struct nfs4_readlink_res *res)
53291da177e4SLinus Torvalds {
53301da177e4SLinus Torvalds 	struct xdr_stream xdr;
53311da177e4SLinus Torvalds 	struct compound_hdr hdr;
53321da177e4SLinus Torvalds 	int status;
53331da177e4SLinus Torvalds 
53341da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53351da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53361da177e4SLinus Torvalds 	if (status)
53371da177e4SLinus Torvalds 		goto out;
53389b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53399b7b9fccSAndy Adamson 	if (status)
53409b7b9fccSAndy Adamson 		goto out;
53411da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53421da177e4SLinus Torvalds 	if (status)
53431da177e4SLinus Torvalds 		goto out;
53441da177e4SLinus Torvalds 	status = decode_readlink(&xdr, rqstp);
53451da177e4SLinus Torvalds out:
53461da177e4SLinus Torvalds 	return status;
53471da177e4SLinus Torvalds }
53481da177e4SLinus Torvalds 
53491da177e4SLinus Torvalds /*
53501da177e4SLinus Torvalds  * Decode READDIR response
53511da177e4SLinus Torvalds  */
53528687b63aSAl Viro static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
53531da177e4SLinus Torvalds {
53541da177e4SLinus Torvalds 	struct xdr_stream xdr;
53551da177e4SLinus Torvalds 	struct compound_hdr hdr;
53561da177e4SLinus Torvalds 	int status;
53571da177e4SLinus Torvalds 
53581da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53591da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53601da177e4SLinus Torvalds 	if (status)
53611da177e4SLinus Torvalds 		goto out;
53629b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53639b7b9fccSAndy Adamson 	if (status)
53649b7b9fccSAndy Adamson 		goto out;
53651da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53661da177e4SLinus Torvalds 	if (status)
53671da177e4SLinus Torvalds 		goto out;
53681da177e4SLinus Torvalds 	status = decode_readdir(&xdr, rqstp, res);
53691da177e4SLinus Torvalds out:
53701da177e4SLinus Torvalds 	return status;
53711da177e4SLinus Torvalds }
53721da177e4SLinus Torvalds 
53731da177e4SLinus Torvalds /*
53741da177e4SLinus Torvalds  * Decode Read response
53751da177e4SLinus Torvalds  */
53768687b63aSAl Viro static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
53771da177e4SLinus Torvalds {
53781da177e4SLinus Torvalds 	struct xdr_stream xdr;
53791da177e4SLinus Torvalds 	struct compound_hdr hdr;
53801da177e4SLinus Torvalds 	int status;
53811da177e4SLinus Torvalds 
53821da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
53831da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
53841da177e4SLinus Torvalds 	if (status)
53851da177e4SLinus Torvalds 		goto out;
53869b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
53879b7b9fccSAndy Adamson 	if (status)
53889b7b9fccSAndy Adamson 		goto out;
53891da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
53901da177e4SLinus Torvalds 	if (status)
53911da177e4SLinus Torvalds 		goto out;
53921da177e4SLinus Torvalds 	status = decode_read(&xdr, rqstp, res);
53931da177e4SLinus Torvalds 	if (!status)
53941da177e4SLinus Torvalds 		status = res->count;
53951da177e4SLinus Torvalds out:
53961da177e4SLinus Torvalds 	return status;
53971da177e4SLinus Torvalds }
53981da177e4SLinus Torvalds 
53991da177e4SLinus Torvalds /*
54001da177e4SLinus Torvalds  * Decode WRITE response
54011da177e4SLinus Torvalds  */
54028687b63aSAl Viro static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
54031da177e4SLinus Torvalds {
54041da177e4SLinus Torvalds 	struct xdr_stream xdr;
54051da177e4SLinus Torvalds 	struct compound_hdr hdr;
54061da177e4SLinus Torvalds 	int status;
54071da177e4SLinus Torvalds 
54081da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
54091da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54101da177e4SLinus Torvalds 	if (status)
54111da177e4SLinus Torvalds 		goto out;
54129b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
54139b7b9fccSAndy Adamson 	if (status)
54149b7b9fccSAndy Adamson 		goto out;
54151da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
54161da177e4SLinus Torvalds 	if (status)
54171da177e4SLinus Torvalds 		goto out;
54181da177e4SLinus Torvalds 	status = decode_write(&xdr, res);
54194f9838c7STrond Myklebust 	if (status)
54204f9838c7STrond Myklebust 		goto out;
542180e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
542280e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
54231da177e4SLinus Torvalds 	if (!status)
54241da177e4SLinus Torvalds 		status = res->count;
54251da177e4SLinus Torvalds out:
54261da177e4SLinus Torvalds 	return status;
54271da177e4SLinus Torvalds }
54281da177e4SLinus Torvalds 
54291da177e4SLinus Torvalds /*
54301da177e4SLinus Torvalds  * Decode COMMIT response
54311da177e4SLinus Torvalds  */
54328687b63aSAl Viro static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
54331da177e4SLinus Torvalds {
54341da177e4SLinus Torvalds 	struct xdr_stream xdr;
54351da177e4SLinus Torvalds 	struct compound_hdr hdr;
54361da177e4SLinus Torvalds 	int status;
54371da177e4SLinus Torvalds 
54381da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
54391da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54401da177e4SLinus Torvalds 	if (status)
54411da177e4SLinus Torvalds 		goto out;
54429b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
54439b7b9fccSAndy Adamson 	if (status)
54449b7b9fccSAndy Adamson 		goto out;
54451da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
54461da177e4SLinus Torvalds 	if (status)
54471da177e4SLinus Torvalds 		goto out;
54481da177e4SLinus Torvalds 	status = decode_commit(&xdr, res);
54494f9838c7STrond Myklebust 	if (status)
54504f9838c7STrond Myklebust 		goto out;
545180e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
545280e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
54531da177e4SLinus Torvalds out:
54541da177e4SLinus Torvalds 	return status;
54551da177e4SLinus Torvalds }
54561da177e4SLinus Torvalds 
54571da177e4SLinus Torvalds /*
54588b173218SRicardo Labiaga  * Decode FSINFO response
54591da177e4SLinus Torvalds  */
54603dda5e43SBenny Halevy static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
54613dda5e43SBenny Halevy 			       struct nfs4_fsinfo_res *res)
54621da177e4SLinus Torvalds {
54631da177e4SLinus Torvalds 	struct xdr_stream xdr;
54641da177e4SLinus Torvalds 	struct compound_hdr hdr;
54651da177e4SLinus Torvalds 	int status;
54661da177e4SLinus Torvalds 
54671da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
54681da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54691da177e4SLinus Torvalds 	if (!status)
54709b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
54719b7b9fccSAndy Adamson 	if (!status)
54721da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
54731da177e4SLinus Torvalds 	if (!status)
54743dda5e43SBenny Halevy 		status = decode_fsinfo(&xdr, res->fsinfo);
54751da177e4SLinus Torvalds 	return status;
54761da177e4SLinus Torvalds }
54771da177e4SLinus Torvalds 
54781da177e4SLinus Torvalds /*
54798b173218SRicardo Labiaga  * Decode PATHCONF response
54801da177e4SLinus Torvalds  */
5481d45b2989SBenny Halevy static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
5482d45b2989SBenny Halevy 				 struct nfs4_pathconf_res *res)
54831da177e4SLinus Torvalds {
54841da177e4SLinus Torvalds 	struct xdr_stream xdr;
54851da177e4SLinus Torvalds 	struct compound_hdr hdr;
54861da177e4SLinus Torvalds 	int status;
54871da177e4SLinus Torvalds 
54881da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
54891da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
54901da177e4SLinus Torvalds 	if (!status)
54919b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
54929b7b9fccSAndy Adamson 	if (!status)
54931da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
54941da177e4SLinus Torvalds 	if (!status)
5495d45b2989SBenny Halevy 		status = decode_pathconf(&xdr, res->pathconf);
54961da177e4SLinus Torvalds 	return status;
54971da177e4SLinus Torvalds }
54981da177e4SLinus Torvalds 
54991da177e4SLinus Torvalds /*
55008b173218SRicardo Labiaga  * Decode STATFS response
55011da177e4SLinus Torvalds  */
550224ad148aSBenny Halevy static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
550324ad148aSBenny Halevy 			       struct nfs4_statfs_res *res)
55041da177e4SLinus Torvalds {
55051da177e4SLinus Torvalds 	struct xdr_stream xdr;
55061da177e4SLinus Torvalds 	struct compound_hdr hdr;
55071da177e4SLinus Torvalds 	int status;
55081da177e4SLinus Torvalds 
55091da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55101da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55111da177e4SLinus Torvalds 	if (!status)
55129b7b9fccSAndy Adamson 		status = decode_sequence(&xdr, &res->seq_res, req);
55139b7b9fccSAndy Adamson 	if (!status)
55141da177e4SLinus Torvalds 		status = decode_putfh(&xdr);
55151da177e4SLinus Torvalds 	if (!status)
551624ad148aSBenny Halevy 		status = decode_statfs(&xdr, res->fsstat);
55171da177e4SLinus Torvalds 	return status;
55181da177e4SLinus Torvalds }
55191da177e4SLinus Torvalds 
55201da177e4SLinus Torvalds /*
55218b173218SRicardo Labiaga  * Decode GETATTR_BITMAP response
55221da177e4SLinus Torvalds  */
55238687b63aSAl Viro static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
55241da177e4SLinus Torvalds {
55251da177e4SLinus Torvalds 	struct xdr_stream xdr;
55261da177e4SLinus Torvalds 	struct compound_hdr hdr;
55271da177e4SLinus Torvalds 	int status;
55281da177e4SLinus Torvalds 
55291da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55309b7b9fccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
55319b7b9fccSAndy Adamson 	if (status)
55329b7b9fccSAndy Adamson 		goto out;
55339b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, req);
55349b7b9fccSAndy Adamson 	if (status)
55351da177e4SLinus Torvalds 		goto out;
55361da177e4SLinus Torvalds 	if ((status = decode_putfh(&xdr)) != 0)
55371da177e4SLinus Torvalds 		goto out;
55381da177e4SLinus Torvalds 	status = decode_server_caps(&xdr, res);
55391da177e4SLinus Torvalds out:
55401da177e4SLinus Torvalds 	return status;
55411da177e4SLinus Torvalds }
55421da177e4SLinus Torvalds 
55431da177e4SLinus Torvalds /*
55441da177e4SLinus Torvalds  * Decode RENEW response
55451da177e4SLinus Torvalds  */
55468687b63aSAl Viro static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
55471da177e4SLinus Torvalds {
55481da177e4SLinus Torvalds 	struct xdr_stream xdr;
55491da177e4SLinus Torvalds 	struct compound_hdr hdr;
55501da177e4SLinus Torvalds 	int status;
55511da177e4SLinus Torvalds 
55521da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
55531da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55541da177e4SLinus Torvalds 	if (!status)
55551da177e4SLinus Torvalds 		status = decode_renew(&xdr);
55561da177e4SLinus Torvalds 	return status;
55571da177e4SLinus Torvalds }
55581da177e4SLinus Torvalds 
55591da177e4SLinus Torvalds /*
55608b173218SRicardo Labiaga  * Decode SETCLIENTID response
55611da177e4SLinus Torvalds  */
55628687b63aSAl Viro static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
5563bb8b27e5STrond Myklebust 		struct nfs4_setclientid_res *res)
55641da177e4SLinus Torvalds {
55651da177e4SLinus Torvalds 	struct xdr_stream xdr;
55661da177e4SLinus Torvalds 	struct compound_hdr hdr;
55671da177e4SLinus Torvalds 	int status;
55681da177e4SLinus Torvalds 
55691da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55701da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55711da177e4SLinus Torvalds 	if (!status)
5572bb8b27e5STrond Myklebust 		status = decode_setclientid(&xdr, res);
55731da177e4SLinus Torvalds 	return status;
55741da177e4SLinus Torvalds }
55751da177e4SLinus Torvalds 
55761da177e4SLinus Torvalds /*
55778b173218SRicardo Labiaga  * Decode SETCLIENTID_CONFIRM response
55781da177e4SLinus Torvalds  */
55798687b63aSAl Viro static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
55801da177e4SLinus Torvalds {
55811da177e4SLinus Torvalds 	struct xdr_stream xdr;
55821da177e4SLinus Torvalds 	struct compound_hdr hdr;
55831da177e4SLinus Torvalds 	int status;
55841da177e4SLinus Torvalds 
55851da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
55861da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
55871da177e4SLinus Torvalds 	if (!status)
55881da177e4SLinus Torvalds 		status = decode_setclientid_confirm(&xdr);
55891da177e4SLinus Torvalds 	if (!status)
55901da177e4SLinus Torvalds 		status = decode_putrootfh(&xdr);
55911da177e4SLinus Torvalds 	if (!status)
55921da177e4SLinus Torvalds 		status = decode_fsinfo(&xdr, fsinfo);
55931da177e4SLinus Torvalds 	return status;
55941da177e4SLinus Torvalds }
55951da177e4SLinus Torvalds 
55961da177e4SLinus Torvalds /*
55978b173218SRicardo Labiaga  * Decode DELEGRETURN response
55981da177e4SLinus Torvalds  */
55998687b63aSAl Viro static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
56001da177e4SLinus Torvalds {
56011da177e4SLinus Torvalds 	struct xdr_stream xdr;
56021da177e4SLinus Torvalds 	struct compound_hdr hdr;
56031da177e4SLinus Torvalds 	int status;
56041da177e4SLinus Torvalds 
56051da177e4SLinus Torvalds 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
56061da177e4SLinus Torvalds 	status = decode_compound_hdr(&xdr, &hdr);
56079b7b9fccSAndy Adamson 	if (status)
56089b7b9fccSAndy Adamson 		goto out;
56099b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, rqstp);
56109b7b9fccSAndy Adamson 	if (status)
5611fa178f29STrond Myklebust 		goto out;
56121da177e4SLinus Torvalds 	status = decode_putfh(&xdr);
5613fa178f29STrond Myklebust 	if (status != 0)
5614fa178f29STrond Myklebust 		goto out;
56151da177e4SLinus Torvalds 	status = decode_delegreturn(&xdr);
5616556ae3bbSJeff Layton 	if (status != 0)
5617556ae3bbSJeff Layton 		goto out;
561880e52aceSTrond Myklebust 	decode_getfattr(&xdr, res->fattr, res->server,
561980e52aceSTrond Myklebust 			!RPC_IS_ASYNC(rqstp->rq_task));
5620fa178f29STrond Myklebust out:
56211da177e4SLinus Torvalds 	return status;
56221da177e4SLinus Torvalds }
56231da177e4SLinus Torvalds 
5624683b57b4STrond Myklebust /*
56258b173218SRicardo Labiaga  * Decode FS_LOCATIONS response
5626683b57b4STrond Myklebust  */
562722958463SBenny Halevy static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
562822958463SBenny Halevy 				     struct nfs4_fs_locations_res *res)
5629683b57b4STrond Myklebust {
5630683b57b4STrond Myklebust 	struct xdr_stream xdr;
5631683b57b4STrond Myklebust 	struct compound_hdr hdr;
5632683b57b4STrond Myklebust 	int status;
5633683b57b4STrond Myklebust 
5634683b57b4STrond Myklebust 	xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5635683b57b4STrond Myklebust 	status = decode_compound_hdr(&xdr, &hdr);
56369b7b9fccSAndy Adamson 	if (status)
56379b7b9fccSAndy Adamson 		goto out;
56389b7b9fccSAndy Adamson 	status = decode_sequence(&xdr, &res->seq_res, req);
56399b7b9fccSAndy Adamson 	if (status)
5640683b57b4STrond Myklebust 		goto out;
5641683b57b4STrond Myklebust 	if ((status = decode_putfh(&xdr)) != 0)
5642683b57b4STrond Myklebust 		goto out;
5643683b57b4STrond Myklebust 	if ((status = decode_lookup(&xdr)) != 0)
5644683b57b4STrond Myklebust 		goto out;
5645683b57b4STrond Myklebust 	xdr_enter_page(&xdr, PAGE_SIZE);
564622958463SBenny Halevy 	status = decode_getfattr(&xdr, &res->fs_locations->fattr,
564780e52aceSTrond Myklebust 				 res->fs_locations->server,
564880e52aceSTrond Myklebust 				 !RPC_IS_ASYNC(req->rq_task));
5649683b57b4STrond Myklebust out:
5650683b57b4STrond Myklebust 	return status;
5651683b57b4STrond Myklebust }
5652683b57b4STrond Myklebust 
565399fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
565499fe60d0SBenny Halevy /*
56558b173218SRicardo Labiaga  * Decode EXCHANGE_ID response
565699fe60d0SBenny Halevy  */
565799fe60d0SBenny Halevy static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
565899fe60d0SBenny Halevy 				    void *res)
565999fe60d0SBenny Halevy {
566099fe60d0SBenny Halevy 	struct xdr_stream xdr;
566199fe60d0SBenny Halevy 	struct compound_hdr hdr;
566299fe60d0SBenny Halevy 	int status;
566399fe60d0SBenny Halevy 
566499fe60d0SBenny Halevy 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
566599fe60d0SBenny Halevy 	status = decode_compound_hdr(&xdr, &hdr);
566699fe60d0SBenny Halevy 	if (!status)
566799fe60d0SBenny Halevy 		status = decode_exchange_id(&xdr, res);
566899fe60d0SBenny Halevy 	return status;
566999fe60d0SBenny Halevy }
56702050f0ccSAndy Adamson 
56712050f0ccSAndy Adamson /*
56728b173218SRicardo Labiaga  * Decode CREATE_SESSION response
5673fc931582SAndy Adamson  */
5674fc931582SAndy Adamson static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
5675fc931582SAndy Adamson 				       struct nfs41_create_session_res *res)
5676fc931582SAndy Adamson {
5677fc931582SAndy Adamson 	struct xdr_stream xdr;
5678fc931582SAndy Adamson 	struct compound_hdr hdr;
5679fc931582SAndy Adamson 	int status;
5680fc931582SAndy Adamson 
5681fc931582SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5682fc931582SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
5683fc931582SAndy Adamson 	if (!status)
5684fc931582SAndy Adamson 		status = decode_create_session(&xdr, res);
5685fc931582SAndy Adamson 	return status;
5686fc931582SAndy Adamson }
5687fc931582SAndy Adamson 
5688fc931582SAndy Adamson /*
56898b173218SRicardo Labiaga  * Decode DESTROY_SESSION response
56900f3e66c6SAndy Adamson  */
56910f3e66c6SAndy Adamson static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
56920f3e66c6SAndy Adamson 					void *dummy)
56930f3e66c6SAndy Adamson {
56940f3e66c6SAndy Adamson 	struct xdr_stream xdr;
56950f3e66c6SAndy Adamson 	struct compound_hdr hdr;
56960f3e66c6SAndy Adamson 	int status;
56970f3e66c6SAndy Adamson 
56980f3e66c6SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
56990f3e66c6SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
57000f3e66c6SAndy Adamson 	if (!status)
57010f3e66c6SAndy Adamson 		status = decode_destroy_session(&xdr, dummy);
57020f3e66c6SAndy Adamson 	return status;
57030f3e66c6SAndy Adamson }
57040f3e66c6SAndy Adamson 
57050f3e66c6SAndy Adamson /*
57068b173218SRicardo Labiaga  * Decode SEQUENCE response
5707fc01cea9SAndy Adamson  */
5708fc01cea9SAndy Adamson static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
5709fc01cea9SAndy Adamson 				 struct nfs4_sequence_res *res)
5710fc01cea9SAndy Adamson {
5711fc01cea9SAndy Adamson 	struct xdr_stream xdr;
5712fc01cea9SAndy Adamson 	struct compound_hdr hdr;
5713fc01cea9SAndy Adamson 	int status;
5714fc01cea9SAndy Adamson 
5715fc01cea9SAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5716fc01cea9SAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
5717fc01cea9SAndy Adamson 	if (!status)
5718fc01cea9SAndy Adamson 		status = decode_sequence(&xdr, res, rqstp);
5719fc01cea9SAndy Adamson 	return status;
5720fc01cea9SAndy Adamson }
5721fc01cea9SAndy Adamson 
5722fc01cea9SAndy Adamson /*
57238b173218SRicardo Labiaga  * Decode GET_LEASE_TIME response
57242050f0ccSAndy Adamson  */
57252050f0ccSAndy Adamson static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
57262050f0ccSAndy Adamson 				       struct nfs4_get_lease_time_res *res)
57272050f0ccSAndy Adamson {
57282050f0ccSAndy Adamson 	struct xdr_stream xdr;
57292050f0ccSAndy Adamson 	struct compound_hdr hdr;
57302050f0ccSAndy Adamson 	int status;
57312050f0ccSAndy Adamson 
57322050f0ccSAndy Adamson 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
57332050f0ccSAndy Adamson 	status = decode_compound_hdr(&xdr, &hdr);
57342050f0ccSAndy Adamson 	if (!status)
57352050f0ccSAndy Adamson 		status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
57362050f0ccSAndy Adamson 	if (!status)
57372050f0ccSAndy Adamson 		status = decode_putrootfh(&xdr);
57382050f0ccSAndy Adamson 	if (!status)
57392050f0ccSAndy Adamson 		status = decode_fsinfo(&xdr, res->lr_fsinfo);
57402050f0ccSAndy Adamson 	return status;
57412050f0ccSAndy Adamson }
574218019753SRicardo Labiaga 
574318019753SRicardo Labiaga /*
574418019753SRicardo Labiaga  * Decode RECLAIM_COMPLETE response
574518019753SRicardo Labiaga  */
574618019753SRicardo Labiaga static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp, uint32_t *p,
574718019753SRicardo Labiaga 					 struct nfs41_reclaim_complete_res *res)
574818019753SRicardo Labiaga {
574918019753SRicardo Labiaga 	struct xdr_stream xdr;
575018019753SRicardo Labiaga 	struct compound_hdr hdr;
575118019753SRicardo Labiaga 	int status;
575218019753SRicardo Labiaga 
575318019753SRicardo Labiaga 	xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
575418019753SRicardo Labiaga 	status = decode_compound_hdr(&xdr, &hdr);
575518019753SRicardo Labiaga 	if (!status)
575618019753SRicardo Labiaga 		status = decode_sequence(&xdr, &res->seq_res, rqstp);
575718019753SRicardo Labiaga 	if (!status)
575818019753SRicardo Labiaga 		status = decode_reclaim_complete(&xdr, (void *)NULL);
575918019753SRicardo Labiaga 	return status;
576018019753SRicardo Labiaga }
576199fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
576299fe60d0SBenny Halevy 
57630dbb4c67SAl Viro __be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
57641da177e4SLinus Torvalds {
57651da177e4SLinus Torvalds 	uint32_t bitmap[2] = {0};
57661da177e4SLinus Torvalds 	uint32_t len;
57671da177e4SLinus Torvalds 
57681da177e4SLinus Torvalds 	if (!*p++) {
57691da177e4SLinus Torvalds 		if (!*p)
57701da177e4SLinus Torvalds 			return ERR_PTR(-EAGAIN);
57711da177e4SLinus Torvalds 		entry->eof = 1;
57721da177e4SLinus Torvalds 		return ERR_PTR(-EBADCOOKIE);
57731da177e4SLinus Torvalds 	}
57741da177e4SLinus Torvalds 
57751da177e4SLinus Torvalds 	entry->prev_cookie = entry->cookie;
57761da177e4SLinus Torvalds 	p = xdr_decode_hyper(p, &entry->cookie);
57771da177e4SLinus Torvalds 	entry->len = ntohl(*p++);
57781da177e4SLinus Torvalds 	entry->name = (const char *) p;
57791da177e4SLinus Torvalds 	p += XDR_QUADLEN(entry->len);
57801da177e4SLinus Torvalds 
57811da177e4SLinus Torvalds 	/*
57821da177e4SLinus Torvalds 	 * In case the server doesn't return an inode number,
57831da177e4SLinus Torvalds 	 * we fake one here.  (We don't use inode number 0,
57841da177e4SLinus Torvalds 	 * since glibc seems to choke on it...)
57851da177e4SLinus Torvalds 	 */
57861da177e4SLinus Torvalds 	entry->ino = 1;
57871da177e4SLinus Torvalds 
57881da177e4SLinus Torvalds 	len = ntohl(*p++);		/* bitmap length */
57891da177e4SLinus Torvalds 	if (len-- > 0) {
57901da177e4SLinus Torvalds 		bitmap[0] = ntohl(*p++);
57911da177e4SLinus Torvalds 		if (len-- > 0) {
57921da177e4SLinus Torvalds 			bitmap[1] = ntohl(*p++);
57931da177e4SLinus Torvalds 			p += len;
57941da177e4SLinus Torvalds 		}
57951da177e4SLinus Torvalds 	}
57961da177e4SLinus Torvalds 	len = XDR_QUADLEN(ntohl(*p++));	/* attribute buffer length */
57971da177e4SLinus Torvalds 	if (len > 0) {
579897d312d0SManoj Naik 		if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
579997d312d0SManoj Naik 			bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
580097d312d0SManoj Naik 			/* Ignore the return value of rdattr_error for now */
580197d312d0SManoj Naik 			p++;
580297d312d0SManoj Naik 			len--;
580397d312d0SManoj Naik 		}
58041da177e4SLinus Torvalds 		if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
58051da177e4SLinus Torvalds 			xdr_decode_hyper(p, &entry->ino);
58061da177e4SLinus Torvalds 		else if (bitmap[0] == FATTR4_WORD0_FILEID)
58071da177e4SLinus Torvalds 			xdr_decode_hyper(p, &entry->ino);
58081da177e4SLinus Torvalds 		p += len;
58091da177e4SLinus Torvalds 	}
58101da177e4SLinus Torvalds 
58111da177e4SLinus Torvalds 	entry->eof = !p[0] && p[1];
58121da177e4SLinus Torvalds 	return p;
58131da177e4SLinus Torvalds }
58141da177e4SLinus Torvalds 
58151da177e4SLinus Torvalds /*
58161da177e4SLinus Torvalds  * We need to translate between nfs status return values and
58171da177e4SLinus Torvalds  * the local errno values which may not be the same.
58181da177e4SLinus Torvalds  */
58191da177e4SLinus Torvalds static struct {
58201da177e4SLinus Torvalds 	int stat;
58211da177e4SLinus Torvalds 	int errno;
58221da177e4SLinus Torvalds } nfs_errtbl[] = {
58231da177e4SLinus Torvalds 	{ NFS4_OK,		0		},
5824856dff3dSBenny Halevy 	{ NFS4ERR_PERM,		-EPERM		},
5825856dff3dSBenny Halevy 	{ NFS4ERR_NOENT,	-ENOENT		},
5826856dff3dSBenny Halevy 	{ NFS4ERR_IO,		-errno_NFSERR_IO},
5827856dff3dSBenny Halevy 	{ NFS4ERR_NXIO,		-ENXIO		},
5828856dff3dSBenny Halevy 	{ NFS4ERR_ACCESS,	-EACCES		},
5829856dff3dSBenny Halevy 	{ NFS4ERR_EXIST,	-EEXIST		},
5830856dff3dSBenny Halevy 	{ NFS4ERR_XDEV,		-EXDEV		},
5831856dff3dSBenny Halevy 	{ NFS4ERR_NOTDIR,	-ENOTDIR	},
5832856dff3dSBenny Halevy 	{ NFS4ERR_ISDIR,	-EISDIR		},
5833856dff3dSBenny Halevy 	{ NFS4ERR_INVAL,	-EINVAL		},
5834856dff3dSBenny Halevy 	{ NFS4ERR_FBIG,		-EFBIG		},
5835856dff3dSBenny Halevy 	{ NFS4ERR_NOSPC,	-ENOSPC		},
5836856dff3dSBenny Halevy 	{ NFS4ERR_ROFS,		-EROFS		},
5837856dff3dSBenny Halevy 	{ NFS4ERR_MLINK,	-EMLINK		},
5838856dff3dSBenny Halevy 	{ NFS4ERR_NAMETOOLONG,	-ENAMETOOLONG	},
5839856dff3dSBenny Halevy 	{ NFS4ERR_NOTEMPTY,	-ENOTEMPTY	},
5840856dff3dSBenny Halevy 	{ NFS4ERR_DQUOT,	-EDQUOT		},
5841856dff3dSBenny Halevy 	{ NFS4ERR_STALE,	-ESTALE		},
5842856dff3dSBenny Halevy 	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
5843856dff3dSBenny Halevy 	{ NFS4ERR_BADOWNER,	-EINVAL		},
5844856dff3dSBenny Halevy 	{ NFS4ERR_BADNAME,	-EINVAL		},
5845856dff3dSBenny Halevy 	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
5846856dff3dSBenny Halevy 	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
5847856dff3dSBenny Halevy 	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
5848fdcb4577STrond Myklebust 	{ NFS4ERR_SERVERFAULT,	-EREMOTEIO	},
5849856dff3dSBenny Halevy 	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
5850856dff3dSBenny Halevy 	{ NFS4ERR_LOCKED,	-EAGAIN		},
5851856dff3dSBenny Halevy 	{ NFS4ERR_SYMLINK,	-ELOOP		},
5852856dff3dSBenny Halevy 	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
5853856dff3dSBenny Halevy 	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
5854856dff3dSBenny Halevy 	{ NFS4ERR_WRONGSEC,	-EPERM		}, /* FIXME: this needs
58551da177e4SLinus Torvalds 						    * to be handled by a
58561da177e4SLinus Torvalds 						    * middle-layer.
58571da177e4SLinus Torvalds 						    */
5858856dff3dSBenny Halevy 	{ -1,			-EIO		}
58591da177e4SLinus Torvalds };
58601da177e4SLinus Torvalds 
58611da177e4SLinus Torvalds /*
58621da177e4SLinus Torvalds  * Convert an NFS error code to a local one.
58631da177e4SLinus Torvalds  * This one is used jointly by NFSv2 and NFSv3.
58641da177e4SLinus Torvalds  */
58651da177e4SLinus Torvalds static int
58660a8ea437SDavid Howells nfs4_stat_to_errno(int stat)
58671da177e4SLinus Torvalds {
58681da177e4SLinus Torvalds 	int i;
58691da177e4SLinus Torvalds 	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
58701da177e4SLinus Torvalds 		if (nfs_errtbl[i].stat == stat)
58711da177e4SLinus Torvalds 			return nfs_errtbl[i].errno;
58721da177e4SLinus Torvalds 	}
58731da177e4SLinus Torvalds 	if (stat <= 10000 || stat > 10100) {
58741da177e4SLinus Torvalds 		/* The server is looney tunes. */
5875fdcb4577STrond Myklebust 		return -EREMOTEIO;
58761da177e4SLinus Torvalds 	}
58771da177e4SLinus Torvalds 	/* If we cannot translate the error, the recovery routines should
58781da177e4SLinus Torvalds 	 * handle it.
58791da177e4SLinus Torvalds 	 * Note: remaining NFSv4 error codes have values > 10000, so should
58801da177e4SLinus Torvalds 	 * not conflict with native Linux error codes.
58811da177e4SLinus Torvalds 	 */
5882856dff3dSBenny Halevy 	return -stat;
58831da177e4SLinus Torvalds }
58841da177e4SLinus Torvalds 
58851da177e4SLinus Torvalds #define PROC(proc, argtype, restype)				\
58861da177e4SLinus Torvalds [NFSPROC4_CLNT_##proc] = {					\
58871da177e4SLinus Torvalds 	.p_proc   = NFSPROC4_COMPOUND,				\
58881da177e4SLinus Torvalds 	.p_encode = (kxdrproc_t) nfs4_xdr_##argtype,		\
58891da177e4SLinus Torvalds 	.p_decode = (kxdrproc_t) nfs4_xdr_##restype,		\
58902bea90d4SChuck Lever 	.p_arglen = NFS4_##argtype##_sz,			\
58912bea90d4SChuck Lever 	.p_replen = NFS4_##restype##_sz,			\
5892cc0175c1SChuck Lever 	.p_statidx = NFSPROC4_CLNT_##proc,			\
5893cc0175c1SChuck Lever 	.p_name   = #proc,					\
58941da177e4SLinus Torvalds }
58951da177e4SLinus Torvalds 
58961da177e4SLinus Torvalds struct rpc_procinfo	nfs4_procedures[] = {
58971da177e4SLinus Torvalds   PROC(READ,		enc_read,	dec_read),
58981da177e4SLinus Torvalds   PROC(WRITE,		enc_write,	dec_write),
58991da177e4SLinus Torvalds   PROC(COMMIT,		enc_commit,	dec_commit),
59001da177e4SLinus Torvalds   PROC(OPEN,		enc_open,	dec_open),
59011da177e4SLinus Torvalds   PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
59021da177e4SLinus Torvalds   PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
59031da177e4SLinus Torvalds   PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
59041da177e4SLinus Torvalds   PROC(CLOSE,		enc_close,	dec_close),
59051da177e4SLinus Torvalds   PROC(SETATTR,		enc_setattr,	dec_setattr),
59061da177e4SLinus Torvalds   PROC(FSINFO,		enc_fsinfo,	dec_fsinfo),
59071da177e4SLinus Torvalds   PROC(RENEW,		enc_renew,	dec_renew),
59081da177e4SLinus Torvalds   PROC(SETCLIENTID,	enc_setclientid,	dec_setclientid),
59091da177e4SLinus Torvalds   PROC(SETCLIENTID_CONFIRM,	enc_setclientid_confirm,	dec_setclientid_confirm),
59101da177e4SLinus Torvalds   PROC(LOCK,            enc_lock,       dec_lock),
59111da177e4SLinus Torvalds   PROC(LOCKT,           enc_lockt,      dec_lockt),
59121da177e4SLinus Torvalds   PROC(LOCKU,           enc_locku,      dec_locku),
59131da177e4SLinus Torvalds   PROC(ACCESS,		enc_access,	dec_access),
59141da177e4SLinus Torvalds   PROC(GETATTR,		enc_getattr,	dec_getattr),
59151da177e4SLinus Torvalds   PROC(LOOKUP,		enc_lookup,	dec_lookup),
59161da177e4SLinus Torvalds   PROC(LOOKUP_ROOT,	enc_lookup_root,	dec_lookup_root),
59171da177e4SLinus Torvalds   PROC(REMOVE,		enc_remove,	dec_remove),
59181da177e4SLinus Torvalds   PROC(RENAME,		enc_rename,	dec_rename),
59191da177e4SLinus Torvalds   PROC(LINK,		enc_link,	dec_link),
59201da177e4SLinus Torvalds   PROC(SYMLINK,		enc_symlink,	dec_symlink),
59211da177e4SLinus Torvalds   PROC(CREATE,		enc_create,	dec_create),
59221da177e4SLinus Torvalds   PROC(PATHCONF,	enc_pathconf,	dec_pathconf),
59231da177e4SLinus Torvalds   PROC(STATFS,		enc_statfs,	dec_statfs),
59241da177e4SLinus Torvalds   PROC(READLINK,	enc_readlink,	dec_readlink),
59251da177e4SLinus Torvalds   PROC(READDIR,		enc_readdir,	dec_readdir),
59261da177e4SLinus Torvalds   PROC(SERVER_CAPS,	enc_server_caps, dec_server_caps),
59271da177e4SLinus Torvalds   PROC(DELEGRETURN,	enc_delegreturn, dec_delegreturn),
5928029d105eSJ. Bruce Fields   PROC(GETACL,		enc_getacl,	dec_getacl),
592923ec6965SJ. Bruce Fields   PROC(SETACL,		enc_setacl,	dec_setacl),
5930683b57b4STrond Myklebust   PROC(FS_LOCATIONS,	enc_fs_locations, dec_fs_locations),
5931d3c7b7ccSTrond Myklebust   PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
593299fe60d0SBenny Halevy #if defined(CONFIG_NFS_V4_1)
593399fe60d0SBenny Halevy   PROC(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
5934fc931582SAndy Adamson   PROC(CREATE_SESSION,	enc_create_session,	dec_create_session),
59350f3e66c6SAndy Adamson   PROC(DESTROY_SESSION,	enc_destroy_session,	dec_destroy_session),
5936fc01cea9SAndy Adamson   PROC(SEQUENCE,	enc_sequence,	dec_sequence),
59372050f0ccSAndy Adamson   PROC(GET_LEASE_TIME,	enc_get_lease_time,	dec_get_lease_time),
593818019753SRicardo Labiaga   PROC(RECLAIM_COMPLETE, enc_reclaim_complete,  dec_reclaim_complete),
593999fe60d0SBenny Halevy #endif /* CONFIG_NFS_V4_1 */
59401da177e4SLinus Torvalds };
59411da177e4SLinus Torvalds 
59421da177e4SLinus Torvalds struct rpc_version		nfs_version4 = {
59431da177e4SLinus Torvalds 	.number			= 4,
5944e8c96f8cSTobias Klauser 	.nrprocs		= ARRAY_SIZE(nfs4_procedures),
59451da177e4SLinus Torvalds 	.procs			= nfs4_procedures
59461da177e4SLinus Torvalds };
59471da177e4SLinus Torvalds 
59481da177e4SLinus Torvalds /*
59491da177e4SLinus Torvalds  * Local variables:
59501da177e4SLinus Torvalds  *  c-basic-offset: 8
59511da177e4SLinus Torvalds  * End:
59521da177e4SLinus Torvalds  */
5953