162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci *  fs/nfs/nfs4xdr.c
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci *  Client-side XDR for NFSv4.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci *  Copyright (c) 2002 The Regents of the University of Michigan.
762306a36Sopenharmony_ci *  All rights reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Kendrick Smith <kmsmith@umich.edu>
1062306a36Sopenharmony_ci *  Andy Adamson   <andros@umich.edu>
1162306a36Sopenharmony_ci *
1262306a36Sopenharmony_ci *  Redistribution and use in source and binary forms, with or without
1362306a36Sopenharmony_ci *  modification, are permitted provided that the following conditions
1462306a36Sopenharmony_ci *  are met:
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *  1. Redistributions of source code must retain the above copyright
1762306a36Sopenharmony_ci *     notice, this list of conditions and the following disclaimer.
1862306a36Sopenharmony_ci *  2. Redistributions in binary form must reproduce the above copyright
1962306a36Sopenharmony_ci *     notice, this list of conditions and the following disclaimer in the
2062306a36Sopenharmony_ci *     documentation and/or other materials provided with the distribution.
2162306a36Sopenharmony_ci *  3. Neither the name of the University nor the names of its
2262306a36Sopenharmony_ci *     contributors may be used to endorse or promote products derived
2362306a36Sopenharmony_ci *     from this software without specific prior written permission.
2462306a36Sopenharmony_ci *
2562306a36Sopenharmony_ci *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
2662306a36Sopenharmony_ci *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
2762306a36Sopenharmony_ci *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
2862306a36Sopenharmony_ci *  DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2962306a36Sopenharmony_ci *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
3062306a36Sopenharmony_ci *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
3162306a36Sopenharmony_ci *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
3262306a36Sopenharmony_ci *  BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
3362306a36Sopenharmony_ci *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
3462306a36Sopenharmony_ci *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
3562306a36Sopenharmony_ci *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
3662306a36Sopenharmony_ci */
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci#include <linux/param.h>
3962306a36Sopenharmony_ci#include <linux/time.h>
4062306a36Sopenharmony_ci#include <linux/mm.h>
4162306a36Sopenharmony_ci#include <linux/errno.h>
4262306a36Sopenharmony_ci#include <linux/string.h>
4362306a36Sopenharmony_ci#include <linux/in.h>
4462306a36Sopenharmony_ci#include <linux/pagemap.h>
4562306a36Sopenharmony_ci#include <linux/proc_fs.h>
4662306a36Sopenharmony_ci#include <linux/kdev_t.h>
4762306a36Sopenharmony_ci#include <linux/module.h>
4862306a36Sopenharmony_ci#include <linux/utsname.h>
4962306a36Sopenharmony_ci#include <linux/sunrpc/clnt.h>
5062306a36Sopenharmony_ci#include <linux/sunrpc/msg_prot.h>
5162306a36Sopenharmony_ci#include <linux/sunrpc/gss_api.h>
5262306a36Sopenharmony_ci#include <linux/nfs.h>
5362306a36Sopenharmony_ci#include <linux/nfs4.h>
5462306a36Sopenharmony_ci#include <linux/nfs_fs.h>
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci#include "nfs4_fs.h"
5762306a36Sopenharmony_ci#include "nfs4trace.h"
5862306a36Sopenharmony_ci#include "internal.h"
5962306a36Sopenharmony_ci#include "nfs4idmap.h"
6062306a36Sopenharmony_ci#include "nfs4session.h"
6162306a36Sopenharmony_ci#include "pnfs.h"
6262306a36Sopenharmony_ci#include "netns.h"
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci#define NFSDBG_FACILITY		NFSDBG_XDR
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci/* Mapping from NFS error code to "errno" error code. */
6762306a36Sopenharmony_ci#define errno_NFSERR_IO		EIO
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_cistruct compound_hdr;
7062306a36Sopenharmony_cistatic int nfs4_stat_to_errno(int);
7162306a36Sopenharmony_cistatic void encode_layoutget(struct xdr_stream *xdr,
7262306a36Sopenharmony_ci			     const struct nfs4_layoutget_args *args,
7362306a36Sopenharmony_ci			     struct compound_hdr *hdr);
7462306a36Sopenharmony_cistatic int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
7562306a36Sopenharmony_ci			     struct nfs4_layoutget_res *res);
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
7862306a36Sopenharmony_ci#ifdef DEBUG
7962306a36Sopenharmony_ci#define NFS4_MAXTAGLEN		20
8062306a36Sopenharmony_ci#else
8162306a36Sopenharmony_ci#define NFS4_MAXTAGLEN		0
8262306a36Sopenharmony_ci#endif
8362306a36Sopenharmony_ci
8462306a36Sopenharmony_ci/* lock,open owner id:
8562306a36Sopenharmony_ci * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT  >> 2)
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_ci#define pagepad_maxsz		(1)
8862306a36Sopenharmony_ci#define open_owner_id_maxsz	(1 + 2 + 1 + 1 + 2)
8962306a36Sopenharmony_ci#define lock_owner_id_maxsz	(1 + 1 + 4)
9062306a36Sopenharmony_ci#define decode_lockowner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
9162306a36Sopenharmony_ci#define compound_encode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
9262306a36Sopenharmony_ci#define compound_decode_hdr_maxsz	(3 + (NFS4_MAXTAGLEN >> 2))
9362306a36Sopenharmony_ci#define op_encode_hdr_maxsz	(1)
9462306a36Sopenharmony_ci#define op_decode_hdr_maxsz	(2)
9562306a36Sopenharmony_ci#define encode_stateid_maxsz	(XDR_QUADLEN(NFS4_STATEID_SIZE))
9662306a36Sopenharmony_ci#define decode_stateid_maxsz	(XDR_QUADLEN(NFS4_STATEID_SIZE))
9762306a36Sopenharmony_ci#define encode_verifier_maxsz	(XDR_QUADLEN(NFS4_VERIFIER_SIZE))
9862306a36Sopenharmony_ci#define decode_verifier_maxsz	(XDR_QUADLEN(NFS4_VERIFIER_SIZE))
9962306a36Sopenharmony_ci#define encode_putfh_maxsz	(op_encode_hdr_maxsz + 1 + \
10062306a36Sopenharmony_ci				(NFS4_FHSIZE >> 2))
10162306a36Sopenharmony_ci#define decode_putfh_maxsz	(op_decode_hdr_maxsz)
10262306a36Sopenharmony_ci#define encode_putrootfh_maxsz	(op_encode_hdr_maxsz)
10362306a36Sopenharmony_ci#define decode_putrootfh_maxsz	(op_decode_hdr_maxsz)
10462306a36Sopenharmony_ci#define encode_getfh_maxsz      (op_encode_hdr_maxsz)
10562306a36Sopenharmony_ci#define decode_getfh_maxsz      (op_decode_hdr_maxsz + 1 + \
10662306a36Sopenharmony_ci				((3+NFS4_FHSIZE) >> 2))
10762306a36Sopenharmony_ci#define nfs4_fattr_bitmap_maxsz 4
10862306a36Sopenharmony_ci#define encode_getattr_maxsz    (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
10962306a36Sopenharmony_ci#define nfstime4_maxsz		(3)
11062306a36Sopenharmony_ci#define nfs4_name_maxsz		(1 + ((3 + NFS4_MAXNAMLEN) >> 2))
11162306a36Sopenharmony_ci#define nfs4_path_maxsz		(1 + ((3 + NFS4_MAXPATHLEN) >> 2))
11262306a36Sopenharmony_ci#define nfs4_owner_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
11362306a36Sopenharmony_ci#define nfs4_group_maxsz	(1 + XDR_QUADLEN(IDMAP_NAMESZ))
11462306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_SECURITY_LABEL
11562306a36Sopenharmony_ci/* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
11662306a36Sopenharmony_ci#define	nfs4_label_maxsz	(4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
11762306a36Sopenharmony_ci#else
11862306a36Sopenharmony_ci#define	nfs4_label_maxsz	0
11962306a36Sopenharmony_ci#endif
12062306a36Sopenharmony_ci/* We support only one layout type per file system */
12162306a36Sopenharmony_ci#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
12262306a36Sopenharmony_ci/* This is based on getfattr, which uses the most attributes: */
12362306a36Sopenharmony_ci#define nfs4_fattr_value_maxsz	(1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
12462306a36Sopenharmony_ci				3*nfstime4_maxsz + \
12562306a36Sopenharmony_ci				nfs4_owner_maxsz + \
12662306a36Sopenharmony_ci				nfs4_group_maxsz + nfs4_label_maxsz + \
12762306a36Sopenharmony_ci				 decode_mdsthreshold_maxsz))
12862306a36Sopenharmony_ci#define nfs4_fattr_maxsz	(nfs4_fattr_bitmap_maxsz + \
12962306a36Sopenharmony_ci				nfs4_fattr_value_maxsz)
13062306a36Sopenharmony_ci#define decode_getattr_maxsz    (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
13162306a36Sopenharmony_ci#define encode_attrs_maxsz	(nfs4_fattr_bitmap_maxsz + \
13262306a36Sopenharmony_ci				 1 + 2 + 1 + \
13362306a36Sopenharmony_ci				nfs4_owner_maxsz + \
13462306a36Sopenharmony_ci				nfs4_group_maxsz + \
13562306a36Sopenharmony_ci				nfs4_label_maxsz + \
13662306a36Sopenharmony_ci				1 + nfstime4_maxsz + \
13762306a36Sopenharmony_ci				1 + nfstime4_maxsz)
13862306a36Sopenharmony_ci#define encode_savefh_maxsz     (op_encode_hdr_maxsz)
13962306a36Sopenharmony_ci#define decode_savefh_maxsz     (op_decode_hdr_maxsz)
14062306a36Sopenharmony_ci#define encode_restorefh_maxsz  (op_encode_hdr_maxsz)
14162306a36Sopenharmony_ci#define decode_restorefh_maxsz  (op_decode_hdr_maxsz)
14262306a36Sopenharmony_ci#define encode_fsinfo_maxsz	(encode_getattr_maxsz)
14362306a36Sopenharmony_ci/* The 5 accounts for the PNFS attributes, and assumes that at most three
14462306a36Sopenharmony_ci * layout types will be returned.
14562306a36Sopenharmony_ci */
14662306a36Sopenharmony_ci#define decode_fsinfo_maxsz	(op_decode_hdr_maxsz + \
14762306a36Sopenharmony_ci				 nfs4_fattr_bitmap_maxsz + 1 + \
14862306a36Sopenharmony_ci				 1 /* lease time */ + \
14962306a36Sopenharmony_ci				 2 /* max filesize */ + \
15062306a36Sopenharmony_ci				 2 /* max read */ + \
15162306a36Sopenharmony_ci				 2 /* max write */ + \
15262306a36Sopenharmony_ci				 nfstime4_maxsz /* time delta */ + \
15362306a36Sopenharmony_ci				 5 /* fs layout types */ + \
15462306a36Sopenharmony_ci				 1 /* layout blksize */ + \
15562306a36Sopenharmony_ci				 1 /* clone blksize */ + \
15662306a36Sopenharmony_ci				 1 /* change attr type */ + \
15762306a36Sopenharmony_ci				 1 /* xattr support */)
15862306a36Sopenharmony_ci#define encode_renew_maxsz	(op_encode_hdr_maxsz + 3)
15962306a36Sopenharmony_ci#define decode_renew_maxsz	(op_decode_hdr_maxsz)
16062306a36Sopenharmony_ci#define encode_setclientid_maxsz \
16162306a36Sopenharmony_ci				(op_encode_hdr_maxsz + \
16262306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
16362306a36Sopenharmony_ci				/* client name */ \
16462306a36Sopenharmony_ci				1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
16562306a36Sopenharmony_ci				1 /* sc_prog */ + \
16662306a36Sopenharmony_ci				1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
16762306a36Sopenharmony_ci				1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
16862306a36Sopenharmony_ci				1) /* sc_cb_ident */
16962306a36Sopenharmony_ci#define decode_setclientid_maxsz \
17062306a36Sopenharmony_ci				(op_decode_hdr_maxsz + \
17162306a36Sopenharmony_ci				2 /* clientid */ + \
17262306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
17362306a36Sopenharmony_ci				1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
17462306a36Sopenharmony_ci				1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
17562306a36Sopenharmony_ci#define encode_setclientid_confirm_maxsz \
17662306a36Sopenharmony_ci				(op_encode_hdr_maxsz + \
17762306a36Sopenharmony_ci				3 + (NFS4_VERIFIER_SIZE >> 2))
17862306a36Sopenharmony_ci#define decode_setclientid_confirm_maxsz \
17962306a36Sopenharmony_ci				(op_decode_hdr_maxsz)
18062306a36Sopenharmony_ci#define encode_lookup_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
18162306a36Sopenharmony_ci#define decode_lookup_maxsz	(op_decode_hdr_maxsz)
18262306a36Sopenharmony_ci#define encode_lookupp_maxsz	(op_encode_hdr_maxsz)
18362306a36Sopenharmony_ci#define decode_lookupp_maxsz	(op_decode_hdr_maxsz)
18462306a36Sopenharmony_ci#define encode_share_access_maxsz \
18562306a36Sopenharmony_ci				(2)
18662306a36Sopenharmony_ci#define encode_createmode_maxsz	(1 + encode_attrs_maxsz + encode_verifier_maxsz)
18762306a36Sopenharmony_ci#define encode_opentype_maxsz	(1 + encode_createmode_maxsz)
18862306a36Sopenharmony_ci#define encode_claim_null_maxsz	(1 + nfs4_name_maxsz)
18962306a36Sopenharmony_ci#define encode_open_maxsz	(op_encode_hdr_maxsz + \
19062306a36Sopenharmony_ci				2 + encode_share_access_maxsz + 2 + \
19162306a36Sopenharmony_ci				open_owner_id_maxsz + \
19262306a36Sopenharmony_ci				encode_opentype_maxsz + \
19362306a36Sopenharmony_ci				encode_claim_null_maxsz)
19462306a36Sopenharmony_ci#define decode_space_limit_maxsz	(3)
19562306a36Sopenharmony_ci#define decode_ace_maxsz	(3 + nfs4_owner_maxsz)
19662306a36Sopenharmony_ci#define decode_delegation_maxsz	(1 + decode_stateid_maxsz + 1 + \
19762306a36Sopenharmony_ci				decode_space_limit_maxsz + \
19862306a36Sopenharmony_ci				decode_ace_maxsz)
19962306a36Sopenharmony_ci#define decode_change_info_maxsz	(5)
20062306a36Sopenharmony_ci#define decode_open_maxsz	(op_decode_hdr_maxsz + \
20162306a36Sopenharmony_ci				decode_stateid_maxsz + \
20262306a36Sopenharmony_ci				decode_change_info_maxsz + 1 + \
20362306a36Sopenharmony_ci				nfs4_fattr_bitmap_maxsz + \
20462306a36Sopenharmony_ci				decode_delegation_maxsz)
20562306a36Sopenharmony_ci#define encode_open_confirm_maxsz \
20662306a36Sopenharmony_ci				(op_encode_hdr_maxsz + \
20762306a36Sopenharmony_ci				 encode_stateid_maxsz + 1)
20862306a36Sopenharmony_ci#define decode_open_confirm_maxsz \
20962306a36Sopenharmony_ci				(op_decode_hdr_maxsz + \
21062306a36Sopenharmony_ci				 decode_stateid_maxsz)
21162306a36Sopenharmony_ci#define encode_open_downgrade_maxsz \
21262306a36Sopenharmony_ci				(op_encode_hdr_maxsz + \
21362306a36Sopenharmony_ci				 encode_stateid_maxsz + 1 + \
21462306a36Sopenharmony_ci				 encode_share_access_maxsz)
21562306a36Sopenharmony_ci#define decode_open_downgrade_maxsz \
21662306a36Sopenharmony_ci				(op_decode_hdr_maxsz + \
21762306a36Sopenharmony_ci				 decode_stateid_maxsz)
21862306a36Sopenharmony_ci#define encode_close_maxsz	(op_encode_hdr_maxsz + \
21962306a36Sopenharmony_ci				 1 + encode_stateid_maxsz)
22062306a36Sopenharmony_ci#define decode_close_maxsz	(op_decode_hdr_maxsz + \
22162306a36Sopenharmony_ci				 decode_stateid_maxsz)
22262306a36Sopenharmony_ci#define encode_setattr_maxsz	(op_encode_hdr_maxsz + \
22362306a36Sopenharmony_ci				 encode_stateid_maxsz + \
22462306a36Sopenharmony_ci				 encode_attrs_maxsz)
22562306a36Sopenharmony_ci#define decode_setattr_maxsz	(op_decode_hdr_maxsz + \
22662306a36Sopenharmony_ci				 nfs4_fattr_bitmap_maxsz)
22762306a36Sopenharmony_ci#define encode_read_maxsz	(op_encode_hdr_maxsz + \
22862306a36Sopenharmony_ci				 encode_stateid_maxsz + 3)
22962306a36Sopenharmony_ci#define decode_read_maxsz	(op_decode_hdr_maxsz + 2 + pagepad_maxsz)
23062306a36Sopenharmony_ci#define encode_readdir_maxsz	(op_encode_hdr_maxsz + \
23162306a36Sopenharmony_ci				 2 + encode_verifier_maxsz + 5 + \
23262306a36Sopenharmony_ci				nfs4_label_maxsz)
23362306a36Sopenharmony_ci#define decode_readdir_maxsz	(op_decode_hdr_maxsz + \
23462306a36Sopenharmony_ci				 decode_verifier_maxsz + pagepad_maxsz)
23562306a36Sopenharmony_ci#define encode_readlink_maxsz	(op_encode_hdr_maxsz)
23662306a36Sopenharmony_ci#define decode_readlink_maxsz	(op_decode_hdr_maxsz + 1 + pagepad_maxsz)
23762306a36Sopenharmony_ci#define encode_write_maxsz	(op_encode_hdr_maxsz + \
23862306a36Sopenharmony_ci				 encode_stateid_maxsz + 4)
23962306a36Sopenharmony_ci#define decode_write_maxsz	(op_decode_hdr_maxsz + \
24062306a36Sopenharmony_ci				 2 + decode_verifier_maxsz)
24162306a36Sopenharmony_ci#define encode_commit_maxsz	(op_encode_hdr_maxsz + 3)
24262306a36Sopenharmony_ci#define decode_commit_maxsz	(op_decode_hdr_maxsz + \
24362306a36Sopenharmony_ci				 decode_verifier_maxsz)
24462306a36Sopenharmony_ci#define encode_remove_maxsz	(op_encode_hdr_maxsz + \
24562306a36Sopenharmony_ci				nfs4_name_maxsz)
24662306a36Sopenharmony_ci#define decode_remove_maxsz	(op_decode_hdr_maxsz + \
24762306a36Sopenharmony_ci				 decode_change_info_maxsz)
24862306a36Sopenharmony_ci#define encode_rename_maxsz	(op_encode_hdr_maxsz + \
24962306a36Sopenharmony_ci				2 * nfs4_name_maxsz)
25062306a36Sopenharmony_ci#define decode_rename_maxsz	(op_decode_hdr_maxsz + \
25162306a36Sopenharmony_ci				 decode_change_info_maxsz + \
25262306a36Sopenharmony_ci				 decode_change_info_maxsz)
25362306a36Sopenharmony_ci#define encode_link_maxsz	(op_encode_hdr_maxsz + \
25462306a36Sopenharmony_ci				nfs4_name_maxsz)
25562306a36Sopenharmony_ci#define decode_link_maxsz	(op_decode_hdr_maxsz + decode_change_info_maxsz)
25662306a36Sopenharmony_ci#define encode_lockowner_maxsz	(7)
25762306a36Sopenharmony_ci#define encode_lock_maxsz	(op_encode_hdr_maxsz + \
25862306a36Sopenharmony_ci				 7 + \
25962306a36Sopenharmony_ci				 1 + encode_stateid_maxsz + 1 + \
26062306a36Sopenharmony_ci				 encode_lockowner_maxsz)
26162306a36Sopenharmony_ci#define decode_lock_denied_maxsz \
26262306a36Sopenharmony_ci				(8 + decode_lockowner_maxsz)
26362306a36Sopenharmony_ci#define decode_lock_maxsz	(op_decode_hdr_maxsz + \
26462306a36Sopenharmony_ci				 decode_lock_denied_maxsz)
26562306a36Sopenharmony_ci#define encode_lockt_maxsz	(op_encode_hdr_maxsz + 5 + \
26662306a36Sopenharmony_ci				encode_lockowner_maxsz)
26762306a36Sopenharmony_ci#define decode_lockt_maxsz	(op_decode_hdr_maxsz + \
26862306a36Sopenharmony_ci				 decode_lock_denied_maxsz)
26962306a36Sopenharmony_ci#define encode_locku_maxsz	(op_encode_hdr_maxsz + 3 + \
27062306a36Sopenharmony_ci				 encode_stateid_maxsz + \
27162306a36Sopenharmony_ci				 4)
27262306a36Sopenharmony_ci#define decode_locku_maxsz	(op_decode_hdr_maxsz + \
27362306a36Sopenharmony_ci				 decode_stateid_maxsz)
27462306a36Sopenharmony_ci#define encode_release_lockowner_maxsz \
27562306a36Sopenharmony_ci				(op_encode_hdr_maxsz + \
27662306a36Sopenharmony_ci				 encode_lockowner_maxsz)
27762306a36Sopenharmony_ci#define decode_release_lockowner_maxsz \
27862306a36Sopenharmony_ci				(op_decode_hdr_maxsz)
27962306a36Sopenharmony_ci#define encode_access_maxsz	(op_encode_hdr_maxsz + 1)
28062306a36Sopenharmony_ci#define decode_access_maxsz	(op_decode_hdr_maxsz + 2)
28162306a36Sopenharmony_ci#define encode_symlink_maxsz	(op_encode_hdr_maxsz + \
28262306a36Sopenharmony_ci				1 + nfs4_name_maxsz + \
28362306a36Sopenharmony_ci				1 + \
28462306a36Sopenharmony_ci				nfs4_fattr_maxsz)
28562306a36Sopenharmony_ci#define decode_symlink_maxsz	(op_decode_hdr_maxsz + 8)
28662306a36Sopenharmony_ci#define encode_create_maxsz	(op_encode_hdr_maxsz + \
28762306a36Sopenharmony_ci				1 + 2 + nfs4_name_maxsz + \
28862306a36Sopenharmony_ci				encode_attrs_maxsz)
28962306a36Sopenharmony_ci#define decode_create_maxsz	(op_decode_hdr_maxsz + \
29062306a36Sopenharmony_ci				decode_change_info_maxsz + \
29162306a36Sopenharmony_ci				nfs4_fattr_bitmap_maxsz)
29262306a36Sopenharmony_ci#define encode_statfs_maxsz	(encode_getattr_maxsz)
29362306a36Sopenharmony_ci#define decode_statfs_maxsz	(decode_getattr_maxsz)
29462306a36Sopenharmony_ci#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
29562306a36Sopenharmony_ci#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
29662306a36Sopenharmony_ci#define encode_getacl_maxsz	(encode_getattr_maxsz)
29762306a36Sopenharmony_ci#define decode_getacl_maxsz	(op_decode_hdr_maxsz + \
29862306a36Sopenharmony_ci				 nfs4_fattr_bitmap_maxsz + 1 + pagepad_maxsz)
29962306a36Sopenharmony_ci#define encode_setacl_maxsz	(op_encode_hdr_maxsz + \
30062306a36Sopenharmony_ci				 encode_stateid_maxsz + 3)
30162306a36Sopenharmony_ci#define decode_setacl_maxsz	(decode_setattr_maxsz)
30262306a36Sopenharmony_ci#define encode_fs_locations_maxsz \
30362306a36Sopenharmony_ci				(encode_getattr_maxsz)
30462306a36Sopenharmony_ci#define decode_fs_locations_maxsz \
30562306a36Sopenharmony_ci				(pagepad_maxsz)
30662306a36Sopenharmony_ci#define encode_secinfo_maxsz	(op_encode_hdr_maxsz + nfs4_name_maxsz)
30762306a36Sopenharmony_ci#define decode_secinfo_maxsz	(op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
31062306a36Sopenharmony_ci#define NFS4_MAX_MACHINE_NAME_LEN (64)
31162306a36Sopenharmony_ci#define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
31262306a36Sopenharmony_ci			 sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
31562306a36Sopenharmony_ci				encode_verifier_maxsz + \
31662306a36Sopenharmony_ci				1 /* co_ownerid.len */ + \
31762306a36Sopenharmony_ci				/* eia_clientowner */ \
31862306a36Sopenharmony_ci				1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
31962306a36Sopenharmony_ci				1 /* flags */ + \
32062306a36Sopenharmony_ci				1 /* spa_how */ + \
32162306a36Sopenharmony_ci				/* max is SP4_MACH_CRED (for now) */ + \
32262306a36Sopenharmony_ci				1 + NFS4_OP_MAP_NUM_WORDS + \
32362306a36Sopenharmony_ci				1 + NFS4_OP_MAP_NUM_WORDS + \
32462306a36Sopenharmony_ci				1 /* implementation id array of size 1 */ + \
32562306a36Sopenharmony_ci				1 /* nii_domain */ + \
32662306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
32762306a36Sopenharmony_ci				1 /* nii_name */ + \
32862306a36Sopenharmony_ci				XDR_QUADLEN(IMPL_NAME_LIMIT) + \
32962306a36Sopenharmony_ci				3 /* nii_date */)
33062306a36Sopenharmony_ci#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
33162306a36Sopenharmony_ci				2 /* eir_clientid */ + \
33262306a36Sopenharmony_ci				1 /* eir_sequenceid */ + \
33362306a36Sopenharmony_ci				1 /* eir_flags */ + \
33462306a36Sopenharmony_ci				1 /* spr_how */ + \
33562306a36Sopenharmony_ci				  /* max is SP4_MACH_CRED (for now) */ + \
33662306a36Sopenharmony_ci				1 + NFS4_OP_MAP_NUM_WORDS + \
33762306a36Sopenharmony_ci				1 + NFS4_OP_MAP_NUM_WORDS + \
33862306a36Sopenharmony_ci				2 /* eir_server_owner.so_minor_id */ + \
33962306a36Sopenharmony_ci				/* eir_server_owner.so_major_id<> */ \
34062306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
34162306a36Sopenharmony_ci				/* eir_server_scope<> */ \
34262306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
34362306a36Sopenharmony_ci				1 /* eir_server_impl_id array length */ + \
34462306a36Sopenharmony_ci				1 /* nii_domain */ + \
34562306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
34662306a36Sopenharmony_ci				1 /* nii_name */ + \
34762306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
34862306a36Sopenharmony_ci				3 /* nii_date */)
34962306a36Sopenharmony_ci#define encode_channel_attrs_maxsz  (6 + 1 /* ca_rdma_ird.len (0) */)
35062306a36Sopenharmony_ci#define decode_channel_attrs_maxsz  (6 + \
35162306a36Sopenharmony_ci				     1 /* ca_rdma_ird.len */ + \
35262306a36Sopenharmony_ci				     1 /* ca_rdma_ird */)
35362306a36Sopenharmony_ci#define encode_create_session_maxsz  (op_encode_hdr_maxsz + \
35462306a36Sopenharmony_ci				     2 /* csa_clientid */ + \
35562306a36Sopenharmony_ci				     1 /* csa_sequence */ + \
35662306a36Sopenharmony_ci				     1 /* csa_flags */ + \
35762306a36Sopenharmony_ci				     encode_channel_attrs_maxsz + \
35862306a36Sopenharmony_ci				     encode_channel_attrs_maxsz + \
35962306a36Sopenharmony_ci				     1 /* csa_cb_program */ + \
36062306a36Sopenharmony_ci				     1 /* csa_sec_parms.len (1) */ + \
36162306a36Sopenharmony_ci				     1 /* cb_secflavor (AUTH_SYS) */ + \
36262306a36Sopenharmony_ci				     1 /* stamp */ + \
36362306a36Sopenharmony_ci				     1 /* machinename.len */ + \
36462306a36Sopenharmony_ci				     XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
36562306a36Sopenharmony_ci				     1 /* uid */ + \
36662306a36Sopenharmony_ci				     1 /* gid */ + \
36762306a36Sopenharmony_ci				     1 /* gids.len (0) */)
36862306a36Sopenharmony_ci#define decode_create_session_maxsz  (op_decode_hdr_maxsz +	\
36962306a36Sopenharmony_ci				     XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
37062306a36Sopenharmony_ci				     1 /* csr_sequence */ + \
37162306a36Sopenharmony_ci				     1 /* csr_flags */ + \
37262306a36Sopenharmony_ci				     decode_channel_attrs_maxsz + \
37362306a36Sopenharmony_ci				     decode_channel_attrs_maxsz)
37462306a36Sopenharmony_ci#define encode_bind_conn_to_session_maxsz  (op_encode_hdr_maxsz + \
37562306a36Sopenharmony_ci				     /* bctsa_sessid */ \
37662306a36Sopenharmony_ci				     XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
37762306a36Sopenharmony_ci				     1 /* bctsa_dir */ + \
37862306a36Sopenharmony_ci				     1 /* bctsa_use_conn_in_rdma_mode */)
37962306a36Sopenharmony_ci#define decode_bind_conn_to_session_maxsz  (op_decode_hdr_maxsz +	\
38062306a36Sopenharmony_ci				     /* bctsr_sessid */ \
38162306a36Sopenharmony_ci				     XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
38262306a36Sopenharmony_ci				     1 /* bctsr_dir */ + \
38362306a36Sopenharmony_ci				     1 /* bctsr_use_conn_in_rdma_mode */)
38462306a36Sopenharmony_ci#define encode_destroy_session_maxsz    (op_encode_hdr_maxsz + 4)
38562306a36Sopenharmony_ci#define decode_destroy_session_maxsz    (op_decode_hdr_maxsz)
38662306a36Sopenharmony_ci#define encode_destroy_clientid_maxsz   (op_encode_hdr_maxsz + 2)
38762306a36Sopenharmony_ci#define decode_destroy_clientid_maxsz   (op_decode_hdr_maxsz)
38862306a36Sopenharmony_ci#define encode_sequence_maxsz	(op_encode_hdr_maxsz + \
38962306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
39062306a36Sopenharmony_ci#define decode_sequence_maxsz	(op_decode_hdr_maxsz + \
39162306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
39262306a36Sopenharmony_ci#define encode_reclaim_complete_maxsz	(op_encode_hdr_maxsz + 4)
39362306a36Sopenharmony_ci#define decode_reclaim_complete_maxsz	(op_decode_hdr_maxsz + 4)
39462306a36Sopenharmony_ci#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \
39562306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
39662306a36Sopenharmony_ci				1 /* layout type */ + \
39762306a36Sopenharmony_ci				1 /* maxcount */ + \
39862306a36Sopenharmony_ci				1 /* bitmap size */ + \
39962306a36Sopenharmony_ci				1 /* notification bitmap length */ + \
40062306a36Sopenharmony_ci				1 /* notification bitmap, word 0 */)
40162306a36Sopenharmony_ci#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
40262306a36Sopenharmony_ci				1 /* layout type */ + \
40362306a36Sopenharmony_ci				1 /* opaque devaddr4 length */ + \
40462306a36Sopenharmony_ci				  /* devaddr4 payload is read into page */ \
40562306a36Sopenharmony_ci				1 /* notification bitmap length */ + \
40662306a36Sopenharmony_ci				1 /* notification bitmap, word 0 */ + \
40762306a36Sopenharmony_ci				pagepad_maxsz /* possible XDR padding */)
40862306a36Sopenharmony_ci#define encode_layoutget_maxsz	(op_encode_hdr_maxsz + 10 + \
40962306a36Sopenharmony_ci				encode_stateid_maxsz)
41062306a36Sopenharmony_ci#define decode_layoutget_maxsz	(op_decode_hdr_maxsz + 8 + \
41162306a36Sopenharmony_ci				decode_stateid_maxsz + \
41262306a36Sopenharmony_ci				XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE) + \
41362306a36Sopenharmony_ci				pagepad_maxsz)
41462306a36Sopenharmony_ci#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz +          \
41562306a36Sopenharmony_ci				2 /* offset */ + \
41662306a36Sopenharmony_ci				2 /* length */ + \
41762306a36Sopenharmony_ci				1 /* reclaim */ + \
41862306a36Sopenharmony_ci				encode_stateid_maxsz + \
41962306a36Sopenharmony_ci				1 /* new offset (true) */ + \
42062306a36Sopenharmony_ci				2 /* last byte written */ + \
42162306a36Sopenharmony_ci				1 /* nt_timechanged (false) */ + \
42262306a36Sopenharmony_ci				1 /* layoutupdate4 layout type */ + \
42362306a36Sopenharmony_ci				1 /* layoutupdate4 opaqueue len */)
42462306a36Sopenharmony_ci				  /* the actual content of layoutupdate4 should
42562306a36Sopenharmony_ci				     be allocated by drivers and spliced in
42662306a36Sopenharmony_ci				     using xdr_write_pages */
42762306a36Sopenharmony_ci#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
42862306a36Sopenharmony_ci#define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \
42962306a36Sopenharmony_ci				encode_stateid_maxsz + \
43062306a36Sopenharmony_ci				1 + \
43162306a36Sopenharmony_ci				XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
43262306a36Sopenharmony_ci#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
43362306a36Sopenharmony_ci				1 + decode_stateid_maxsz)
43462306a36Sopenharmony_ci#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
43562306a36Sopenharmony_ci#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
43662306a36Sopenharmony_ci#define encode_test_stateid_maxsz	(op_encode_hdr_maxsz + 2 + \
43762306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE))
43862306a36Sopenharmony_ci#define decode_test_stateid_maxsz	(op_decode_hdr_maxsz + 2 + 1)
43962306a36Sopenharmony_ci#define encode_free_stateid_maxsz	(op_encode_hdr_maxsz + 1 + \
44062306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE))
44162306a36Sopenharmony_ci#define decode_free_stateid_maxsz	(op_decode_hdr_maxsz)
44262306a36Sopenharmony_ci#else /* CONFIG_NFS_V4_1 */
44362306a36Sopenharmony_ci#define encode_sequence_maxsz	0
44462306a36Sopenharmony_ci#define decode_sequence_maxsz	0
44562306a36Sopenharmony_ci#define encode_layoutreturn_maxsz 0
44662306a36Sopenharmony_ci#define decode_layoutreturn_maxsz 0
44762306a36Sopenharmony_ci#define encode_layoutget_maxsz	0
44862306a36Sopenharmony_ci#define decode_layoutget_maxsz	0
44962306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci#define NFS4_enc_compound_sz	(1024)  /* XXX: large enough? */
45262306a36Sopenharmony_ci#define NFS4_dec_compound_sz	(1024)  /* XXX: large enough? */
45362306a36Sopenharmony_ci#define NFS4_enc_read_sz	(compound_encode_hdr_maxsz + \
45462306a36Sopenharmony_ci				encode_sequence_maxsz + \
45562306a36Sopenharmony_ci				encode_putfh_maxsz + \
45662306a36Sopenharmony_ci				encode_read_maxsz)
45762306a36Sopenharmony_ci#define NFS4_dec_read_sz	(compound_decode_hdr_maxsz + \
45862306a36Sopenharmony_ci				decode_sequence_maxsz + \
45962306a36Sopenharmony_ci				decode_putfh_maxsz + \
46062306a36Sopenharmony_ci				decode_read_maxsz)
46162306a36Sopenharmony_ci#define NFS4_enc_readlink_sz	(compound_encode_hdr_maxsz + \
46262306a36Sopenharmony_ci				encode_sequence_maxsz + \
46362306a36Sopenharmony_ci				encode_putfh_maxsz + \
46462306a36Sopenharmony_ci				encode_readlink_maxsz)
46562306a36Sopenharmony_ci#define NFS4_dec_readlink_sz	(compound_decode_hdr_maxsz + \
46662306a36Sopenharmony_ci				decode_sequence_maxsz + \
46762306a36Sopenharmony_ci				decode_putfh_maxsz + \
46862306a36Sopenharmony_ci				decode_readlink_maxsz)
46962306a36Sopenharmony_ci#define NFS4_enc_readdir_sz	(compound_encode_hdr_maxsz + \
47062306a36Sopenharmony_ci				encode_sequence_maxsz + \
47162306a36Sopenharmony_ci				encode_putfh_maxsz + \
47262306a36Sopenharmony_ci				encode_readdir_maxsz)
47362306a36Sopenharmony_ci#define NFS4_dec_readdir_sz	(compound_decode_hdr_maxsz + \
47462306a36Sopenharmony_ci				decode_sequence_maxsz + \
47562306a36Sopenharmony_ci				decode_putfh_maxsz + \
47662306a36Sopenharmony_ci				decode_readdir_maxsz)
47762306a36Sopenharmony_ci#define NFS4_enc_write_sz	(compound_encode_hdr_maxsz + \
47862306a36Sopenharmony_ci				encode_sequence_maxsz + \
47962306a36Sopenharmony_ci				encode_putfh_maxsz + \
48062306a36Sopenharmony_ci				encode_write_maxsz + \
48162306a36Sopenharmony_ci				encode_getattr_maxsz)
48262306a36Sopenharmony_ci#define NFS4_dec_write_sz	(compound_decode_hdr_maxsz + \
48362306a36Sopenharmony_ci				decode_sequence_maxsz + \
48462306a36Sopenharmony_ci				decode_putfh_maxsz + \
48562306a36Sopenharmony_ci				decode_write_maxsz + \
48662306a36Sopenharmony_ci				decode_getattr_maxsz)
48762306a36Sopenharmony_ci#define NFS4_enc_commit_sz	(compound_encode_hdr_maxsz + \
48862306a36Sopenharmony_ci				encode_sequence_maxsz + \
48962306a36Sopenharmony_ci				encode_putfh_maxsz + \
49062306a36Sopenharmony_ci				encode_commit_maxsz)
49162306a36Sopenharmony_ci#define NFS4_dec_commit_sz	(compound_decode_hdr_maxsz + \
49262306a36Sopenharmony_ci				decode_sequence_maxsz + \
49362306a36Sopenharmony_ci				decode_putfh_maxsz + \
49462306a36Sopenharmony_ci				decode_commit_maxsz)
49562306a36Sopenharmony_ci#define NFS4_enc_open_sz        (compound_encode_hdr_maxsz + \
49662306a36Sopenharmony_ci				encode_sequence_maxsz + \
49762306a36Sopenharmony_ci				encode_putfh_maxsz + \
49862306a36Sopenharmony_ci				encode_open_maxsz + \
49962306a36Sopenharmony_ci				encode_access_maxsz + \
50062306a36Sopenharmony_ci				encode_getfh_maxsz + \
50162306a36Sopenharmony_ci				encode_getattr_maxsz + \
50262306a36Sopenharmony_ci				encode_layoutget_maxsz)
50362306a36Sopenharmony_ci#define NFS4_dec_open_sz        (compound_decode_hdr_maxsz + \
50462306a36Sopenharmony_ci				decode_sequence_maxsz + \
50562306a36Sopenharmony_ci				decode_putfh_maxsz + \
50662306a36Sopenharmony_ci				decode_open_maxsz + \
50762306a36Sopenharmony_ci				decode_access_maxsz + \
50862306a36Sopenharmony_ci				decode_getfh_maxsz + \
50962306a36Sopenharmony_ci				decode_getattr_maxsz + \
51062306a36Sopenharmony_ci				decode_layoutget_maxsz)
51162306a36Sopenharmony_ci#define NFS4_enc_open_confirm_sz \
51262306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
51362306a36Sopenharmony_ci				 encode_putfh_maxsz + \
51462306a36Sopenharmony_ci				 encode_open_confirm_maxsz)
51562306a36Sopenharmony_ci#define NFS4_dec_open_confirm_sz \
51662306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
51762306a36Sopenharmony_ci				 decode_putfh_maxsz + \
51862306a36Sopenharmony_ci				 decode_open_confirm_maxsz)
51962306a36Sopenharmony_ci#define NFS4_enc_open_noattr_sz	(compound_encode_hdr_maxsz + \
52062306a36Sopenharmony_ci					encode_sequence_maxsz + \
52162306a36Sopenharmony_ci					encode_putfh_maxsz + \
52262306a36Sopenharmony_ci					encode_open_maxsz + \
52362306a36Sopenharmony_ci					encode_access_maxsz + \
52462306a36Sopenharmony_ci					encode_getattr_maxsz + \
52562306a36Sopenharmony_ci					encode_layoutget_maxsz)
52662306a36Sopenharmony_ci#define NFS4_dec_open_noattr_sz	(compound_decode_hdr_maxsz + \
52762306a36Sopenharmony_ci					decode_sequence_maxsz + \
52862306a36Sopenharmony_ci					decode_putfh_maxsz + \
52962306a36Sopenharmony_ci					decode_open_maxsz + \
53062306a36Sopenharmony_ci					decode_access_maxsz + \
53162306a36Sopenharmony_ci					decode_getattr_maxsz + \
53262306a36Sopenharmony_ci					decode_layoutget_maxsz)
53362306a36Sopenharmony_ci#define NFS4_enc_open_downgrade_sz \
53462306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
53562306a36Sopenharmony_ci				 encode_sequence_maxsz + \
53662306a36Sopenharmony_ci				 encode_putfh_maxsz + \
53762306a36Sopenharmony_ci				 encode_layoutreturn_maxsz + \
53862306a36Sopenharmony_ci				 encode_open_downgrade_maxsz)
53962306a36Sopenharmony_ci#define NFS4_dec_open_downgrade_sz \
54062306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
54162306a36Sopenharmony_ci				 decode_sequence_maxsz + \
54262306a36Sopenharmony_ci				 decode_putfh_maxsz + \
54362306a36Sopenharmony_ci				 decode_layoutreturn_maxsz + \
54462306a36Sopenharmony_ci				 decode_open_downgrade_maxsz)
54562306a36Sopenharmony_ci#define NFS4_enc_close_sz	(compound_encode_hdr_maxsz + \
54662306a36Sopenharmony_ci				 encode_sequence_maxsz + \
54762306a36Sopenharmony_ci				 encode_putfh_maxsz + \
54862306a36Sopenharmony_ci				 encode_layoutreturn_maxsz + \
54962306a36Sopenharmony_ci				 encode_close_maxsz + \
55062306a36Sopenharmony_ci				 encode_getattr_maxsz)
55162306a36Sopenharmony_ci#define NFS4_dec_close_sz	(compound_decode_hdr_maxsz + \
55262306a36Sopenharmony_ci				 decode_sequence_maxsz + \
55362306a36Sopenharmony_ci				 decode_putfh_maxsz + \
55462306a36Sopenharmony_ci				 decode_layoutreturn_maxsz + \
55562306a36Sopenharmony_ci				 decode_close_maxsz + \
55662306a36Sopenharmony_ci				 decode_getattr_maxsz)
55762306a36Sopenharmony_ci#define NFS4_enc_setattr_sz	(compound_encode_hdr_maxsz + \
55862306a36Sopenharmony_ci				 encode_sequence_maxsz + \
55962306a36Sopenharmony_ci				 encode_putfh_maxsz + \
56062306a36Sopenharmony_ci				 encode_setattr_maxsz + \
56162306a36Sopenharmony_ci				 encode_getattr_maxsz)
56262306a36Sopenharmony_ci#define NFS4_dec_setattr_sz	(compound_decode_hdr_maxsz + \
56362306a36Sopenharmony_ci				 decode_sequence_maxsz + \
56462306a36Sopenharmony_ci				 decode_putfh_maxsz + \
56562306a36Sopenharmony_ci				 decode_setattr_maxsz + \
56662306a36Sopenharmony_ci				 decode_getattr_maxsz)
56762306a36Sopenharmony_ci#define NFS4_enc_fsinfo_sz	(compound_encode_hdr_maxsz + \
56862306a36Sopenharmony_ci				encode_sequence_maxsz + \
56962306a36Sopenharmony_ci				encode_putfh_maxsz + \
57062306a36Sopenharmony_ci				encode_fsinfo_maxsz)
57162306a36Sopenharmony_ci#define NFS4_dec_fsinfo_sz	(compound_decode_hdr_maxsz + \
57262306a36Sopenharmony_ci				decode_sequence_maxsz + \
57362306a36Sopenharmony_ci				decode_putfh_maxsz + \
57462306a36Sopenharmony_ci				decode_fsinfo_maxsz)
57562306a36Sopenharmony_ci#define NFS4_enc_renew_sz	(compound_encode_hdr_maxsz + \
57662306a36Sopenharmony_ci				encode_renew_maxsz)
57762306a36Sopenharmony_ci#define NFS4_dec_renew_sz	(compound_decode_hdr_maxsz + \
57862306a36Sopenharmony_ci				decode_renew_maxsz)
57962306a36Sopenharmony_ci#define NFS4_enc_setclientid_sz	(compound_encode_hdr_maxsz + \
58062306a36Sopenharmony_ci				encode_setclientid_maxsz)
58162306a36Sopenharmony_ci#define NFS4_dec_setclientid_sz	(compound_decode_hdr_maxsz + \
58262306a36Sopenharmony_ci				decode_setclientid_maxsz)
58362306a36Sopenharmony_ci#define NFS4_enc_setclientid_confirm_sz \
58462306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
58562306a36Sopenharmony_ci				encode_setclientid_confirm_maxsz)
58662306a36Sopenharmony_ci#define NFS4_dec_setclientid_confirm_sz \
58762306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
58862306a36Sopenharmony_ci				decode_setclientid_confirm_maxsz)
58962306a36Sopenharmony_ci#define NFS4_enc_lock_sz        (compound_encode_hdr_maxsz + \
59062306a36Sopenharmony_ci				encode_sequence_maxsz + \
59162306a36Sopenharmony_ci				encode_putfh_maxsz + \
59262306a36Sopenharmony_ci				encode_lock_maxsz)
59362306a36Sopenharmony_ci#define NFS4_dec_lock_sz        (compound_decode_hdr_maxsz + \
59462306a36Sopenharmony_ci				decode_sequence_maxsz + \
59562306a36Sopenharmony_ci				decode_putfh_maxsz + \
59662306a36Sopenharmony_ci				decode_lock_maxsz)
59762306a36Sopenharmony_ci#define NFS4_enc_lockt_sz       (compound_encode_hdr_maxsz + \
59862306a36Sopenharmony_ci				encode_sequence_maxsz + \
59962306a36Sopenharmony_ci				encode_putfh_maxsz + \
60062306a36Sopenharmony_ci				encode_lockt_maxsz)
60162306a36Sopenharmony_ci#define NFS4_dec_lockt_sz       (compound_decode_hdr_maxsz + \
60262306a36Sopenharmony_ci				 decode_sequence_maxsz + \
60362306a36Sopenharmony_ci				 decode_putfh_maxsz + \
60462306a36Sopenharmony_ci				 decode_lockt_maxsz)
60562306a36Sopenharmony_ci#define NFS4_enc_locku_sz       (compound_encode_hdr_maxsz + \
60662306a36Sopenharmony_ci				encode_sequence_maxsz + \
60762306a36Sopenharmony_ci				encode_putfh_maxsz + \
60862306a36Sopenharmony_ci				encode_locku_maxsz)
60962306a36Sopenharmony_ci#define NFS4_dec_locku_sz       (compound_decode_hdr_maxsz + \
61062306a36Sopenharmony_ci				decode_sequence_maxsz + \
61162306a36Sopenharmony_ci				decode_putfh_maxsz + \
61262306a36Sopenharmony_ci				decode_locku_maxsz)
61362306a36Sopenharmony_ci#define NFS4_enc_release_lockowner_sz \
61462306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
61562306a36Sopenharmony_ci				 encode_lockowner_maxsz)
61662306a36Sopenharmony_ci#define NFS4_dec_release_lockowner_sz \
61762306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
61862306a36Sopenharmony_ci				 decode_lockowner_maxsz)
61962306a36Sopenharmony_ci#define NFS4_enc_access_sz	(compound_encode_hdr_maxsz + \
62062306a36Sopenharmony_ci				encode_sequence_maxsz + \
62162306a36Sopenharmony_ci				encode_putfh_maxsz + \
62262306a36Sopenharmony_ci				encode_access_maxsz + \
62362306a36Sopenharmony_ci				encode_getattr_maxsz)
62462306a36Sopenharmony_ci#define NFS4_dec_access_sz	(compound_decode_hdr_maxsz + \
62562306a36Sopenharmony_ci				decode_sequence_maxsz + \
62662306a36Sopenharmony_ci				decode_putfh_maxsz + \
62762306a36Sopenharmony_ci				decode_access_maxsz + \
62862306a36Sopenharmony_ci				decode_getattr_maxsz)
62962306a36Sopenharmony_ci#define NFS4_enc_getattr_sz	(compound_encode_hdr_maxsz + \
63062306a36Sopenharmony_ci				encode_sequence_maxsz + \
63162306a36Sopenharmony_ci				encode_putfh_maxsz + \
63262306a36Sopenharmony_ci				encode_getattr_maxsz + \
63362306a36Sopenharmony_ci				encode_renew_maxsz)
63462306a36Sopenharmony_ci#define NFS4_dec_getattr_sz	(compound_decode_hdr_maxsz + \
63562306a36Sopenharmony_ci				decode_sequence_maxsz + \
63662306a36Sopenharmony_ci				decode_putfh_maxsz + \
63762306a36Sopenharmony_ci				decode_getattr_maxsz + \
63862306a36Sopenharmony_ci				decode_renew_maxsz)
63962306a36Sopenharmony_ci#define NFS4_enc_lookup_sz	(compound_encode_hdr_maxsz + \
64062306a36Sopenharmony_ci				encode_sequence_maxsz + \
64162306a36Sopenharmony_ci				encode_putfh_maxsz + \
64262306a36Sopenharmony_ci				encode_lookup_maxsz + \
64362306a36Sopenharmony_ci				encode_getattr_maxsz + \
64462306a36Sopenharmony_ci				encode_getfh_maxsz)
64562306a36Sopenharmony_ci#define NFS4_dec_lookup_sz	(compound_decode_hdr_maxsz + \
64662306a36Sopenharmony_ci				decode_sequence_maxsz + \
64762306a36Sopenharmony_ci				decode_putfh_maxsz + \
64862306a36Sopenharmony_ci				decode_lookup_maxsz + \
64962306a36Sopenharmony_ci				decode_getattr_maxsz + \
65062306a36Sopenharmony_ci				decode_getfh_maxsz)
65162306a36Sopenharmony_ci#define NFS4_enc_lookupp_sz	(compound_encode_hdr_maxsz + \
65262306a36Sopenharmony_ci				encode_sequence_maxsz + \
65362306a36Sopenharmony_ci				encode_putfh_maxsz + \
65462306a36Sopenharmony_ci				encode_lookupp_maxsz + \
65562306a36Sopenharmony_ci				encode_getattr_maxsz + \
65662306a36Sopenharmony_ci				encode_getfh_maxsz)
65762306a36Sopenharmony_ci#define NFS4_dec_lookupp_sz	(compound_decode_hdr_maxsz + \
65862306a36Sopenharmony_ci				decode_sequence_maxsz + \
65962306a36Sopenharmony_ci				decode_putfh_maxsz + \
66062306a36Sopenharmony_ci				decode_lookupp_maxsz + \
66162306a36Sopenharmony_ci				decode_getattr_maxsz + \
66262306a36Sopenharmony_ci				decode_getfh_maxsz)
66362306a36Sopenharmony_ci#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
66462306a36Sopenharmony_ci				encode_sequence_maxsz + \
66562306a36Sopenharmony_ci				encode_putrootfh_maxsz + \
66662306a36Sopenharmony_ci				encode_getattr_maxsz + \
66762306a36Sopenharmony_ci				encode_getfh_maxsz)
66862306a36Sopenharmony_ci#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
66962306a36Sopenharmony_ci				decode_sequence_maxsz + \
67062306a36Sopenharmony_ci				decode_putrootfh_maxsz + \
67162306a36Sopenharmony_ci				decode_getattr_maxsz + \
67262306a36Sopenharmony_ci				decode_getfh_maxsz)
67362306a36Sopenharmony_ci#define NFS4_enc_remove_sz	(compound_encode_hdr_maxsz + \
67462306a36Sopenharmony_ci				encode_sequence_maxsz + \
67562306a36Sopenharmony_ci				encode_putfh_maxsz + \
67662306a36Sopenharmony_ci				encode_remove_maxsz)
67762306a36Sopenharmony_ci#define NFS4_dec_remove_sz	(compound_decode_hdr_maxsz + \
67862306a36Sopenharmony_ci				decode_sequence_maxsz + \
67962306a36Sopenharmony_ci				decode_putfh_maxsz + \
68062306a36Sopenharmony_ci				decode_remove_maxsz)
68162306a36Sopenharmony_ci#define NFS4_enc_rename_sz	(compound_encode_hdr_maxsz + \
68262306a36Sopenharmony_ci				encode_sequence_maxsz + \
68362306a36Sopenharmony_ci				encode_putfh_maxsz + \
68462306a36Sopenharmony_ci				encode_savefh_maxsz + \
68562306a36Sopenharmony_ci				encode_putfh_maxsz + \
68662306a36Sopenharmony_ci				encode_rename_maxsz)
68762306a36Sopenharmony_ci#define NFS4_dec_rename_sz	(compound_decode_hdr_maxsz + \
68862306a36Sopenharmony_ci				decode_sequence_maxsz + \
68962306a36Sopenharmony_ci				decode_putfh_maxsz + \
69062306a36Sopenharmony_ci				decode_savefh_maxsz + \
69162306a36Sopenharmony_ci				decode_putfh_maxsz + \
69262306a36Sopenharmony_ci				decode_rename_maxsz)
69362306a36Sopenharmony_ci#define NFS4_enc_link_sz	(compound_encode_hdr_maxsz + \
69462306a36Sopenharmony_ci				encode_sequence_maxsz + \
69562306a36Sopenharmony_ci				encode_putfh_maxsz + \
69662306a36Sopenharmony_ci				encode_savefh_maxsz + \
69762306a36Sopenharmony_ci				encode_putfh_maxsz + \
69862306a36Sopenharmony_ci				encode_link_maxsz + \
69962306a36Sopenharmony_ci				encode_restorefh_maxsz + \
70062306a36Sopenharmony_ci				encode_getattr_maxsz)
70162306a36Sopenharmony_ci#define NFS4_dec_link_sz	(compound_decode_hdr_maxsz + \
70262306a36Sopenharmony_ci				decode_sequence_maxsz + \
70362306a36Sopenharmony_ci				decode_putfh_maxsz + \
70462306a36Sopenharmony_ci				decode_savefh_maxsz + \
70562306a36Sopenharmony_ci				decode_putfh_maxsz + \
70662306a36Sopenharmony_ci				decode_link_maxsz + \
70762306a36Sopenharmony_ci				decode_restorefh_maxsz + \
70862306a36Sopenharmony_ci				decode_getattr_maxsz)
70962306a36Sopenharmony_ci#define NFS4_enc_symlink_sz	(compound_encode_hdr_maxsz + \
71062306a36Sopenharmony_ci				encode_sequence_maxsz + \
71162306a36Sopenharmony_ci				encode_putfh_maxsz + \
71262306a36Sopenharmony_ci				encode_symlink_maxsz + \
71362306a36Sopenharmony_ci				encode_getattr_maxsz + \
71462306a36Sopenharmony_ci				encode_getfh_maxsz)
71562306a36Sopenharmony_ci#define NFS4_dec_symlink_sz	(compound_decode_hdr_maxsz + \
71662306a36Sopenharmony_ci				decode_sequence_maxsz + \
71762306a36Sopenharmony_ci				decode_putfh_maxsz + \
71862306a36Sopenharmony_ci				decode_symlink_maxsz + \
71962306a36Sopenharmony_ci				decode_getattr_maxsz + \
72062306a36Sopenharmony_ci				decode_getfh_maxsz)
72162306a36Sopenharmony_ci#define NFS4_enc_create_sz	(compound_encode_hdr_maxsz + \
72262306a36Sopenharmony_ci				encode_sequence_maxsz + \
72362306a36Sopenharmony_ci				encode_putfh_maxsz + \
72462306a36Sopenharmony_ci				encode_create_maxsz + \
72562306a36Sopenharmony_ci				encode_getfh_maxsz + \
72662306a36Sopenharmony_ci				encode_getattr_maxsz)
72762306a36Sopenharmony_ci#define NFS4_dec_create_sz	(compound_decode_hdr_maxsz + \
72862306a36Sopenharmony_ci				decode_sequence_maxsz + \
72962306a36Sopenharmony_ci				decode_putfh_maxsz + \
73062306a36Sopenharmony_ci				decode_create_maxsz + \
73162306a36Sopenharmony_ci				decode_getfh_maxsz + \
73262306a36Sopenharmony_ci				decode_getattr_maxsz)
73362306a36Sopenharmony_ci#define NFS4_enc_pathconf_sz	(compound_encode_hdr_maxsz + \
73462306a36Sopenharmony_ci				encode_sequence_maxsz + \
73562306a36Sopenharmony_ci				encode_putfh_maxsz + \
73662306a36Sopenharmony_ci				encode_getattr_maxsz)
73762306a36Sopenharmony_ci#define NFS4_dec_pathconf_sz	(compound_decode_hdr_maxsz + \
73862306a36Sopenharmony_ci				decode_sequence_maxsz + \
73962306a36Sopenharmony_ci				decode_putfh_maxsz + \
74062306a36Sopenharmony_ci				decode_getattr_maxsz)
74162306a36Sopenharmony_ci#define NFS4_enc_statfs_sz	(compound_encode_hdr_maxsz + \
74262306a36Sopenharmony_ci				encode_sequence_maxsz + \
74362306a36Sopenharmony_ci				encode_putfh_maxsz + \
74462306a36Sopenharmony_ci				encode_statfs_maxsz)
74562306a36Sopenharmony_ci#define NFS4_dec_statfs_sz	(compound_decode_hdr_maxsz + \
74662306a36Sopenharmony_ci				decode_sequence_maxsz + \
74762306a36Sopenharmony_ci				decode_putfh_maxsz + \
74862306a36Sopenharmony_ci				decode_statfs_maxsz)
74962306a36Sopenharmony_ci#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
75062306a36Sopenharmony_ci				encode_sequence_maxsz + \
75162306a36Sopenharmony_ci				encode_putfh_maxsz + \
75262306a36Sopenharmony_ci				encode_getattr_maxsz)
75362306a36Sopenharmony_ci#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
75462306a36Sopenharmony_ci				decode_sequence_maxsz + \
75562306a36Sopenharmony_ci				decode_putfh_maxsz + \
75662306a36Sopenharmony_ci				decode_getattr_maxsz)
75762306a36Sopenharmony_ci#define NFS4_enc_delegreturn_sz	(compound_encode_hdr_maxsz + \
75862306a36Sopenharmony_ci				encode_sequence_maxsz + \
75962306a36Sopenharmony_ci				encode_putfh_maxsz + \
76062306a36Sopenharmony_ci				encode_layoutreturn_maxsz + \
76162306a36Sopenharmony_ci				encode_delegreturn_maxsz + \
76262306a36Sopenharmony_ci				encode_getattr_maxsz)
76362306a36Sopenharmony_ci#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
76462306a36Sopenharmony_ci				decode_sequence_maxsz + \
76562306a36Sopenharmony_ci				decode_putfh_maxsz + \
76662306a36Sopenharmony_ci				decode_layoutreturn_maxsz + \
76762306a36Sopenharmony_ci				decode_delegreturn_maxsz + \
76862306a36Sopenharmony_ci				decode_getattr_maxsz)
76962306a36Sopenharmony_ci#define NFS4_enc_getacl_sz	(compound_encode_hdr_maxsz + \
77062306a36Sopenharmony_ci				encode_sequence_maxsz + \
77162306a36Sopenharmony_ci				encode_putfh_maxsz + \
77262306a36Sopenharmony_ci				encode_getacl_maxsz)
77362306a36Sopenharmony_ci#define NFS4_dec_getacl_sz	(compound_decode_hdr_maxsz + \
77462306a36Sopenharmony_ci				decode_sequence_maxsz + \
77562306a36Sopenharmony_ci				decode_putfh_maxsz + \
77662306a36Sopenharmony_ci				decode_getacl_maxsz)
77762306a36Sopenharmony_ci#define NFS4_enc_setacl_sz	(compound_encode_hdr_maxsz + \
77862306a36Sopenharmony_ci				encode_sequence_maxsz + \
77962306a36Sopenharmony_ci				encode_putfh_maxsz + \
78062306a36Sopenharmony_ci				encode_setacl_maxsz)
78162306a36Sopenharmony_ci#define NFS4_dec_setacl_sz	(compound_decode_hdr_maxsz + \
78262306a36Sopenharmony_ci				decode_sequence_maxsz + \
78362306a36Sopenharmony_ci				decode_putfh_maxsz + \
78462306a36Sopenharmony_ci				decode_setacl_maxsz)
78562306a36Sopenharmony_ci#define NFS4_enc_fs_locations_sz \
78662306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
78762306a36Sopenharmony_ci				 encode_sequence_maxsz + \
78862306a36Sopenharmony_ci				 encode_putfh_maxsz + \
78962306a36Sopenharmony_ci				 encode_lookup_maxsz + \
79062306a36Sopenharmony_ci				 encode_fs_locations_maxsz + \
79162306a36Sopenharmony_ci				 encode_renew_maxsz)
79262306a36Sopenharmony_ci#define NFS4_dec_fs_locations_sz \
79362306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
79462306a36Sopenharmony_ci				 decode_sequence_maxsz + \
79562306a36Sopenharmony_ci				 decode_putfh_maxsz + \
79662306a36Sopenharmony_ci				 decode_lookup_maxsz + \
79762306a36Sopenharmony_ci				 decode_fs_locations_maxsz + \
79862306a36Sopenharmony_ci				 decode_renew_maxsz)
79962306a36Sopenharmony_ci#define NFS4_enc_secinfo_sz 	(compound_encode_hdr_maxsz + \
80062306a36Sopenharmony_ci				encode_sequence_maxsz + \
80162306a36Sopenharmony_ci				encode_putfh_maxsz + \
80262306a36Sopenharmony_ci				encode_secinfo_maxsz)
80362306a36Sopenharmony_ci#define NFS4_dec_secinfo_sz	(compound_decode_hdr_maxsz + \
80462306a36Sopenharmony_ci				decode_sequence_maxsz + \
80562306a36Sopenharmony_ci				decode_putfh_maxsz + \
80662306a36Sopenharmony_ci				decode_secinfo_maxsz)
80762306a36Sopenharmony_ci#define NFS4_enc_fsid_present_sz \
80862306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
80962306a36Sopenharmony_ci				 encode_sequence_maxsz + \
81062306a36Sopenharmony_ci				 encode_putfh_maxsz + \
81162306a36Sopenharmony_ci				 encode_getfh_maxsz + \
81262306a36Sopenharmony_ci				 encode_renew_maxsz)
81362306a36Sopenharmony_ci#define NFS4_dec_fsid_present_sz \
81462306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
81562306a36Sopenharmony_ci				 decode_sequence_maxsz + \
81662306a36Sopenharmony_ci				 decode_putfh_maxsz + \
81762306a36Sopenharmony_ci				 decode_getfh_maxsz + \
81862306a36Sopenharmony_ci				 decode_renew_maxsz)
81962306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
82062306a36Sopenharmony_ci#define NFS4_enc_bind_conn_to_session_sz \
82162306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
82262306a36Sopenharmony_ci				 encode_bind_conn_to_session_maxsz)
82362306a36Sopenharmony_ci#define NFS4_dec_bind_conn_to_session_sz \
82462306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
82562306a36Sopenharmony_ci				 decode_bind_conn_to_session_maxsz)
82662306a36Sopenharmony_ci#define NFS4_enc_exchange_id_sz \
82762306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
82862306a36Sopenharmony_ci				 encode_exchange_id_maxsz)
82962306a36Sopenharmony_ci#define NFS4_dec_exchange_id_sz \
83062306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
83162306a36Sopenharmony_ci				 decode_exchange_id_maxsz)
83262306a36Sopenharmony_ci#define NFS4_enc_create_session_sz \
83362306a36Sopenharmony_ci				(compound_encode_hdr_maxsz + \
83462306a36Sopenharmony_ci				 encode_create_session_maxsz)
83562306a36Sopenharmony_ci#define NFS4_dec_create_session_sz \
83662306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
83762306a36Sopenharmony_ci				 decode_create_session_maxsz)
83862306a36Sopenharmony_ci#define NFS4_enc_destroy_session_sz	(compound_encode_hdr_maxsz + \
83962306a36Sopenharmony_ci					 encode_destroy_session_maxsz)
84062306a36Sopenharmony_ci#define NFS4_dec_destroy_session_sz	(compound_decode_hdr_maxsz + \
84162306a36Sopenharmony_ci					 decode_destroy_session_maxsz)
84262306a36Sopenharmony_ci#define NFS4_enc_destroy_clientid_sz	(compound_encode_hdr_maxsz + \
84362306a36Sopenharmony_ci					 encode_destroy_clientid_maxsz)
84462306a36Sopenharmony_ci#define NFS4_dec_destroy_clientid_sz	(compound_decode_hdr_maxsz + \
84562306a36Sopenharmony_ci					 decode_destroy_clientid_maxsz)
84662306a36Sopenharmony_ci#define NFS4_enc_sequence_sz \
84762306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
84862306a36Sopenharmony_ci				 encode_sequence_maxsz)
84962306a36Sopenharmony_ci#define NFS4_dec_sequence_sz \
85062306a36Sopenharmony_ci				(compound_decode_hdr_maxsz + \
85162306a36Sopenharmony_ci				 decode_sequence_maxsz)
85262306a36Sopenharmony_ci#endif
85362306a36Sopenharmony_ci#define NFS4_enc_get_lease_time_sz	(compound_encode_hdr_maxsz + \
85462306a36Sopenharmony_ci					 encode_sequence_maxsz + \
85562306a36Sopenharmony_ci					 encode_putrootfh_maxsz + \
85662306a36Sopenharmony_ci					 encode_fsinfo_maxsz)
85762306a36Sopenharmony_ci#define NFS4_dec_get_lease_time_sz	(compound_decode_hdr_maxsz + \
85862306a36Sopenharmony_ci					 decode_sequence_maxsz + \
85962306a36Sopenharmony_ci					 decode_putrootfh_maxsz + \
86062306a36Sopenharmony_ci					 decode_fsinfo_maxsz)
86162306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
86262306a36Sopenharmony_ci#define NFS4_enc_reclaim_complete_sz	(compound_encode_hdr_maxsz + \
86362306a36Sopenharmony_ci					 encode_sequence_maxsz + \
86462306a36Sopenharmony_ci					 encode_reclaim_complete_maxsz)
86562306a36Sopenharmony_ci#define NFS4_dec_reclaim_complete_sz	(compound_decode_hdr_maxsz + \
86662306a36Sopenharmony_ci					 decode_sequence_maxsz + \
86762306a36Sopenharmony_ci					 decode_reclaim_complete_maxsz)
86862306a36Sopenharmony_ci#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz +    \
86962306a36Sopenharmony_ci				encode_sequence_maxsz +\
87062306a36Sopenharmony_ci				encode_getdeviceinfo_maxsz)
87162306a36Sopenharmony_ci#define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz +    \
87262306a36Sopenharmony_ci				decode_sequence_maxsz + \
87362306a36Sopenharmony_ci				decode_getdeviceinfo_maxsz)
87462306a36Sopenharmony_ci#define NFS4_enc_layoutget_sz	(compound_encode_hdr_maxsz + \
87562306a36Sopenharmony_ci				encode_sequence_maxsz + \
87662306a36Sopenharmony_ci				encode_putfh_maxsz +        \
87762306a36Sopenharmony_ci				encode_layoutget_maxsz)
87862306a36Sopenharmony_ci#define NFS4_dec_layoutget_sz	(compound_decode_hdr_maxsz + \
87962306a36Sopenharmony_ci				decode_sequence_maxsz + \
88062306a36Sopenharmony_ci				decode_putfh_maxsz +        \
88162306a36Sopenharmony_ci				decode_layoutget_maxsz)
88262306a36Sopenharmony_ci#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \
88362306a36Sopenharmony_ci				encode_sequence_maxsz +\
88462306a36Sopenharmony_ci				encode_putfh_maxsz + \
88562306a36Sopenharmony_ci				encode_layoutcommit_maxsz + \
88662306a36Sopenharmony_ci				encode_getattr_maxsz)
88762306a36Sopenharmony_ci#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \
88862306a36Sopenharmony_ci				decode_sequence_maxsz + \
88962306a36Sopenharmony_ci				decode_putfh_maxsz + \
89062306a36Sopenharmony_ci				decode_layoutcommit_maxsz + \
89162306a36Sopenharmony_ci				decode_getattr_maxsz)
89262306a36Sopenharmony_ci#define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \
89362306a36Sopenharmony_ci				encode_sequence_maxsz + \
89462306a36Sopenharmony_ci				encode_putfh_maxsz + \
89562306a36Sopenharmony_ci				encode_layoutreturn_maxsz)
89662306a36Sopenharmony_ci#define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \
89762306a36Sopenharmony_ci				decode_sequence_maxsz + \
89862306a36Sopenharmony_ci				decode_putfh_maxsz + \
89962306a36Sopenharmony_ci				decode_layoutreturn_maxsz)
90062306a36Sopenharmony_ci#define NFS4_enc_secinfo_no_name_sz	(compound_encode_hdr_maxsz + \
90162306a36Sopenharmony_ci					encode_sequence_maxsz + \
90262306a36Sopenharmony_ci					encode_putrootfh_maxsz +\
90362306a36Sopenharmony_ci					encode_secinfo_no_name_maxsz)
90462306a36Sopenharmony_ci#define NFS4_dec_secinfo_no_name_sz	(compound_decode_hdr_maxsz + \
90562306a36Sopenharmony_ci					decode_sequence_maxsz + \
90662306a36Sopenharmony_ci					decode_putrootfh_maxsz + \
90762306a36Sopenharmony_ci					decode_secinfo_no_name_maxsz)
90862306a36Sopenharmony_ci#define NFS4_enc_test_stateid_sz	(compound_encode_hdr_maxsz + \
90962306a36Sopenharmony_ci					 encode_sequence_maxsz + \
91062306a36Sopenharmony_ci					 encode_test_stateid_maxsz)
91162306a36Sopenharmony_ci#define NFS4_dec_test_stateid_sz	(compound_decode_hdr_maxsz + \
91262306a36Sopenharmony_ci					 decode_sequence_maxsz + \
91362306a36Sopenharmony_ci					 decode_test_stateid_maxsz)
91462306a36Sopenharmony_ci#define NFS4_enc_free_stateid_sz	(compound_encode_hdr_maxsz + \
91562306a36Sopenharmony_ci					 encode_sequence_maxsz + \
91662306a36Sopenharmony_ci					 encode_free_stateid_maxsz)
91762306a36Sopenharmony_ci#define NFS4_dec_free_stateid_sz	(compound_decode_hdr_maxsz + \
91862306a36Sopenharmony_ci					 decode_sequence_maxsz + \
91962306a36Sopenharmony_ci					 decode_free_stateid_maxsz)
92062306a36Sopenharmony_ci
92162306a36Sopenharmony_ciconst u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
92262306a36Sopenharmony_ci				      compound_encode_hdr_maxsz +
92362306a36Sopenharmony_ci				      encode_sequence_maxsz +
92462306a36Sopenharmony_ci				      encode_putfh_maxsz +
92562306a36Sopenharmony_ci				      encode_getattr_maxsz) *
92662306a36Sopenharmony_ci				     XDR_UNIT);
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ciconst u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
92962306a36Sopenharmony_ci				     compound_decode_hdr_maxsz +
93062306a36Sopenharmony_ci				     decode_sequence_maxsz +
93162306a36Sopenharmony_ci				     decode_putfh_maxsz) *
93262306a36Sopenharmony_ci				    XDR_UNIT);
93362306a36Sopenharmony_ci
93462306a36Sopenharmony_ciconst u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH +
93562306a36Sopenharmony_ci					   compound_decode_hdr_maxsz +
93662306a36Sopenharmony_ci					   decode_sequence_maxsz) *
93762306a36Sopenharmony_ci					  XDR_UNIT);
93862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead);
93962306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
94062306a36Sopenharmony_ci
94162306a36Sopenharmony_cistatic const umode_t nfs_type2fmt[] = {
94262306a36Sopenharmony_ci	[NF4BAD] = 0,
94362306a36Sopenharmony_ci	[NF4REG] = S_IFREG,
94462306a36Sopenharmony_ci	[NF4DIR] = S_IFDIR,
94562306a36Sopenharmony_ci	[NF4BLK] = S_IFBLK,
94662306a36Sopenharmony_ci	[NF4CHR] = S_IFCHR,
94762306a36Sopenharmony_ci	[NF4LNK] = S_IFLNK,
94862306a36Sopenharmony_ci	[NF4SOCK] = S_IFSOCK,
94962306a36Sopenharmony_ci	[NF4FIFO] = S_IFIFO,
95062306a36Sopenharmony_ci	[NF4ATTRDIR] = 0,
95162306a36Sopenharmony_ci	[NF4NAMEDATTR] = 0,
95262306a36Sopenharmony_ci};
95362306a36Sopenharmony_ci
95462306a36Sopenharmony_cistruct compound_hdr {
95562306a36Sopenharmony_ci	int32_t		status;
95662306a36Sopenharmony_ci	uint32_t	nops;
95762306a36Sopenharmony_ci	__be32 *	nops_p;
95862306a36Sopenharmony_ci	uint32_t	taglen;
95962306a36Sopenharmony_ci	char *		tag;
96062306a36Sopenharmony_ci	uint32_t	replen;		/* expected reply words */
96162306a36Sopenharmony_ci	u32		minorversion;
96262306a36Sopenharmony_ci};
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_cistatic __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
96562306a36Sopenharmony_ci{
96662306a36Sopenharmony_ci	__be32 *p = xdr_reserve_space(xdr, nbytes);
96762306a36Sopenharmony_ci	BUG_ON(!p);
96862306a36Sopenharmony_ci	return p;
96962306a36Sopenharmony_ci}
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_cistatic void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
97262306a36Sopenharmony_ci{
97362306a36Sopenharmony_ci	WARN_ON_ONCE(xdr_stream_encode_opaque_fixed(xdr, buf, len) < 0);
97462306a36Sopenharmony_ci}
97562306a36Sopenharmony_ci
97662306a36Sopenharmony_cistatic void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
97762306a36Sopenharmony_ci{
97862306a36Sopenharmony_ci	WARN_ON_ONCE(xdr_stream_encode_opaque(xdr, str, len) < 0);
97962306a36Sopenharmony_ci}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_cistatic void encode_uint32(struct xdr_stream *xdr, u32 n)
98262306a36Sopenharmony_ci{
98362306a36Sopenharmony_ci	WARN_ON_ONCE(xdr_stream_encode_u32(xdr, n) < 0);
98462306a36Sopenharmony_ci}
98562306a36Sopenharmony_ci
98662306a36Sopenharmony_cistatic void encode_uint64(struct xdr_stream *xdr, u64 n)
98762306a36Sopenharmony_ci{
98862306a36Sopenharmony_ci	WARN_ON_ONCE(xdr_stream_encode_u64(xdr, n) < 0);
98962306a36Sopenharmony_ci}
99062306a36Sopenharmony_ci
99162306a36Sopenharmony_cistatic ssize_t xdr_encode_bitmap4(struct xdr_stream *xdr,
99262306a36Sopenharmony_ci		const __u32 *bitmap, size_t len)
99362306a36Sopenharmony_ci{
99462306a36Sopenharmony_ci	ssize_t ret;
99562306a36Sopenharmony_ci
99662306a36Sopenharmony_ci	/* Trim empty words */
99762306a36Sopenharmony_ci	while (len > 0 && bitmap[len-1] == 0)
99862306a36Sopenharmony_ci		len--;
99962306a36Sopenharmony_ci	ret = xdr_stream_encode_uint32_array(xdr, bitmap, len);
100062306a36Sopenharmony_ci	if (WARN_ON_ONCE(ret < 0))
100162306a36Sopenharmony_ci		return ret;
100262306a36Sopenharmony_ci	return len;
100362306a36Sopenharmony_ci}
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_cistatic size_t mask_bitmap4(const __u32 *bitmap, const __u32 *mask,
100662306a36Sopenharmony_ci		__u32 *res, size_t len)
100762306a36Sopenharmony_ci{
100862306a36Sopenharmony_ci	size_t i;
100962306a36Sopenharmony_ci	__u32 tmp;
101062306a36Sopenharmony_ci
101162306a36Sopenharmony_ci	while (len > 0 && (bitmap[len-1] == 0 || mask[len-1] == 0))
101262306a36Sopenharmony_ci		len--;
101362306a36Sopenharmony_ci	for (i = len; i-- > 0;) {
101462306a36Sopenharmony_ci		tmp = bitmap[i] & mask[i];
101562306a36Sopenharmony_ci		res[i] = tmp;
101662306a36Sopenharmony_ci	}
101762306a36Sopenharmony_ci	return len;
101862306a36Sopenharmony_ci}
101962306a36Sopenharmony_ci
102062306a36Sopenharmony_cistatic void encode_nfs4_seqid(struct xdr_stream *xdr,
102162306a36Sopenharmony_ci		const struct nfs_seqid *seqid)
102262306a36Sopenharmony_ci{
102362306a36Sopenharmony_ci	if (seqid != NULL)
102462306a36Sopenharmony_ci		encode_uint32(xdr, seqid->sequence->counter);
102562306a36Sopenharmony_ci	else
102662306a36Sopenharmony_ci		encode_uint32(xdr, 0);
102762306a36Sopenharmony_ci}
102862306a36Sopenharmony_ci
102962306a36Sopenharmony_cistatic void encode_compound_hdr(struct xdr_stream *xdr,
103062306a36Sopenharmony_ci				struct rpc_rqst *req,
103162306a36Sopenharmony_ci				struct compound_hdr *hdr)
103262306a36Sopenharmony_ci{
103362306a36Sopenharmony_ci	__be32 *p;
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	/* initialize running count of expected bytes in reply.
103662306a36Sopenharmony_ci	 * NOTE: the replied tag SHOULD be the same is the one sent,
103762306a36Sopenharmony_ci	 * but this is not required as a MUST for the server to do so. */
103862306a36Sopenharmony_ci	hdr->replen = 3 + hdr->taglen;
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
104162306a36Sopenharmony_ci	encode_string(xdr, hdr->taglen, hdr->tag);
104262306a36Sopenharmony_ci	p = reserve_space(xdr, 8);
104362306a36Sopenharmony_ci	*p++ = cpu_to_be32(hdr->minorversion);
104462306a36Sopenharmony_ci	hdr->nops_p = p;
104562306a36Sopenharmony_ci	*p = cpu_to_be32(hdr->nops);
104662306a36Sopenharmony_ci}
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_cistatic void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op,
104962306a36Sopenharmony_ci		uint32_t replen,
105062306a36Sopenharmony_ci		struct compound_hdr *hdr)
105162306a36Sopenharmony_ci{
105262306a36Sopenharmony_ci	encode_uint32(xdr, op);
105362306a36Sopenharmony_ci	hdr->nops++;
105462306a36Sopenharmony_ci	hdr->replen += replen;
105562306a36Sopenharmony_ci}
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_cistatic void encode_nops(struct compound_hdr *hdr)
105862306a36Sopenharmony_ci{
105962306a36Sopenharmony_ci	WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
106062306a36Sopenharmony_ci	*hdr->nops_p = htonl(hdr->nops);
106162306a36Sopenharmony_ci}
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_cistatic void encode_nfs4_stateid(struct xdr_stream *xdr, const nfs4_stateid *stateid)
106462306a36Sopenharmony_ci{
106562306a36Sopenharmony_ci	encode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
106662306a36Sopenharmony_ci}
106762306a36Sopenharmony_ci
106862306a36Sopenharmony_cistatic void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
106962306a36Sopenharmony_ci{
107062306a36Sopenharmony_ci	encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE);
107162306a36Sopenharmony_ci}
107262306a36Sopenharmony_ci
107362306a36Sopenharmony_cistatic __be32 *
107462306a36Sopenharmony_cixdr_encode_nfstime4(__be32 *p, const struct timespec64 *t)
107562306a36Sopenharmony_ci{
107662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, t->tv_sec);
107762306a36Sopenharmony_ci	*p++ = cpu_to_be32(t->tv_nsec);
107862306a36Sopenharmony_ci	return p;
107962306a36Sopenharmony_ci}
108062306a36Sopenharmony_ci
108162306a36Sopenharmony_cistatic void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
108262306a36Sopenharmony_ci				const struct nfs4_label *label,
108362306a36Sopenharmony_ci				const umode_t *umask,
108462306a36Sopenharmony_ci				const struct nfs_server *server,
108562306a36Sopenharmony_ci				const uint32_t attrmask[])
108662306a36Sopenharmony_ci{
108762306a36Sopenharmony_ci	char owner_name[IDMAP_NAMESZ];
108862306a36Sopenharmony_ci	char owner_group[IDMAP_NAMESZ];
108962306a36Sopenharmony_ci	int owner_namelen = 0;
109062306a36Sopenharmony_ci	int owner_grouplen = 0;
109162306a36Sopenharmony_ci	__be32 *p;
109262306a36Sopenharmony_ci	uint32_t len = 0;
109362306a36Sopenharmony_ci	uint32_t bmval[3] = { 0 };
109462306a36Sopenharmony_ci
109562306a36Sopenharmony_ci	/*
109662306a36Sopenharmony_ci	 * We reserve enough space to write the entire attribute buffer at once.
109762306a36Sopenharmony_ci	 */
109862306a36Sopenharmony_ci	if ((iap->ia_valid & ATTR_SIZE) && (attrmask[0] & FATTR4_WORD0_SIZE)) {
109962306a36Sopenharmony_ci		bmval[0] |= FATTR4_WORD0_SIZE;
110062306a36Sopenharmony_ci		len += 8;
110162306a36Sopenharmony_ci	}
110262306a36Sopenharmony_ci	if (iap->ia_valid & ATTR_MODE) {
110362306a36Sopenharmony_ci		if (umask && (attrmask[2] & FATTR4_WORD2_MODE_UMASK)) {
110462306a36Sopenharmony_ci			bmval[2] |= FATTR4_WORD2_MODE_UMASK;
110562306a36Sopenharmony_ci			len += 8;
110662306a36Sopenharmony_ci		} else if (attrmask[1] & FATTR4_WORD1_MODE) {
110762306a36Sopenharmony_ci			bmval[1] |= FATTR4_WORD1_MODE;
110862306a36Sopenharmony_ci			len += 4;
110962306a36Sopenharmony_ci		}
111062306a36Sopenharmony_ci	}
111162306a36Sopenharmony_ci	if ((iap->ia_valid & ATTR_UID) && (attrmask[1] & FATTR4_WORD1_OWNER)) {
111262306a36Sopenharmony_ci		owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
111362306a36Sopenharmony_ci		if (owner_namelen < 0) {
111462306a36Sopenharmony_ci			dprintk("nfs: couldn't resolve uid %d to string\n",
111562306a36Sopenharmony_ci					from_kuid(&init_user_ns, iap->ia_uid));
111662306a36Sopenharmony_ci			/* XXX */
111762306a36Sopenharmony_ci			strcpy(owner_name, "nobody");
111862306a36Sopenharmony_ci			owner_namelen = sizeof("nobody") - 1;
111962306a36Sopenharmony_ci			/* goto out; */
112062306a36Sopenharmony_ci		}
112162306a36Sopenharmony_ci		bmval[1] |= FATTR4_WORD1_OWNER;
112262306a36Sopenharmony_ci		len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
112362306a36Sopenharmony_ci	}
112462306a36Sopenharmony_ci	if ((iap->ia_valid & ATTR_GID) &&
112562306a36Sopenharmony_ci	   (attrmask[1] & FATTR4_WORD1_OWNER_GROUP)) {
112662306a36Sopenharmony_ci		owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
112762306a36Sopenharmony_ci		if (owner_grouplen < 0) {
112862306a36Sopenharmony_ci			dprintk("nfs: couldn't resolve gid %d to string\n",
112962306a36Sopenharmony_ci					from_kgid(&init_user_ns, iap->ia_gid));
113062306a36Sopenharmony_ci			strcpy(owner_group, "nobody");
113162306a36Sopenharmony_ci			owner_grouplen = sizeof("nobody") - 1;
113262306a36Sopenharmony_ci			/* goto out; */
113362306a36Sopenharmony_ci		}
113462306a36Sopenharmony_ci		bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
113562306a36Sopenharmony_ci		len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
113662306a36Sopenharmony_ci	}
113762306a36Sopenharmony_ci	if (attrmask[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
113862306a36Sopenharmony_ci		if (iap->ia_valid & ATTR_ATIME_SET) {
113962306a36Sopenharmony_ci			bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
114062306a36Sopenharmony_ci			len += 4 + (nfstime4_maxsz << 2);
114162306a36Sopenharmony_ci		} else if (iap->ia_valid & ATTR_ATIME) {
114262306a36Sopenharmony_ci			bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
114362306a36Sopenharmony_ci			len += 4;
114462306a36Sopenharmony_ci		}
114562306a36Sopenharmony_ci	}
114662306a36Sopenharmony_ci	if (attrmask[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
114762306a36Sopenharmony_ci		if (iap->ia_valid & ATTR_MTIME_SET) {
114862306a36Sopenharmony_ci			bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
114962306a36Sopenharmony_ci			len += 4 + (nfstime4_maxsz << 2);
115062306a36Sopenharmony_ci		} else if (iap->ia_valid & ATTR_MTIME) {
115162306a36Sopenharmony_ci			bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
115262306a36Sopenharmony_ci			len += 4;
115362306a36Sopenharmony_ci		}
115462306a36Sopenharmony_ci	}
115562306a36Sopenharmony_ci
115662306a36Sopenharmony_ci	if (label && (attrmask[2] & FATTR4_WORD2_SECURITY_LABEL)) {
115762306a36Sopenharmony_ci		len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
115862306a36Sopenharmony_ci		bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
115962306a36Sopenharmony_ci	}
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	xdr_encode_bitmap4(xdr, bmval, ARRAY_SIZE(bmval));
116262306a36Sopenharmony_ci	xdr_stream_encode_opaque_inline(xdr, (void **)&p, len);
116362306a36Sopenharmony_ci
116462306a36Sopenharmony_ci	if (bmval[0] & FATTR4_WORD0_SIZE)
116562306a36Sopenharmony_ci		p = xdr_encode_hyper(p, iap->ia_size);
116662306a36Sopenharmony_ci	if (bmval[1] & FATTR4_WORD1_MODE)
116762306a36Sopenharmony_ci		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
116862306a36Sopenharmony_ci	if (bmval[1] & FATTR4_WORD1_OWNER)
116962306a36Sopenharmony_ci		p = xdr_encode_opaque(p, owner_name, owner_namelen);
117062306a36Sopenharmony_ci	if (bmval[1] & FATTR4_WORD1_OWNER_GROUP)
117162306a36Sopenharmony_ci		p = xdr_encode_opaque(p, owner_group, owner_grouplen);
117262306a36Sopenharmony_ci	if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
117362306a36Sopenharmony_ci		if (iap->ia_valid & ATTR_ATIME_SET) {
117462306a36Sopenharmony_ci			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
117562306a36Sopenharmony_ci			p = xdr_encode_nfstime4(p, &iap->ia_atime);
117662306a36Sopenharmony_ci		} else
117762306a36Sopenharmony_ci			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
117862306a36Sopenharmony_ci	}
117962306a36Sopenharmony_ci	if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
118062306a36Sopenharmony_ci		if (iap->ia_valid & ATTR_MTIME_SET) {
118162306a36Sopenharmony_ci			*p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
118262306a36Sopenharmony_ci			p = xdr_encode_nfstime4(p, &iap->ia_mtime);
118362306a36Sopenharmony_ci		} else
118462306a36Sopenharmony_ci			*p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
118562306a36Sopenharmony_ci	}
118662306a36Sopenharmony_ci	if (label && (bmval[2] & FATTR4_WORD2_SECURITY_LABEL)) {
118762306a36Sopenharmony_ci		*p++ = cpu_to_be32(label->lfs);
118862306a36Sopenharmony_ci		*p++ = cpu_to_be32(label->pi);
118962306a36Sopenharmony_ci		*p++ = cpu_to_be32(label->len);
119062306a36Sopenharmony_ci		p = xdr_encode_opaque_fixed(p, label->label, label->len);
119162306a36Sopenharmony_ci	}
119262306a36Sopenharmony_ci	if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
119362306a36Sopenharmony_ci		*p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
119462306a36Sopenharmony_ci		*p++ = cpu_to_be32(*umask);
119562306a36Sopenharmony_ci	}
119662306a36Sopenharmony_ci
119762306a36Sopenharmony_ci/* out: */
119862306a36Sopenharmony_ci}
119962306a36Sopenharmony_ci
120062306a36Sopenharmony_cistatic void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
120162306a36Sopenharmony_ci{
120262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr);
120362306a36Sopenharmony_ci	encode_uint32(xdr, access);
120462306a36Sopenharmony_ci}
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_cistatic void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
120762306a36Sopenharmony_ci{
120862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr);
120962306a36Sopenharmony_ci	encode_nfs4_seqid(xdr, arg->seqid);
121062306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &arg->stateid);
121162306a36Sopenharmony_ci}
121262306a36Sopenharmony_ci
121362306a36Sopenharmony_cistatic void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
121462306a36Sopenharmony_ci{
121562306a36Sopenharmony_ci	__be32 *p;
121662306a36Sopenharmony_ci
121762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
121862306a36Sopenharmony_ci	p = reserve_space(xdr, 12);
121962306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->offset);
122062306a36Sopenharmony_ci	*p = cpu_to_be32(args->count);
122162306a36Sopenharmony_ci}
122262306a36Sopenharmony_ci
122362306a36Sopenharmony_cistatic void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
122462306a36Sopenharmony_ci{
122562306a36Sopenharmony_ci	__be32 *p;
122662306a36Sopenharmony_ci
122762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr);
122862306a36Sopenharmony_ci	encode_uint32(xdr, create->ftype);
122962306a36Sopenharmony_ci
123062306a36Sopenharmony_ci	switch (create->ftype) {
123162306a36Sopenharmony_ci	case NF4LNK:
123262306a36Sopenharmony_ci		p = reserve_space(xdr, 4);
123362306a36Sopenharmony_ci		*p = cpu_to_be32(create->u.symlink.len);
123462306a36Sopenharmony_ci		xdr_write_pages(xdr, create->u.symlink.pages, 0,
123562306a36Sopenharmony_ci				create->u.symlink.len);
123662306a36Sopenharmony_ci		xdr->buf->flags |= XDRBUF_WRITE;
123762306a36Sopenharmony_ci		break;
123862306a36Sopenharmony_ci
123962306a36Sopenharmony_ci	case NF4BLK: case NF4CHR:
124062306a36Sopenharmony_ci		p = reserve_space(xdr, 8);
124162306a36Sopenharmony_ci		*p++ = cpu_to_be32(create->u.device.specdata1);
124262306a36Sopenharmony_ci		*p = cpu_to_be32(create->u.device.specdata2);
124362306a36Sopenharmony_ci		break;
124462306a36Sopenharmony_ci
124562306a36Sopenharmony_ci	default:
124662306a36Sopenharmony_ci		break;
124762306a36Sopenharmony_ci	}
124862306a36Sopenharmony_ci
124962306a36Sopenharmony_ci	encode_string(xdr, create->name->len, create->name->name);
125062306a36Sopenharmony_ci	encode_attrs(xdr, create->attrs, create->label, &create->umask,
125162306a36Sopenharmony_ci			create->server, create->server->attr_bitmask);
125262306a36Sopenharmony_ci}
125362306a36Sopenharmony_ci
125462306a36Sopenharmony_cistatic void encode_getattr(struct xdr_stream *xdr,
125562306a36Sopenharmony_ci		const __u32 *bitmap, const __u32 *mask, size_t len,
125662306a36Sopenharmony_ci		struct compound_hdr *hdr)
125762306a36Sopenharmony_ci{
125862306a36Sopenharmony_ci	__u32 masked_bitmap[nfs4_fattr_bitmap_maxsz];
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
126162306a36Sopenharmony_ci	if (mask) {
126262306a36Sopenharmony_ci		if (WARN_ON_ONCE(len > ARRAY_SIZE(masked_bitmap)))
126362306a36Sopenharmony_ci			len = ARRAY_SIZE(masked_bitmap);
126462306a36Sopenharmony_ci		len = mask_bitmap4(bitmap, mask, masked_bitmap, len);
126562306a36Sopenharmony_ci		bitmap = masked_bitmap;
126662306a36Sopenharmony_ci	}
126762306a36Sopenharmony_ci	xdr_encode_bitmap4(xdr, bitmap, len);
126862306a36Sopenharmony_ci}
126962306a36Sopenharmony_ci
127062306a36Sopenharmony_cistatic void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
127162306a36Sopenharmony_ci{
127262306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_fattr_bitmap, bitmask,
127362306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_fattr_bitmap), hdr);
127462306a36Sopenharmony_ci}
127562306a36Sopenharmony_ci
127662306a36Sopenharmony_cistatic void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
127762306a36Sopenharmony_ci				 const u32 *open_bitmap,
127862306a36Sopenharmony_ci				 struct compound_hdr *hdr)
127962306a36Sopenharmony_ci{
128062306a36Sopenharmony_ci	encode_getattr(xdr, open_bitmap, bitmask, 3, hdr);
128162306a36Sopenharmony_ci}
128262306a36Sopenharmony_ci
128362306a36Sopenharmony_cistatic void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
128462306a36Sopenharmony_ci{
128562306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_fsinfo_bitmap, bitmask,
128662306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_fsinfo_bitmap), hdr);
128762306a36Sopenharmony_ci}
128862306a36Sopenharmony_ci
128962306a36Sopenharmony_cistatic void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
129062306a36Sopenharmony_ci{
129162306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_fs_locations_bitmap, bitmask,
129262306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_fs_locations_bitmap), hdr);
129362306a36Sopenharmony_ci}
129462306a36Sopenharmony_ci
129562306a36Sopenharmony_cistatic void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
129662306a36Sopenharmony_ci{
129762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr);
129862306a36Sopenharmony_ci}
129962306a36Sopenharmony_ci
130062306a36Sopenharmony_cistatic void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
130162306a36Sopenharmony_ci{
130262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr);
130362306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
130462306a36Sopenharmony_ci}
130562306a36Sopenharmony_ci
130662306a36Sopenharmony_cistatic inline int nfs4_lock_type(struct file_lock *fl, int block)
130762306a36Sopenharmony_ci{
130862306a36Sopenharmony_ci	if (fl->fl_type == F_RDLCK)
130962306a36Sopenharmony_ci		return block ? NFS4_READW_LT : NFS4_READ_LT;
131062306a36Sopenharmony_ci	return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
131162306a36Sopenharmony_ci}
131262306a36Sopenharmony_ci
131362306a36Sopenharmony_cistatic inline uint64_t nfs4_lock_length(struct file_lock *fl)
131462306a36Sopenharmony_ci{
131562306a36Sopenharmony_ci	if (fl->fl_end == OFFSET_MAX)
131662306a36Sopenharmony_ci		return ~(uint64_t)0;
131762306a36Sopenharmony_ci	return fl->fl_end - fl->fl_start + 1;
131862306a36Sopenharmony_ci}
131962306a36Sopenharmony_ci
132062306a36Sopenharmony_cistatic void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
132162306a36Sopenharmony_ci{
132262306a36Sopenharmony_ci	__be32 *p;
132362306a36Sopenharmony_ci
132462306a36Sopenharmony_ci	p = reserve_space(xdr, 32);
132562306a36Sopenharmony_ci	p = xdr_encode_hyper(p, lowner->clientid);
132662306a36Sopenharmony_ci	*p++ = cpu_to_be32(20);
132762306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, "lock id:", 8);
132862306a36Sopenharmony_ci	*p++ = cpu_to_be32(lowner->s_dev);
132962306a36Sopenharmony_ci	xdr_encode_hyper(p, lowner->id);
133062306a36Sopenharmony_ci}
133162306a36Sopenharmony_ci
133262306a36Sopenharmony_ci/*
133362306a36Sopenharmony_ci * opcode,type,reclaim,offset,length,new_lock_owner = 32
133462306a36Sopenharmony_ci * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
133562306a36Sopenharmony_ci */
133662306a36Sopenharmony_cistatic void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
133762306a36Sopenharmony_ci{
133862306a36Sopenharmony_ci	__be32 *p;
133962306a36Sopenharmony_ci
134062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr);
134162306a36Sopenharmony_ci	p = reserve_space(xdr, 28);
134262306a36Sopenharmony_ci	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
134362306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->reclaim);
134462306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->fl->fl_start);
134562306a36Sopenharmony_ci	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
134662306a36Sopenharmony_ci	*p = cpu_to_be32(args->new_lock_owner);
134762306a36Sopenharmony_ci	if (args->new_lock_owner){
134862306a36Sopenharmony_ci		encode_nfs4_seqid(xdr, args->open_seqid);
134962306a36Sopenharmony_ci		encode_nfs4_stateid(xdr, &args->open_stateid);
135062306a36Sopenharmony_ci		encode_nfs4_seqid(xdr, args->lock_seqid);
135162306a36Sopenharmony_ci		encode_lockowner(xdr, &args->lock_owner);
135262306a36Sopenharmony_ci	}
135362306a36Sopenharmony_ci	else {
135462306a36Sopenharmony_ci		encode_nfs4_stateid(xdr, &args->lock_stateid);
135562306a36Sopenharmony_ci		encode_nfs4_seqid(xdr, args->lock_seqid);
135662306a36Sopenharmony_ci	}
135762306a36Sopenharmony_ci}
135862306a36Sopenharmony_ci
135962306a36Sopenharmony_cistatic void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
136062306a36Sopenharmony_ci{
136162306a36Sopenharmony_ci	__be32 *p;
136262306a36Sopenharmony_ci
136362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr);
136462306a36Sopenharmony_ci	p = reserve_space(xdr, 20);
136562306a36Sopenharmony_ci	*p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
136662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->fl->fl_start);
136762306a36Sopenharmony_ci	p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
136862306a36Sopenharmony_ci	encode_lockowner(xdr, &args->lock_owner);
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_cistatic void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
137262306a36Sopenharmony_ci{
137362306a36Sopenharmony_ci	__be32 *p;
137462306a36Sopenharmony_ci
137562306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr);
137662306a36Sopenharmony_ci	encode_uint32(xdr, nfs4_lock_type(args->fl, 0));
137762306a36Sopenharmony_ci	encode_nfs4_seqid(xdr, args->seqid);
137862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
137962306a36Sopenharmony_ci	p = reserve_space(xdr, 16);
138062306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->fl->fl_start);
138162306a36Sopenharmony_ci	xdr_encode_hyper(p, nfs4_lock_length(args->fl));
138262306a36Sopenharmony_ci}
138362306a36Sopenharmony_ci
138462306a36Sopenharmony_cistatic void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
138562306a36Sopenharmony_ci{
138662306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr);
138762306a36Sopenharmony_ci	encode_lockowner(xdr, lowner);
138862306a36Sopenharmony_ci}
138962306a36Sopenharmony_ci
139062306a36Sopenharmony_cistatic void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
139162306a36Sopenharmony_ci{
139262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr);
139362306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_cistatic void encode_lookupp(struct xdr_stream *xdr, struct compound_hdr *hdr)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LOOKUPP, decode_lookupp_maxsz, hdr);
139962306a36Sopenharmony_ci}
140062306a36Sopenharmony_ci
140162306a36Sopenharmony_cistatic void encode_share_access(struct xdr_stream *xdr, u32 share_access)
140262306a36Sopenharmony_ci{
140362306a36Sopenharmony_ci	__be32 *p;
140462306a36Sopenharmony_ci
140562306a36Sopenharmony_ci	p = reserve_space(xdr, 8);
140662306a36Sopenharmony_ci	*p++ = cpu_to_be32(share_access);
140762306a36Sopenharmony_ci	*p = cpu_to_be32(0);		/* for linux, share_deny = 0 always */
140862306a36Sopenharmony_ci}
140962306a36Sopenharmony_ci
141062306a36Sopenharmony_cistatic inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
141162306a36Sopenharmony_ci{
141262306a36Sopenharmony_ci	__be32 *p;
141362306a36Sopenharmony_ci /*
141462306a36Sopenharmony_ci * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
141562306a36Sopenharmony_ci * owner 4 = 32
141662306a36Sopenharmony_ci */
141762306a36Sopenharmony_ci	encode_nfs4_seqid(xdr, arg->seqid);
141862306a36Sopenharmony_ci	encode_share_access(xdr, arg->share_access);
141962306a36Sopenharmony_ci	p = reserve_space(xdr, 36);
142062306a36Sopenharmony_ci	p = xdr_encode_hyper(p, arg->clientid);
142162306a36Sopenharmony_ci	*p++ = cpu_to_be32(24);
142262306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, "open id:", 8);
142362306a36Sopenharmony_ci	*p++ = cpu_to_be32(arg->server->s_dev);
142462306a36Sopenharmony_ci	*p++ = cpu_to_be32(arg->id.uniquifier);
142562306a36Sopenharmony_ci	xdr_encode_hyper(p, arg->id.create_time);
142662306a36Sopenharmony_ci}
142762306a36Sopenharmony_ci
142862306a36Sopenharmony_cistatic inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
142962306a36Sopenharmony_ci{
143062306a36Sopenharmony_ci	__be32 *p;
143162306a36Sopenharmony_ci
143262306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
143362306a36Sopenharmony_ci	switch(arg->createmode) {
143462306a36Sopenharmony_ci	case NFS4_CREATE_UNCHECKED:
143562306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
143662306a36Sopenharmony_ci		encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
143762306a36Sopenharmony_ci				arg->server, arg->server->attr_bitmask);
143862306a36Sopenharmony_ci		break;
143962306a36Sopenharmony_ci	case NFS4_CREATE_GUARDED:
144062306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_CREATE_GUARDED);
144162306a36Sopenharmony_ci		encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
144262306a36Sopenharmony_ci				arg->server, arg->server->attr_bitmask);
144362306a36Sopenharmony_ci		break;
144462306a36Sopenharmony_ci	case NFS4_CREATE_EXCLUSIVE:
144562306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
144662306a36Sopenharmony_ci		encode_nfs4_verifier(xdr, &arg->u.verifier);
144762306a36Sopenharmony_ci		break;
144862306a36Sopenharmony_ci	case NFS4_CREATE_EXCLUSIVE4_1:
144962306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
145062306a36Sopenharmony_ci		encode_nfs4_verifier(xdr, &arg->u.verifier);
145162306a36Sopenharmony_ci		encode_attrs(xdr, arg->u.attrs, arg->label, &arg->umask,
145262306a36Sopenharmony_ci				arg->server, arg->server->exclcreat_bitmask);
145362306a36Sopenharmony_ci	}
145462306a36Sopenharmony_ci}
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_cistatic void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
145762306a36Sopenharmony_ci{
145862306a36Sopenharmony_ci	__be32 *p;
145962306a36Sopenharmony_ci
146062306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
146162306a36Sopenharmony_ci	switch (arg->open_flags & O_CREAT) {
146262306a36Sopenharmony_ci	case 0:
146362306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_OPEN_NOCREATE);
146462306a36Sopenharmony_ci		break;
146562306a36Sopenharmony_ci	default:
146662306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_OPEN_CREATE);
146762306a36Sopenharmony_ci		encode_createmode(xdr, arg);
146862306a36Sopenharmony_ci	}
146962306a36Sopenharmony_ci}
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_cistatic inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
147262306a36Sopenharmony_ci{
147362306a36Sopenharmony_ci	__be32 *p;
147462306a36Sopenharmony_ci
147562306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
147662306a36Sopenharmony_ci	switch (delegation_type) {
147762306a36Sopenharmony_ci	case 0:
147862306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
147962306a36Sopenharmony_ci		break;
148062306a36Sopenharmony_ci	case FMODE_READ:
148162306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
148262306a36Sopenharmony_ci		break;
148362306a36Sopenharmony_ci	case FMODE_WRITE|FMODE_READ:
148462306a36Sopenharmony_ci		*p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
148562306a36Sopenharmony_ci		break;
148662306a36Sopenharmony_ci	default:
148762306a36Sopenharmony_ci		BUG();
148862306a36Sopenharmony_ci	}
148962306a36Sopenharmony_ci}
149062306a36Sopenharmony_ci
149162306a36Sopenharmony_cistatic inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
149262306a36Sopenharmony_ci{
149362306a36Sopenharmony_ci	__be32 *p;
149462306a36Sopenharmony_ci
149562306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
149662306a36Sopenharmony_ci	*p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
149762306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
149862306a36Sopenharmony_ci}
149962306a36Sopenharmony_ci
150062306a36Sopenharmony_cistatic inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
150162306a36Sopenharmony_ci{
150262306a36Sopenharmony_ci	__be32 *p;
150362306a36Sopenharmony_ci
150462306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
150562306a36Sopenharmony_ci	*p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
150662306a36Sopenharmony_ci	encode_delegation_type(xdr, type);
150762306a36Sopenharmony_ci}
150862306a36Sopenharmony_ci
150962306a36Sopenharmony_cistatic inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
151062306a36Sopenharmony_ci{
151162306a36Sopenharmony_ci	__be32 *p;
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
151462306a36Sopenharmony_ci	*p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
151562306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, stateid);
151662306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
151762306a36Sopenharmony_ci}
151862306a36Sopenharmony_ci
151962306a36Sopenharmony_cistatic inline void encode_claim_fh(struct xdr_stream *xdr)
152062306a36Sopenharmony_ci{
152162306a36Sopenharmony_ci	__be32 *p;
152262306a36Sopenharmony_ci
152362306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
152462306a36Sopenharmony_ci	*p = cpu_to_be32(NFS4_OPEN_CLAIM_FH);
152562306a36Sopenharmony_ci}
152662306a36Sopenharmony_ci
152762306a36Sopenharmony_cistatic inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid)
152862306a36Sopenharmony_ci{
152962306a36Sopenharmony_ci	__be32 *p;
153062306a36Sopenharmony_ci
153162306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
153262306a36Sopenharmony_ci	*p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH);
153362306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, stateid);
153462306a36Sopenharmony_ci}
153562306a36Sopenharmony_ci
153662306a36Sopenharmony_cistatic void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
153762306a36Sopenharmony_ci{
153862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr);
153962306a36Sopenharmony_ci	encode_openhdr(xdr, arg);
154062306a36Sopenharmony_ci	encode_opentype(xdr, arg);
154162306a36Sopenharmony_ci	switch (arg->claim) {
154262306a36Sopenharmony_ci	case NFS4_OPEN_CLAIM_NULL:
154362306a36Sopenharmony_ci		encode_claim_null(xdr, arg->name);
154462306a36Sopenharmony_ci		break;
154562306a36Sopenharmony_ci	case NFS4_OPEN_CLAIM_PREVIOUS:
154662306a36Sopenharmony_ci		encode_claim_previous(xdr, arg->u.delegation_type);
154762306a36Sopenharmony_ci		break;
154862306a36Sopenharmony_ci	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
154962306a36Sopenharmony_ci		encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
155062306a36Sopenharmony_ci		break;
155162306a36Sopenharmony_ci	case NFS4_OPEN_CLAIM_FH:
155262306a36Sopenharmony_ci		encode_claim_fh(xdr);
155362306a36Sopenharmony_ci		break;
155462306a36Sopenharmony_ci	case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
155562306a36Sopenharmony_ci		encode_claim_delegate_cur_fh(xdr, &arg->u.delegation);
155662306a36Sopenharmony_ci		break;
155762306a36Sopenharmony_ci	default:
155862306a36Sopenharmony_ci		BUG();
155962306a36Sopenharmony_ci	}
156062306a36Sopenharmony_ci}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_cistatic void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
156362306a36Sopenharmony_ci{
156462306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr);
156562306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, arg->stateid);
156662306a36Sopenharmony_ci	encode_nfs4_seqid(xdr, arg->seqid);
156762306a36Sopenharmony_ci}
156862306a36Sopenharmony_ci
156962306a36Sopenharmony_cistatic void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
157062306a36Sopenharmony_ci{
157162306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
157262306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &arg->stateid);
157362306a36Sopenharmony_ci	encode_nfs4_seqid(xdr, arg->seqid);
157462306a36Sopenharmony_ci	encode_share_access(xdr, arg->share_access);
157562306a36Sopenharmony_ci}
157662306a36Sopenharmony_ci
157762306a36Sopenharmony_cistatic void
157862306a36Sopenharmony_ciencode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
157962306a36Sopenharmony_ci{
158062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr);
158162306a36Sopenharmony_ci	encode_string(xdr, fh->size, fh->data);
158262306a36Sopenharmony_ci}
158362306a36Sopenharmony_ci
158462306a36Sopenharmony_cistatic void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
158562306a36Sopenharmony_ci{
158662306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
158762306a36Sopenharmony_ci}
158862306a36Sopenharmony_ci
158962306a36Sopenharmony_cistatic void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
159062306a36Sopenharmony_ci			struct compound_hdr *hdr)
159162306a36Sopenharmony_ci{
159262306a36Sopenharmony_ci	__be32 *p;
159362306a36Sopenharmony_ci
159462306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
159562306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
159662306a36Sopenharmony_ci
159762306a36Sopenharmony_ci	p = reserve_space(xdr, 12);
159862306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->offset);
159962306a36Sopenharmony_ci	*p = cpu_to_be32(args->count);
160062306a36Sopenharmony_ci}
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_cistatic void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
160362306a36Sopenharmony_ci{
160462306a36Sopenharmony_ci	uint32_t attrs[3] = {
160562306a36Sopenharmony_ci		FATTR4_WORD0_RDATTR_ERROR,
160662306a36Sopenharmony_ci		FATTR4_WORD1_MOUNTED_ON_FILEID,
160762306a36Sopenharmony_ci	};
160862306a36Sopenharmony_ci	uint32_t dircount = readdir->count;
160962306a36Sopenharmony_ci	uint32_t maxcount = readdir->count;
161062306a36Sopenharmony_ci	__be32 *p, verf[2];
161162306a36Sopenharmony_ci	uint32_t attrlen = 0;
161262306a36Sopenharmony_ci	unsigned int i;
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	if (readdir->plus) {
161562306a36Sopenharmony_ci		attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
161662306a36Sopenharmony_ci			FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
161762306a36Sopenharmony_ci		attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
161862306a36Sopenharmony_ci			FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
161962306a36Sopenharmony_ci			FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
162062306a36Sopenharmony_ci			FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
162162306a36Sopenharmony_ci		attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
162262306a36Sopenharmony_ci	}
162362306a36Sopenharmony_ci	/* Use mounted_on_fileid only if the server supports it */
162462306a36Sopenharmony_ci	if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
162562306a36Sopenharmony_ci		attrs[0] |= FATTR4_WORD0_FILEID;
162662306a36Sopenharmony_ci	for (i = 0; i < ARRAY_SIZE(attrs); i++) {
162762306a36Sopenharmony_ci		attrs[i] &= readdir->bitmask[i];
162862306a36Sopenharmony_ci		if (attrs[i] != 0)
162962306a36Sopenharmony_ci			attrlen = i+1;
163062306a36Sopenharmony_ci	}
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
163362306a36Sopenharmony_ci	encode_uint64(xdr, readdir->cookie);
163462306a36Sopenharmony_ci	encode_nfs4_verifier(xdr, &readdir->verifier);
163562306a36Sopenharmony_ci	p = reserve_space(xdr, 12 + (attrlen << 2));
163662306a36Sopenharmony_ci	*p++ = cpu_to_be32(dircount);
163762306a36Sopenharmony_ci	*p++ = cpu_to_be32(maxcount);
163862306a36Sopenharmony_ci	*p++ = cpu_to_be32(attrlen);
163962306a36Sopenharmony_ci	for (i = 0; i < attrlen; i++)
164062306a36Sopenharmony_ci		*p++ = cpu_to_be32(attrs[i]);
164162306a36Sopenharmony_ci	memcpy(verf, readdir->verifier.data, sizeof(verf));
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n",
164462306a36Sopenharmony_ci			__func__,
164562306a36Sopenharmony_ci			(unsigned long long)readdir->cookie,
164662306a36Sopenharmony_ci			verf[0], verf[1],
164762306a36Sopenharmony_ci			attrs[0] & readdir->bitmask[0],
164862306a36Sopenharmony_ci			attrs[1] & readdir->bitmask[1],
164962306a36Sopenharmony_ci			attrs[2] & readdir->bitmask[2]);
165062306a36Sopenharmony_ci}
165162306a36Sopenharmony_ci
165262306a36Sopenharmony_cistatic void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
165362306a36Sopenharmony_ci{
165462306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr);
165562306a36Sopenharmony_ci}
165662306a36Sopenharmony_ci
165762306a36Sopenharmony_cistatic void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
165862306a36Sopenharmony_ci{
165962306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr);
166062306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
166162306a36Sopenharmony_ci}
166262306a36Sopenharmony_ci
166362306a36Sopenharmony_cistatic void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
166462306a36Sopenharmony_ci{
166562306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr);
166662306a36Sopenharmony_ci	encode_string(xdr, oldname->len, oldname->name);
166762306a36Sopenharmony_ci	encode_string(xdr, newname->len, newname->name);
166862306a36Sopenharmony_ci}
166962306a36Sopenharmony_ci
167062306a36Sopenharmony_cistatic void encode_renew(struct xdr_stream *xdr, clientid4 clid,
167162306a36Sopenharmony_ci			 struct compound_hdr *hdr)
167262306a36Sopenharmony_ci{
167362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr);
167462306a36Sopenharmony_ci	encode_uint64(xdr, clid);
167562306a36Sopenharmony_ci}
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_cistatic void
167862306a36Sopenharmony_ciencode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
167962306a36Sopenharmony_ci{
168062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr);
168162306a36Sopenharmony_ci}
168262306a36Sopenharmony_ci
168362306a36Sopenharmony_cistatic void nfs4_acltype_to_bitmap(enum nfs4_acl_type type, __u32 bitmap[2])
168462306a36Sopenharmony_ci{
168562306a36Sopenharmony_ci	switch (type) {
168662306a36Sopenharmony_ci	default:
168762306a36Sopenharmony_ci		bitmap[0] = FATTR4_WORD0_ACL;
168862306a36Sopenharmony_ci		bitmap[1] = 0;
168962306a36Sopenharmony_ci		break;
169062306a36Sopenharmony_ci	case NFS4ACL_DACL:
169162306a36Sopenharmony_ci		bitmap[0] = 0;
169262306a36Sopenharmony_ci		bitmap[1] = FATTR4_WORD1_DACL;
169362306a36Sopenharmony_ci		break;
169462306a36Sopenharmony_ci	case NFS4ACL_SACL:
169562306a36Sopenharmony_ci		bitmap[0] = 0;
169662306a36Sopenharmony_ci		bitmap[1] = FATTR4_WORD1_SACL;
169762306a36Sopenharmony_ci	}
169862306a36Sopenharmony_ci}
169962306a36Sopenharmony_ci
170062306a36Sopenharmony_cistatic void encode_setacl(struct xdr_stream *xdr,
170162306a36Sopenharmony_ci			  const struct nfs_setaclargs *arg,
170262306a36Sopenharmony_ci			  struct compound_hdr *hdr)
170362306a36Sopenharmony_ci{
170462306a36Sopenharmony_ci	__u32 bitmap[2];
170562306a36Sopenharmony_ci
170662306a36Sopenharmony_ci	nfs4_acltype_to_bitmap(arg->acl_type, bitmap);
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr);
170962306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &zero_stateid);
171062306a36Sopenharmony_ci	xdr_encode_bitmap4(xdr, bitmap, ARRAY_SIZE(bitmap));
171162306a36Sopenharmony_ci	encode_uint32(xdr, arg->acl_len);
171262306a36Sopenharmony_ci	xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len);
171362306a36Sopenharmony_ci}
171462306a36Sopenharmony_ci
171562306a36Sopenharmony_cistatic void
171662306a36Sopenharmony_ciencode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
171762306a36Sopenharmony_ci{
171862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr);
171962306a36Sopenharmony_ci}
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_cistatic void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
172262306a36Sopenharmony_ci{
172362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
172462306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &arg->stateid);
172562306a36Sopenharmony_ci	encode_attrs(xdr, arg->iap, arg->label, NULL, server,
172662306a36Sopenharmony_ci			server->attr_bitmask);
172762306a36Sopenharmony_ci}
172862306a36Sopenharmony_ci
172962306a36Sopenharmony_cistatic void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
173062306a36Sopenharmony_ci{
173162306a36Sopenharmony_ci	__be32 *p;
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr);
173462306a36Sopenharmony_ci	encode_nfs4_verifier(xdr, setclientid->sc_verifier);
173562306a36Sopenharmony_ci
173662306a36Sopenharmony_ci	encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id),
173762306a36Sopenharmony_ci			setclientid->sc_clnt->cl_owner_id);
173862306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
173962306a36Sopenharmony_ci	*p = cpu_to_be32(setclientid->sc_prog);
174062306a36Sopenharmony_ci	encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
174162306a36Sopenharmony_ci	encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
174262306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
174362306a36Sopenharmony_ci	*p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident);
174462306a36Sopenharmony_ci}
174562306a36Sopenharmony_ci
174662306a36Sopenharmony_cistatic void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr)
174762306a36Sopenharmony_ci{
174862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM,
174962306a36Sopenharmony_ci			decode_setclientid_confirm_maxsz, hdr);
175062306a36Sopenharmony_ci	encode_uint64(xdr, arg->clientid);
175162306a36Sopenharmony_ci	encode_nfs4_verifier(xdr, &arg->confirm);
175262306a36Sopenharmony_ci}
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_cistatic void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
175562306a36Sopenharmony_ci			 struct compound_hdr *hdr)
175662306a36Sopenharmony_ci{
175762306a36Sopenharmony_ci	__be32 *p;
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
176062306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
176162306a36Sopenharmony_ci
176262306a36Sopenharmony_ci	p = reserve_space(xdr, 16);
176362306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->offset);
176462306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->stable);
176562306a36Sopenharmony_ci	*p = cpu_to_be32(args->count);
176662306a36Sopenharmony_ci
176762306a36Sopenharmony_ci	xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
176862306a36Sopenharmony_ci}
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_cistatic void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
177162306a36Sopenharmony_ci{
177262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr);
177362306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, stateid);
177462306a36Sopenharmony_ci}
177562306a36Sopenharmony_ci
177662306a36Sopenharmony_cistatic void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
177762306a36Sopenharmony_ci{
177862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr);
177962306a36Sopenharmony_ci	encode_string(xdr, name->len, name->name);
178062306a36Sopenharmony_ci}
178162306a36Sopenharmony_ci
178262306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
178362306a36Sopenharmony_ci/* NFSv4.1 operations */
178462306a36Sopenharmony_cistatic void encode_bind_conn_to_session(struct xdr_stream *xdr,
178562306a36Sopenharmony_ci				   const struct nfs41_bind_conn_to_session_args *args,
178662306a36Sopenharmony_ci				   struct compound_hdr *hdr)
178762306a36Sopenharmony_ci{
178862306a36Sopenharmony_ci	__be32 *p;
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
179162306a36Sopenharmony_ci		decode_bind_conn_to_session_maxsz, hdr);
179262306a36Sopenharmony_ci	encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
179362306a36Sopenharmony_ci	p = xdr_reserve_space(xdr, 8);
179462306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->dir);
179562306a36Sopenharmony_ci	*p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
179662306a36Sopenharmony_ci}
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_cistatic void encode_op_map(struct xdr_stream *xdr, const struct nfs4_op_map *op_map)
179962306a36Sopenharmony_ci{
180062306a36Sopenharmony_ci	unsigned int i;
180162306a36Sopenharmony_ci	encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS);
180262306a36Sopenharmony_ci	for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++)
180362306a36Sopenharmony_ci		encode_uint32(xdr, op_map->u.words[i]);
180462306a36Sopenharmony_ci}
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_cistatic void encode_exchange_id(struct xdr_stream *xdr,
180762306a36Sopenharmony_ci			       const struct nfs41_exchange_id_args *args,
180862306a36Sopenharmony_ci			       struct compound_hdr *hdr)
180962306a36Sopenharmony_ci{
181062306a36Sopenharmony_ci	__be32 *p;
181162306a36Sopenharmony_ci	char impl_name[IMPL_NAME_LIMIT];
181262306a36Sopenharmony_ci	int len = 0;
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
181562306a36Sopenharmony_ci	encode_nfs4_verifier(xdr, &args->verifier);
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci	encode_string(xdr, strlen(args->client->cl_owner_id),
181862306a36Sopenharmony_ci			args->client->cl_owner_id);
181962306a36Sopenharmony_ci
182062306a36Sopenharmony_ci	encode_uint32(xdr, args->flags);
182162306a36Sopenharmony_ci	encode_uint32(xdr, args->state_protect.how);
182262306a36Sopenharmony_ci
182362306a36Sopenharmony_ci	switch (args->state_protect.how) {
182462306a36Sopenharmony_ci	case SP4_NONE:
182562306a36Sopenharmony_ci		break;
182662306a36Sopenharmony_ci	case SP4_MACH_CRED:
182762306a36Sopenharmony_ci		encode_op_map(xdr, &args->state_protect.enforce);
182862306a36Sopenharmony_ci		encode_op_map(xdr, &args->state_protect.allow);
182962306a36Sopenharmony_ci		break;
183062306a36Sopenharmony_ci	default:
183162306a36Sopenharmony_ci		WARN_ON_ONCE(1);
183262306a36Sopenharmony_ci		break;
183362306a36Sopenharmony_ci	}
183462306a36Sopenharmony_ci
183562306a36Sopenharmony_ci	if (send_implementation_id &&
183662306a36Sopenharmony_ci	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
183762306a36Sopenharmony_ci	    sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
183862306a36Sopenharmony_ci		<= sizeof(impl_name) + 1)
183962306a36Sopenharmony_ci		len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
184062306a36Sopenharmony_ci			       utsname()->sysname, utsname()->release,
184162306a36Sopenharmony_ci			       utsname()->version, utsname()->machine);
184262306a36Sopenharmony_ci
184362306a36Sopenharmony_ci	if (len > 0) {
184462306a36Sopenharmony_ci		encode_uint32(xdr, 1);	/* implementation id array length=1 */
184562306a36Sopenharmony_ci
184662306a36Sopenharmony_ci		encode_string(xdr,
184762306a36Sopenharmony_ci			sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1,
184862306a36Sopenharmony_ci			CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN);
184962306a36Sopenharmony_ci		encode_string(xdr, len, impl_name);
185062306a36Sopenharmony_ci		/* just send zeros for nii_date - the date is in nii_name */
185162306a36Sopenharmony_ci		p = reserve_space(xdr, 12);
185262306a36Sopenharmony_ci		p = xdr_encode_hyper(p, 0);
185362306a36Sopenharmony_ci		*p = cpu_to_be32(0);
185462306a36Sopenharmony_ci	} else
185562306a36Sopenharmony_ci		encode_uint32(xdr, 0);	/* implementation id array length=0 */
185662306a36Sopenharmony_ci}
185762306a36Sopenharmony_ci
185862306a36Sopenharmony_cistatic void encode_create_session(struct xdr_stream *xdr,
185962306a36Sopenharmony_ci				  const struct nfs41_create_session_args *args,
186062306a36Sopenharmony_ci				  struct compound_hdr *hdr)
186162306a36Sopenharmony_ci{
186262306a36Sopenharmony_ci	__be32 *p;
186362306a36Sopenharmony_ci	struct nfs_client *clp = args->client;
186462306a36Sopenharmony_ci	struct rpc_clnt *clnt = clp->cl_rpcclient;
186562306a36Sopenharmony_ci	struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
186662306a36Sopenharmony_ci	u32 max_resp_sz_cached;
186762306a36Sopenharmony_ci
186862306a36Sopenharmony_ci	/*
186962306a36Sopenharmony_ci	 * Assumes OPEN is the biggest non-idempotent compound.
187062306a36Sopenharmony_ci	 * 2 is the verifier.
187162306a36Sopenharmony_ci	 */
187262306a36Sopenharmony_ci	max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE + 2)
187362306a36Sopenharmony_ci				* XDR_UNIT + RPC_MAX_AUTH_SIZE;
187462306a36Sopenharmony_ci
187562306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
187662306a36Sopenharmony_ci	p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
187762306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->clientid);
187862306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->seqid);			/*Sequence id */
187962306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->flags);			/*flags */
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	/* Fore Channel */
188262306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* header padding size */
188362306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz);	/* max req size */
188462306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->fc_attrs.max_resp_sz);	/* max resp size */
188562306a36Sopenharmony_ci	*p++ = cpu_to_be32(max_resp_sz_cached);		/* Max resp sz cached */
188662306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->fc_attrs.max_ops);	/* max operations */
188762306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->fc_attrs.max_reqs);	/* max requests */
188862306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	/* Back Channel */
189162306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* header padding size */
189262306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz);	/* max req size */
189362306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz);	/* max resp size */
189462306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached);	/* Max resp sz cached */
189562306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->bc_attrs.max_ops);	/* max operations */
189662306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->bc_attrs.max_reqs);	/* max requests */
189762306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* rdmachannel_attrs */
189862306a36Sopenharmony_ci
189962306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->cb_program);		/* cb_program */
190062306a36Sopenharmony_ci	*p++ = cpu_to_be32(1);
190162306a36Sopenharmony_ci	*p++ = cpu_to_be32(RPC_AUTH_UNIX);			/* auth_sys */
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	/* authsys_parms rfc1831 */
190462306a36Sopenharmony_ci	*p++ = cpu_to_be32(ktime_to_ns(nn->boot_time));	/* stamp */
190562306a36Sopenharmony_ci	p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
190662306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* UID */
190762306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);				/* GID */
190862306a36Sopenharmony_ci	*p = cpu_to_be32(0);				/* No more gids */
190962306a36Sopenharmony_ci}
191062306a36Sopenharmony_ci
191162306a36Sopenharmony_cistatic void encode_destroy_session(struct xdr_stream *xdr,
191262306a36Sopenharmony_ci				   const struct nfs4_session *session,
191362306a36Sopenharmony_ci				   struct compound_hdr *hdr)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr);
191662306a36Sopenharmony_ci	encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
191762306a36Sopenharmony_ci}
191862306a36Sopenharmony_ci
191962306a36Sopenharmony_cistatic void encode_destroy_clientid(struct xdr_stream *xdr,
192062306a36Sopenharmony_ci				   uint64_t clientid,
192162306a36Sopenharmony_ci				   struct compound_hdr *hdr)
192262306a36Sopenharmony_ci{
192362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr);
192462306a36Sopenharmony_ci	encode_uint64(xdr, clientid);
192562306a36Sopenharmony_ci}
192662306a36Sopenharmony_ci
192762306a36Sopenharmony_cistatic void encode_reclaim_complete(struct xdr_stream *xdr,
192862306a36Sopenharmony_ci				    const struct nfs41_reclaim_complete_args *args,
192962306a36Sopenharmony_ci				    struct compound_hdr *hdr)
193062306a36Sopenharmony_ci{
193162306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr);
193262306a36Sopenharmony_ci	encode_uint32(xdr, args->one_fs);
193362306a36Sopenharmony_ci}
193462306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
193562306a36Sopenharmony_ci
193662306a36Sopenharmony_cistatic void encode_sequence(struct xdr_stream *xdr,
193762306a36Sopenharmony_ci			    const struct nfs4_sequence_args *args,
193862306a36Sopenharmony_ci			    struct compound_hdr *hdr)
193962306a36Sopenharmony_ci{
194062306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
194162306a36Sopenharmony_ci	struct nfs4_session *session;
194262306a36Sopenharmony_ci	struct nfs4_slot_table *tp;
194362306a36Sopenharmony_ci	struct nfs4_slot *slot = args->sa_slot;
194462306a36Sopenharmony_ci	__be32 *p;
194562306a36Sopenharmony_ci
194662306a36Sopenharmony_ci	tp = slot->table;
194762306a36Sopenharmony_ci	session = tp->session;
194862306a36Sopenharmony_ci	if (!session)
194962306a36Sopenharmony_ci		return;
195062306a36Sopenharmony_ci
195162306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
195262306a36Sopenharmony_ci
195362306a36Sopenharmony_ci	/*
195462306a36Sopenharmony_ci	 * Sessionid + seqid + slotid + max slotid + cache_this
195562306a36Sopenharmony_ci	 */
195662306a36Sopenharmony_ci	dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
195762306a36Sopenharmony_ci		"max_slotid=%d cache_this=%d\n",
195862306a36Sopenharmony_ci		__func__,
195962306a36Sopenharmony_ci		((u32 *)session->sess_id.data)[0],
196062306a36Sopenharmony_ci		((u32 *)session->sess_id.data)[1],
196162306a36Sopenharmony_ci		((u32 *)session->sess_id.data)[2],
196262306a36Sopenharmony_ci		((u32 *)session->sess_id.data)[3],
196362306a36Sopenharmony_ci		slot->seq_nr, slot->slot_nr,
196462306a36Sopenharmony_ci		tp->highest_used_slotid, args->sa_cache_this);
196562306a36Sopenharmony_ci	p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
196662306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
196762306a36Sopenharmony_ci	*p++ = cpu_to_be32(slot->seq_nr);
196862306a36Sopenharmony_ci	*p++ = cpu_to_be32(slot->slot_nr);
196962306a36Sopenharmony_ci	*p++ = cpu_to_be32(tp->highest_used_slotid);
197062306a36Sopenharmony_ci	*p = cpu_to_be32(args->sa_cache_this);
197162306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
197262306a36Sopenharmony_ci}
197362306a36Sopenharmony_ci
197462306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_1
197562306a36Sopenharmony_cistatic void
197662306a36Sopenharmony_ciencode_getdeviceinfo(struct xdr_stream *xdr,
197762306a36Sopenharmony_ci		     const struct nfs4_getdeviceinfo_args *args,
197862306a36Sopenharmony_ci		     struct compound_hdr *hdr)
197962306a36Sopenharmony_ci{
198062306a36Sopenharmony_ci	__be32 *p;
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr);
198362306a36Sopenharmony_ci	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4);
198462306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
198562306a36Sopenharmony_ci				    NFS4_DEVICEID4_SIZE);
198662306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->pdev->layout_type);
198762306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->pdev->maxcount);	/* gdia_maxcount */
198862306a36Sopenharmony_ci
198962306a36Sopenharmony_ci	p = reserve_space(xdr, 4 + 4);
199062306a36Sopenharmony_ci	*p++ = cpu_to_be32(1);			/* bitmap length */
199162306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->notify_types);
199262306a36Sopenharmony_ci}
199362306a36Sopenharmony_ci
199462306a36Sopenharmony_cistatic void
199562306a36Sopenharmony_ciencode_layoutget(struct xdr_stream *xdr,
199662306a36Sopenharmony_ci		      const struct nfs4_layoutget_args *args,
199762306a36Sopenharmony_ci		      struct compound_hdr *hdr)
199862306a36Sopenharmony_ci{
199962306a36Sopenharmony_ci	__be32 *p;
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr);
200262306a36Sopenharmony_ci	p = reserve_space(xdr, 36);
200362306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);     /* Signal layout available */
200462306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->type);
200562306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->range.iomode);
200662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->range.offset);
200762306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->range.length);
200862306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->minlength);
200962306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
201062306a36Sopenharmony_ci	encode_uint32(xdr, args->maxcount);
201162306a36Sopenharmony_ci
201262306a36Sopenharmony_ci	dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
201362306a36Sopenharmony_ci		__func__,
201462306a36Sopenharmony_ci		args->type,
201562306a36Sopenharmony_ci		args->range.iomode,
201662306a36Sopenharmony_ci		(unsigned long)args->range.offset,
201762306a36Sopenharmony_ci		(unsigned long)args->range.length,
201862306a36Sopenharmony_ci		args->maxcount);
201962306a36Sopenharmony_ci}
202062306a36Sopenharmony_ci
202162306a36Sopenharmony_cistatic int
202262306a36Sopenharmony_ciencode_layoutcommit(struct xdr_stream *xdr,
202362306a36Sopenharmony_ci		    struct inode *inode,
202462306a36Sopenharmony_ci		    const struct nfs4_layoutcommit_args *args,
202562306a36Sopenharmony_ci		    struct compound_hdr *hdr)
202662306a36Sopenharmony_ci{
202762306a36Sopenharmony_ci	__be32 *p;
202862306a36Sopenharmony_ci
202962306a36Sopenharmony_ci	dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,
203062306a36Sopenharmony_ci		NFS_SERVER(args->inode)->pnfs_curr_ld->id);
203162306a36Sopenharmony_ci
203262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr);
203362306a36Sopenharmony_ci	p = reserve_space(xdr, 20);
203462306a36Sopenharmony_ci	/* Only whole file layouts */
203562306a36Sopenharmony_ci	p = xdr_encode_hyper(p, 0); /* offset */
203662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->lastbytewritten + 1);	/* length */
203762306a36Sopenharmony_ci	*p = cpu_to_be32(0); /* reclaim */
203862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
203962306a36Sopenharmony_ci	if (args->lastbytewritten != U64_MAX) {
204062306a36Sopenharmony_ci		p = reserve_space(xdr, 20);
204162306a36Sopenharmony_ci		*p++ = cpu_to_be32(1); /* newoffset = TRUE */
204262306a36Sopenharmony_ci		p = xdr_encode_hyper(p, args->lastbytewritten);
204362306a36Sopenharmony_ci	} else {
204462306a36Sopenharmony_ci		p = reserve_space(xdr, 12);
204562306a36Sopenharmony_ci		*p++ = cpu_to_be32(0); /* newoffset = FALSE */
204662306a36Sopenharmony_ci	}
204762306a36Sopenharmony_ci	*p++ = cpu_to_be32(0); /* Never send time_modify_changed */
204862306a36Sopenharmony_ci	*p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
204962306a36Sopenharmony_ci
205062306a36Sopenharmony_ci	encode_uint32(xdr, args->layoutupdate_len);
205162306a36Sopenharmony_ci	if (args->layoutupdate_pages)
205262306a36Sopenharmony_ci		xdr_write_pages(xdr, args->layoutupdate_pages, 0,
205362306a36Sopenharmony_ci				args->layoutupdate_len);
205462306a36Sopenharmony_ci
205562306a36Sopenharmony_ci	return 0;
205662306a36Sopenharmony_ci}
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_cistatic void
205962306a36Sopenharmony_ciencode_layoutreturn(struct xdr_stream *xdr,
206062306a36Sopenharmony_ci		    const struct nfs4_layoutreturn_args *args,
206162306a36Sopenharmony_ci		    struct compound_hdr *hdr)
206262306a36Sopenharmony_ci{
206362306a36Sopenharmony_ci	__be32 *p;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr);
206662306a36Sopenharmony_ci	p = reserve_space(xdr, 16);
206762306a36Sopenharmony_ci	*p++ = cpu_to_be32(0);		/* reclaim. always 0 for now */
206862306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->layout_type);
206962306a36Sopenharmony_ci	*p++ = cpu_to_be32(args->range.iomode);
207062306a36Sopenharmony_ci	*p = cpu_to_be32(RETURN_FILE);
207162306a36Sopenharmony_ci	p = reserve_space(xdr, 16);
207262306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->range.offset);
207362306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->range.length);
207462306a36Sopenharmony_ci	spin_lock(&args->inode->i_lock);
207562306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
207662306a36Sopenharmony_ci	spin_unlock(&args->inode->i_lock);
207762306a36Sopenharmony_ci	if (args->ld_private->ops && args->ld_private->ops->encode)
207862306a36Sopenharmony_ci		args->ld_private->ops->encode(xdr, args, args->ld_private);
207962306a36Sopenharmony_ci	else
208062306a36Sopenharmony_ci		encode_uint32(xdr, 0);
208162306a36Sopenharmony_ci}
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_cistatic int
208462306a36Sopenharmony_ciencode_secinfo_no_name(struct xdr_stream *xdr,
208562306a36Sopenharmony_ci		       const struct nfs41_secinfo_no_name_args *args,
208662306a36Sopenharmony_ci		       struct compound_hdr *hdr)
208762306a36Sopenharmony_ci{
208862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr);
208962306a36Sopenharmony_ci	encode_uint32(xdr, args->style);
209062306a36Sopenharmony_ci	return 0;
209162306a36Sopenharmony_ci}
209262306a36Sopenharmony_ci
209362306a36Sopenharmony_cistatic void encode_test_stateid(struct xdr_stream *xdr,
209462306a36Sopenharmony_ci				const struct nfs41_test_stateid_args *args,
209562306a36Sopenharmony_ci				struct compound_hdr *hdr)
209662306a36Sopenharmony_ci{
209762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr);
209862306a36Sopenharmony_ci	encode_uint32(xdr, 1);
209962306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, args->stateid);
210062306a36Sopenharmony_ci}
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_cistatic void encode_free_stateid(struct xdr_stream *xdr,
210362306a36Sopenharmony_ci				const struct nfs41_free_stateid_args *args,
210462306a36Sopenharmony_ci				struct compound_hdr *hdr)
210562306a36Sopenharmony_ci{
210662306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr);
210762306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
210862306a36Sopenharmony_ci}
210962306a36Sopenharmony_ci#else
211062306a36Sopenharmony_cistatic inline void
211162306a36Sopenharmony_ciencode_layoutreturn(struct xdr_stream *xdr,
211262306a36Sopenharmony_ci		    const struct nfs4_layoutreturn_args *args,
211362306a36Sopenharmony_ci		    struct compound_hdr *hdr)
211462306a36Sopenharmony_ci{
211562306a36Sopenharmony_ci}
211662306a36Sopenharmony_ci
211762306a36Sopenharmony_cistatic void
211862306a36Sopenharmony_ciencode_layoutget(struct xdr_stream *xdr,
211962306a36Sopenharmony_ci		      const struct nfs4_layoutget_args *args,
212062306a36Sopenharmony_ci		      struct compound_hdr *hdr)
212162306a36Sopenharmony_ci{
212262306a36Sopenharmony_ci}
212362306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
212462306a36Sopenharmony_ci
212562306a36Sopenharmony_ci/*
212662306a36Sopenharmony_ci * END OF "GENERIC" ENCODE ROUTINES.
212762306a36Sopenharmony_ci */
212862306a36Sopenharmony_ci
212962306a36Sopenharmony_cistatic u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
213062306a36Sopenharmony_ci{
213162306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
213262306a36Sopenharmony_ci	struct nfs4_session *session = args->sa_slot->table->session;
213362306a36Sopenharmony_ci	if (session)
213462306a36Sopenharmony_ci		return session->clp->cl_mvops->minor_version;
213562306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
213662306a36Sopenharmony_ci	return 0;
213762306a36Sopenharmony_ci}
213862306a36Sopenharmony_ci
213962306a36Sopenharmony_ci/*
214062306a36Sopenharmony_ci * Encode an ACCESS request
214162306a36Sopenharmony_ci */
214262306a36Sopenharmony_cistatic void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr,
214362306a36Sopenharmony_ci				const void *data)
214462306a36Sopenharmony_ci{
214562306a36Sopenharmony_ci	const struct nfs4_accessargs *args = data;
214662306a36Sopenharmony_ci	struct compound_hdr hdr = {
214762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
214862306a36Sopenharmony_ci	};
214962306a36Sopenharmony_ci
215062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
215162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
215262306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
215362306a36Sopenharmony_ci	encode_access(xdr, args->access, &hdr);
215462306a36Sopenharmony_ci	if (args->bitmask)
215562306a36Sopenharmony_ci		encode_getfattr(xdr, args->bitmask, &hdr);
215662306a36Sopenharmony_ci	encode_nops(&hdr);
215762306a36Sopenharmony_ci}
215862306a36Sopenharmony_ci
215962306a36Sopenharmony_ci/*
216062306a36Sopenharmony_ci * Encode LOOKUP request
216162306a36Sopenharmony_ci */
216262306a36Sopenharmony_cistatic void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
216362306a36Sopenharmony_ci				const void *data)
216462306a36Sopenharmony_ci{
216562306a36Sopenharmony_ci	const struct nfs4_lookup_arg *args = data;
216662306a36Sopenharmony_ci	struct compound_hdr hdr = {
216762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
216862306a36Sopenharmony_ci	};
216962306a36Sopenharmony_ci
217062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
217162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
217262306a36Sopenharmony_ci	encode_putfh(xdr, args->dir_fh, &hdr);
217362306a36Sopenharmony_ci	encode_lookup(xdr, args->name, &hdr);
217462306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
217562306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
217662306a36Sopenharmony_ci	encode_nops(&hdr);
217762306a36Sopenharmony_ci}
217862306a36Sopenharmony_ci
217962306a36Sopenharmony_ci/*
218062306a36Sopenharmony_ci * Encode LOOKUPP request
218162306a36Sopenharmony_ci */
218262306a36Sopenharmony_cistatic void nfs4_xdr_enc_lookupp(struct rpc_rqst *req, struct xdr_stream *xdr,
218362306a36Sopenharmony_ci		const void *data)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	const struct nfs4_lookupp_arg *args = data;
218662306a36Sopenharmony_ci	struct compound_hdr hdr = {
218762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
218862306a36Sopenharmony_ci	};
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
219162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
219262306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
219362306a36Sopenharmony_ci	encode_lookupp(xdr, &hdr);
219462306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
219562306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
219662306a36Sopenharmony_ci	encode_nops(&hdr);
219762306a36Sopenharmony_ci}
219862306a36Sopenharmony_ci
219962306a36Sopenharmony_ci/*
220062306a36Sopenharmony_ci * Encode LOOKUP_ROOT request
220162306a36Sopenharmony_ci */
220262306a36Sopenharmony_cistatic void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req,
220362306a36Sopenharmony_ci				     struct xdr_stream *xdr,
220462306a36Sopenharmony_ci				     const void *data)
220562306a36Sopenharmony_ci{
220662306a36Sopenharmony_ci	const struct nfs4_lookup_root_arg *args = data;
220762306a36Sopenharmony_ci	struct compound_hdr hdr = {
220862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
220962306a36Sopenharmony_ci	};
221062306a36Sopenharmony_ci
221162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
221262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
221362306a36Sopenharmony_ci	encode_putrootfh(xdr, &hdr);
221462306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
221562306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
221662306a36Sopenharmony_ci	encode_nops(&hdr);
221762306a36Sopenharmony_ci}
221862306a36Sopenharmony_ci
221962306a36Sopenharmony_ci/*
222062306a36Sopenharmony_ci * Encode REMOVE request
222162306a36Sopenharmony_ci */
222262306a36Sopenharmony_cistatic void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr,
222362306a36Sopenharmony_ci				const void *data)
222462306a36Sopenharmony_ci{
222562306a36Sopenharmony_ci	const struct nfs_removeargs *args = data;
222662306a36Sopenharmony_ci	struct compound_hdr hdr = {
222762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
222862306a36Sopenharmony_ci	};
222962306a36Sopenharmony_ci
223062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
223162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
223262306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
223362306a36Sopenharmony_ci	encode_remove(xdr, &args->name, &hdr);
223462306a36Sopenharmony_ci	encode_nops(&hdr);
223562306a36Sopenharmony_ci}
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci/*
223862306a36Sopenharmony_ci * Encode RENAME request
223962306a36Sopenharmony_ci */
224062306a36Sopenharmony_cistatic void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr,
224162306a36Sopenharmony_ci				const void *data)
224262306a36Sopenharmony_ci{
224362306a36Sopenharmony_ci	const struct nfs_renameargs *args = data;
224462306a36Sopenharmony_ci	struct compound_hdr hdr = {
224562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
224662306a36Sopenharmony_ci	};
224762306a36Sopenharmony_ci
224862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
224962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
225062306a36Sopenharmony_ci	encode_putfh(xdr, args->old_dir, &hdr);
225162306a36Sopenharmony_ci	encode_savefh(xdr, &hdr);
225262306a36Sopenharmony_ci	encode_putfh(xdr, args->new_dir, &hdr);
225362306a36Sopenharmony_ci	encode_rename(xdr, args->old_name, args->new_name, &hdr);
225462306a36Sopenharmony_ci	encode_nops(&hdr);
225562306a36Sopenharmony_ci}
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci/*
225862306a36Sopenharmony_ci * Encode LINK request
225962306a36Sopenharmony_ci */
226062306a36Sopenharmony_cistatic void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr,
226162306a36Sopenharmony_ci			      const void *data)
226262306a36Sopenharmony_ci{
226362306a36Sopenharmony_ci	const struct nfs4_link_arg *args = data;
226462306a36Sopenharmony_ci	struct compound_hdr hdr = {
226562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
226662306a36Sopenharmony_ci	};
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
226962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
227062306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
227162306a36Sopenharmony_ci	encode_savefh(xdr, &hdr);
227262306a36Sopenharmony_ci	encode_putfh(xdr, args->dir_fh, &hdr);
227362306a36Sopenharmony_ci	encode_link(xdr, args->name, &hdr);
227462306a36Sopenharmony_ci	encode_restorefh(xdr, &hdr);
227562306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
227662306a36Sopenharmony_ci	encode_nops(&hdr);
227762306a36Sopenharmony_ci}
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci/*
228062306a36Sopenharmony_ci * Encode CREATE request
228162306a36Sopenharmony_ci */
228262306a36Sopenharmony_cistatic void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
228362306a36Sopenharmony_ci				const void *data)
228462306a36Sopenharmony_ci{
228562306a36Sopenharmony_ci	const struct nfs4_create_arg *args = data;
228662306a36Sopenharmony_ci	struct compound_hdr hdr = {
228762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
228862306a36Sopenharmony_ci	};
228962306a36Sopenharmony_ci
229062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
229162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
229262306a36Sopenharmony_ci	encode_putfh(xdr, args->dir_fh, &hdr);
229362306a36Sopenharmony_ci	encode_create(xdr, args, &hdr);
229462306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
229562306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
229662306a36Sopenharmony_ci	encode_nops(&hdr);
229762306a36Sopenharmony_ci}
229862306a36Sopenharmony_ci
229962306a36Sopenharmony_ci/*
230062306a36Sopenharmony_ci * Encode SYMLINK request
230162306a36Sopenharmony_ci */
230262306a36Sopenharmony_cistatic void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr,
230362306a36Sopenharmony_ci				 const void *data)
230462306a36Sopenharmony_ci{
230562306a36Sopenharmony_ci	const struct nfs4_create_arg *args = data;
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	nfs4_xdr_enc_create(req, xdr, args);
230862306a36Sopenharmony_ci}
230962306a36Sopenharmony_ci
231062306a36Sopenharmony_ci/*
231162306a36Sopenharmony_ci * Encode GETATTR request
231262306a36Sopenharmony_ci */
231362306a36Sopenharmony_cistatic void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr,
231462306a36Sopenharmony_ci				 const void *data)
231562306a36Sopenharmony_ci{
231662306a36Sopenharmony_ci	const struct nfs4_getattr_arg *args = data;
231762306a36Sopenharmony_ci	struct compound_hdr hdr = {
231862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
231962306a36Sopenharmony_ci	};
232062306a36Sopenharmony_ci
232162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
232262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
232362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
232462306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
232562306a36Sopenharmony_ci	encode_nops(&hdr);
232662306a36Sopenharmony_ci}
232762306a36Sopenharmony_ci
232862306a36Sopenharmony_ci/*
232962306a36Sopenharmony_ci * Encode a CLOSE request
233062306a36Sopenharmony_ci */
233162306a36Sopenharmony_cistatic void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr,
233262306a36Sopenharmony_ci			       const void *data)
233362306a36Sopenharmony_ci{
233462306a36Sopenharmony_ci	const struct nfs_closeargs *args = data;
233562306a36Sopenharmony_ci	struct compound_hdr hdr = {
233662306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
233762306a36Sopenharmony_ci	};
233862306a36Sopenharmony_ci
233962306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
234062306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
234162306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
234262306a36Sopenharmony_ci	if (args->lr_args)
234362306a36Sopenharmony_ci		encode_layoutreturn(xdr, args->lr_args, &hdr);
234462306a36Sopenharmony_ci	if (args->bitmask != NULL)
234562306a36Sopenharmony_ci		encode_getfattr(xdr, args->bitmask, &hdr);
234662306a36Sopenharmony_ci	encode_close(xdr, args, &hdr);
234762306a36Sopenharmony_ci	encode_nops(&hdr);
234862306a36Sopenharmony_ci}
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci/*
235162306a36Sopenharmony_ci * Encode an OPEN request
235262306a36Sopenharmony_ci */
235362306a36Sopenharmony_cistatic void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
235462306a36Sopenharmony_ci			      const void *data)
235562306a36Sopenharmony_ci{
235662306a36Sopenharmony_ci	const struct nfs_openargs *args = data;
235762306a36Sopenharmony_ci	struct compound_hdr hdr = {
235862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
235962306a36Sopenharmony_ci	};
236062306a36Sopenharmony_ci
236162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
236262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
236362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
236462306a36Sopenharmony_ci	encode_open(xdr, args, &hdr);
236562306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
236662306a36Sopenharmony_ci	if (args->access)
236762306a36Sopenharmony_ci		encode_access(xdr, args->access, &hdr);
236862306a36Sopenharmony_ci	encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
236962306a36Sopenharmony_ci	if (args->lg_args) {
237062306a36Sopenharmony_ci		encode_layoutget(xdr, args->lg_args, &hdr);
237162306a36Sopenharmony_ci		rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
237262306a36Sopenharmony_ci					args->lg_args->layout.pglen,
237362306a36Sopenharmony_ci					hdr.replen - pagepad_maxsz);
237462306a36Sopenharmony_ci	}
237562306a36Sopenharmony_ci	encode_nops(&hdr);
237662306a36Sopenharmony_ci}
237762306a36Sopenharmony_ci
237862306a36Sopenharmony_ci/*
237962306a36Sopenharmony_ci * Encode an OPEN_CONFIRM request
238062306a36Sopenharmony_ci */
238162306a36Sopenharmony_cistatic void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req,
238262306a36Sopenharmony_ci				      struct xdr_stream *xdr,
238362306a36Sopenharmony_ci				      const void *data)
238462306a36Sopenharmony_ci{
238562306a36Sopenharmony_ci	const struct nfs_open_confirmargs *args = data;
238662306a36Sopenharmony_ci	struct compound_hdr hdr = {
238762306a36Sopenharmony_ci		.nops   = 0,
238862306a36Sopenharmony_ci	};
238962306a36Sopenharmony_ci
239062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
239162306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
239262306a36Sopenharmony_ci	encode_open_confirm(xdr, args, &hdr);
239362306a36Sopenharmony_ci	encode_nops(&hdr);
239462306a36Sopenharmony_ci}
239562306a36Sopenharmony_ci
239662306a36Sopenharmony_ci/*
239762306a36Sopenharmony_ci * Encode an OPEN request with no attributes.
239862306a36Sopenharmony_ci */
239962306a36Sopenharmony_cistatic void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
240062306a36Sopenharmony_ci				     struct xdr_stream *xdr,
240162306a36Sopenharmony_ci				     const void *data)
240262306a36Sopenharmony_ci{
240362306a36Sopenharmony_ci	const struct nfs_openargs *args = data;
240462306a36Sopenharmony_ci	struct compound_hdr hdr = {
240562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
240662306a36Sopenharmony_ci	};
240762306a36Sopenharmony_ci
240862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
240962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
241062306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
241162306a36Sopenharmony_ci	encode_open(xdr, args, &hdr);
241262306a36Sopenharmony_ci	if (args->access)
241362306a36Sopenharmony_ci		encode_access(xdr, args->access, &hdr);
241462306a36Sopenharmony_ci	encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
241562306a36Sopenharmony_ci	if (args->lg_args) {
241662306a36Sopenharmony_ci		encode_layoutget(xdr, args->lg_args, &hdr);
241762306a36Sopenharmony_ci		rpc_prepare_reply_pages(req, args->lg_args->layout.pages, 0,
241862306a36Sopenharmony_ci					args->lg_args->layout.pglen,
241962306a36Sopenharmony_ci					hdr.replen - pagepad_maxsz);
242062306a36Sopenharmony_ci	}
242162306a36Sopenharmony_ci	encode_nops(&hdr);
242262306a36Sopenharmony_ci}
242362306a36Sopenharmony_ci
242462306a36Sopenharmony_ci/*
242562306a36Sopenharmony_ci * Encode an OPEN_DOWNGRADE request
242662306a36Sopenharmony_ci */
242762306a36Sopenharmony_cistatic void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req,
242862306a36Sopenharmony_ci					struct xdr_stream *xdr,
242962306a36Sopenharmony_ci					const void *data)
243062306a36Sopenharmony_ci{
243162306a36Sopenharmony_ci	const struct nfs_closeargs *args = data;
243262306a36Sopenharmony_ci	struct compound_hdr hdr = {
243362306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
243462306a36Sopenharmony_ci	};
243562306a36Sopenharmony_ci
243662306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
243762306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
243862306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
243962306a36Sopenharmony_ci	if (args->lr_args)
244062306a36Sopenharmony_ci		encode_layoutreturn(xdr, args->lr_args, &hdr);
244162306a36Sopenharmony_ci	encode_open_downgrade(xdr, args, &hdr);
244262306a36Sopenharmony_ci	encode_nops(&hdr);
244362306a36Sopenharmony_ci}
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci/*
244662306a36Sopenharmony_ci * Encode a LOCK request
244762306a36Sopenharmony_ci */
244862306a36Sopenharmony_cistatic void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr,
244962306a36Sopenharmony_ci			      const void *data)
245062306a36Sopenharmony_ci{
245162306a36Sopenharmony_ci	const struct nfs_lock_args *args = data;
245262306a36Sopenharmony_ci	struct compound_hdr hdr = {
245362306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
245462306a36Sopenharmony_ci	};
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
245762306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
245862306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
245962306a36Sopenharmony_ci	encode_lock(xdr, args, &hdr);
246062306a36Sopenharmony_ci	encode_nops(&hdr);
246162306a36Sopenharmony_ci}
246262306a36Sopenharmony_ci
246362306a36Sopenharmony_ci/*
246462306a36Sopenharmony_ci * Encode a LOCKT request
246562306a36Sopenharmony_ci */
246662306a36Sopenharmony_cistatic void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr,
246762306a36Sopenharmony_ci			       const void *data)
246862306a36Sopenharmony_ci{
246962306a36Sopenharmony_ci	const struct nfs_lockt_args *args = data;
247062306a36Sopenharmony_ci	struct compound_hdr hdr = {
247162306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
247262306a36Sopenharmony_ci	};
247362306a36Sopenharmony_ci
247462306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
247562306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
247662306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
247762306a36Sopenharmony_ci	encode_lockt(xdr, args, &hdr);
247862306a36Sopenharmony_ci	encode_nops(&hdr);
247962306a36Sopenharmony_ci}
248062306a36Sopenharmony_ci
248162306a36Sopenharmony_ci/*
248262306a36Sopenharmony_ci * Encode a LOCKU request
248362306a36Sopenharmony_ci */
248462306a36Sopenharmony_cistatic void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr,
248562306a36Sopenharmony_ci			       const void *data)
248662306a36Sopenharmony_ci{
248762306a36Sopenharmony_ci	const struct nfs_locku_args *args = data;
248862306a36Sopenharmony_ci	struct compound_hdr hdr = {
248962306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
249062306a36Sopenharmony_ci	};
249162306a36Sopenharmony_ci
249262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
249362306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
249462306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
249562306a36Sopenharmony_ci	encode_locku(xdr, args, &hdr);
249662306a36Sopenharmony_ci	encode_nops(&hdr);
249762306a36Sopenharmony_ci}
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_cistatic void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req,
250062306a36Sopenharmony_ci					   struct xdr_stream *xdr,
250162306a36Sopenharmony_ci					   const void *data)
250262306a36Sopenharmony_ci{
250362306a36Sopenharmony_ci	const struct nfs_release_lockowner_args *args = data;
250462306a36Sopenharmony_ci	struct compound_hdr hdr = {
250562306a36Sopenharmony_ci		.minorversion = 0,
250662306a36Sopenharmony_ci	};
250762306a36Sopenharmony_ci
250862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
250962306a36Sopenharmony_ci	encode_release_lockowner(xdr, &args->lock_owner, &hdr);
251062306a36Sopenharmony_ci	encode_nops(&hdr);
251162306a36Sopenharmony_ci}
251262306a36Sopenharmony_ci
251362306a36Sopenharmony_ci/*
251462306a36Sopenharmony_ci * Encode a READLINK request
251562306a36Sopenharmony_ci */
251662306a36Sopenharmony_cistatic void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr,
251762306a36Sopenharmony_ci				  const void *data)
251862306a36Sopenharmony_ci{
251962306a36Sopenharmony_ci	const struct nfs4_readlink *args = data;
252062306a36Sopenharmony_ci	struct compound_hdr hdr = {
252162306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
252262306a36Sopenharmony_ci	};
252362306a36Sopenharmony_ci
252462306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
252562306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
252662306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
252762306a36Sopenharmony_ci	encode_readlink(xdr, args, req, &hdr);
252862306a36Sopenharmony_ci
252962306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
253062306a36Sopenharmony_ci				args->pglen, hdr.replen - pagepad_maxsz);
253162306a36Sopenharmony_ci	encode_nops(&hdr);
253262306a36Sopenharmony_ci}
253362306a36Sopenharmony_ci
253462306a36Sopenharmony_ci/*
253562306a36Sopenharmony_ci * Encode a READDIR request
253662306a36Sopenharmony_ci */
253762306a36Sopenharmony_cistatic void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr,
253862306a36Sopenharmony_ci				 const void *data)
253962306a36Sopenharmony_ci{
254062306a36Sopenharmony_ci	const struct nfs4_readdir_arg *args = data;
254162306a36Sopenharmony_ci	struct compound_hdr hdr = {
254262306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
254362306a36Sopenharmony_ci	};
254462306a36Sopenharmony_ci
254562306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
254662306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
254762306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
254862306a36Sopenharmony_ci	encode_readdir(xdr, args, req, &hdr);
254962306a36Sopenharmony_ci
255062306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
255162306a36Sopenharmony_ci				args->count, hdr.replen - pagepad_maxsz);
255262306a36Sopenharmony_ci	encode_nops(&hdr);
255362306a36Sopenharmony_ci}
255462306a36Sopenharmony_ci
255562306a36Sopenharmony_ci/*
255662306a36Sopenharmony_ci * Encode a READ request
255762306a36Sopenharmony_ci */
255862306a36Sopenharmony_cistatic void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr,
255962306a36Sopenharmony_ci			      const void *data)
256062306a36Sopenharmony_ci{
256162306a36Sopenharmony_ci	const struct nfs_pgio_args *args = data;
256262306a36Sopenharmony_ci	struct compound_hdr hdr = {
256362306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
256462306a36Sopenharmony_ci	};
256562306a36Sopenharmony_ci
256662306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
256762306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
256862306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
256962306a36Sopenharmony_ci	encode_read(xdr, args, &hdr);
257062306a36Sopenharmony_ci
257162306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->pages, args->pgbase,
257262306a36Sopenharmony_ci				args->count, hdr.replen - pagepad_maxsz);
257362306a36Sopenharmony_ci	req->rq_rcv_buf.flags |= XDRBUF_READ;
257462306a36Sopenharmony_ci	encode_nops(&hdr);
257562306a36Sopenharmony_ci}
257662306a36Sopenharmony_ci
257762306a36Sopenharmony_ci/*
257862306a36Sopenharmony_ci * Encode an SETATTR request
257962306a36Sopenharmony_ci */
258062306a36Sopenharmony_cistatic void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr,
258162306a36Sopenharmony_ci				 const void *data)
258262306a36Sopenharmony_ci{
258362306a36Sopenharmony_ci	const struct nfs_setattrargs *args = data;
258462306a36Sopenharmony_ci	struct compound_hdr hdr = {
258562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
258662306a36Sopenharmony_ci	};
258762306a36Sopenharmony_ci
258862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
258962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
259062306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
259162306a36Sopenharmony_ci	encode_setattr(xdr, args, args->server, &hdr);
259262306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
259362306a36Sopenharmony_ci	encode_nops(&hdr);
259462306a36Sopenharmony_ci}
259562306a36Sopenharmony_ci
259662306a36Sopenharmony_ci/*
259762306a36Sopenharmony_ci * Encode a GETACL request
259862306a36Sopenharmony_ci */
259962306a36Sopenharmony_cistatic void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
260062306a36Sopenharmony_ci				const void *data)
260162306a36Sopenharmony_ci{
260262306a36Sopenharmony_ci	const struct nfs_getaclargs *args = data;
260362306a36Sopenharmony_ci	struct compound_hdr hdr = {
260462306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
260562306a36Sopenharmony_ci	};
260662306a36Sopenharmony_ci	__u32 nfs4_acl_bitmap[2];
260762306a36Sopenharmony_ci	uint32_t replen;
260862306a36Sopenharmony_ci
260962306a36Sopenharmony_ci	nfs4_acltype_to_bitmap(args->acl_type, nfs4_acl_bitmap);
261062306a36Sopenharmony_ci
261162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
261262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
261362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
261462306a36Sopenharmony_ci	replen = hdr.replen + op_decode_hdr_maxsz;
261562306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_acl_bitmap, NULL,
261662306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_acl_bitmap), &hdr);
261762306a36Sopenharmony_ci
261862306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->acl_pages, 0,
261962306a36Sopenharmony_ci				args->acl_len, replen);
262062306a36Sopenharmony_ci	encode_nops(&hdr);
262162306a36Sopenharmony_ci}
262262306a36Sopenharmony_ci
262362306a36Sopenharmony_ci/*
262462306a36Sopenharmony_ci * Encode a WRITE request
262562306a36Sopenharmony_ci */
262662306a36Sopenharmony_cistatic void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
262762306a36Sopenharmony_ci			       const void *data)
262862306a36Sopenharmony_ci{
262962306a36Sopenharmony_ci	const struct nfs_pgio_args *args = data;
263062306a36Sopenharmony_ci	struct compound_hdr hdr = {
263162306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
263262306a36Sopenharmony_ci	};
263362306a36Sopenharmony_ci
263462306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
263562306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
263662306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
263762306a36Sopenharmony_ci	encode_write(xdr, args, &hdr);
263862306a36Sopenharmony_ci	req->rq_snd_buf.flags |= XDRBUF_WRITE;
263962306a36Sopenharmony_ci	if (args->bitmask)
264062306a36Sopenharmony_ci		encode_getfattr(xdr, args->bitmask, &hdr);
264162306a36Sopenharmony_ci	encode_nops(&hdr);
264262306a36Sopenharmony_ci}
264362306a36Sopenharmony_ci
264462306a36Sopenharmony_ci/*
264562306a36Sopenharmony_ci *  a COMMIT request
264662306a36Sopenharmony_ci */
264762306a36Sopenharmony_cistatic void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr,
264862306a36Sopenharmony_ci				const void *data)
264962306a36Sopenharmony_ci{
265062306a36Sopenharmony_ci	const struct nfs_commitargs *args = data;
265162306a36Sopenharmony_ci	struct compound_hdr hdr = {
265262306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
265362306a36Sopenharmony_ci	};
265462306a36Sopenharmony_ci
265562306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
265662306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
265762306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
265862306a36Sopenharmony_ci	encode_commit(xdr, args, &hdr);
265962306a36Sopenharmony_ci	encode_nops(&hdr);
266062306a36Sopenharmony_ci}
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci/*
266362306a36Sopenharmony_ci * FSINFO request
266462306a36Sopenharmony_ci */
266562306a36Sopenharmony_cistatic void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
266662306a36Sopenharmony_ci				const void *data)
266762306a36Sopenharmony_ci{
266862306a36Sopenharmony_ci	const struct nfs4_fsinfo_arg *args = data;
266962306a36Sopenharmony_ci	struct compound_hdr hdr = {
267062306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
267162306a36Sopenharmony_ci	};
267262306a36Sopenharmony_ci
267362306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
267462306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
267562306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
267662306a36Sopenharmony_ci	encode_fsinfo(xdr, args->bitmask, &hdr);
267762306a36Sopenharmony_ci	encode_nops(&hdr);
267862306a36Sopenharmony_ci}
267962306a36Sopenharmony_ci
268062306a36Sopenharmony_ci/*
268162306a36Sopenharmony_ci * a PATHCONF request
268262306a36Sopenharmony_ci */
268362306a36Sopenharmony_cistatic void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
268462306a36Sopenharmony_ci				  const void *data)
268562306a36Sopenharmony_ci{
268662306a36Sopenharmony_ci	const struct nfs4_pathconf_arg *args = data;
268762306a36Sopenharmony_ci	struct compound_hdr hdr = {
268862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
268962306a36Sopenharmony_ci	};
269062306a36Sopenharmony_ci
269162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
269262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
269362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
269462306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_pathconf_bitmap, args->bitmask,
269562306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_pathconf_bitmap), &hdr);
269662306a36Sopenharmony_ci	encode_nops(&hdr);
269762306a36Sopenharmony_ci}
269862306a36Sopenharmony_ci
269962306a36Sopenharmony_ci/*
270062306a36Sopenharmony_ci * a STATFS request
270162306a36Sopenharmony_ci */
270262306a36Sopenharmony_cistatic void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
270362306a36Sopenharmony_ci				const void *data)
270462306a36Sopenharmony_ci{
270562306a36Sopenharmony_ci	const struct nfs4_statfs_arg *args = data;
270662306a36Sopenharmony_ci	struct compound_hdr hdr = {
270762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
270862306a36Sopenharmony_ci	};
270962306a36Sopenharmony_ci
271062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
271162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
271262306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
271362306a36Sopenharmony_ci	encode_getattr(xdr, nfs4_statfs_bitmap, args->bitmask,
271462306a36Sopenharmony_ci			ARRAY_SIZE(nfs4_statfs_bitmap), &hdr);
271562306a36Sopenharmony_ci	encode_nops(&hdr);
271662306a36Sopenharmony_ci}
271762306a36Sopenharmony_ci
271862306a36Sopenharmony_ci/*
271962306a36Sopenharmony_ci * GETATTR_BITMAP request
272062306a36Sopenharmony_ci */
272162306a36Sopenharmony_cistatic void nfs4_xdr_enc_server_caps(struct rpc_rqst *req,
272262306a36Sopenharmony_ci				     struct xdr_stream *xdr,
272362306a36Sopenharmony_ci				     const void *data)
272462306a36Sopenharmony_ci{
272562306a36Sopenharmony_ci	const struct nfs4_server_caps_arg *args = data;
272662306a36Sopenharmony_ci	const u32 *bitmask = args->bitmask;
272762306a36Sopenharmony_ci	struct compound_hdr hdr = {
272862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
272962306a36Sopenharmony_ci	};
273062306a36Sopenharmony_ci
273162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
273262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
273362306a36Sopenharmony_ci	encode_putfh(xdr, args->fhandle, &hdr);
273462306a36Sopenharmony_ci	encode_getattr(xdr, bitmask, NULL, 3, &hdr);
273562306a36Sopenharmony_ci	encode_nops(&hdr);
273662306a36Sopenharmony_ci}
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci/*
273962306a36Sopenharmony_ci * a RENEW request
274062306a36Sopenharmony_ci */
274162306a36Sopenharmony_cistatic void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr,
274262306a36Sopenharmony_ci			       const void *data)
274362306a36Sopenharmony_ci
274462306a36Sopenharmony_ci{
274562306a36Sopenharmony_ci	const struct nfs_client *clp = data;
274662306a36Sopenharmony_ci	struct compound_hdr hdr = {
274762306a36Sopenharmony_ci		.nops	= 0,
274862306a36Sopenharmony_ci	};
274962306a36Sopenharmony_ci
275062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
275162306a36Sopenharmony_ci	encode_renew(xdr, clp->cl_clientid, &hdr);
275262306a36Sopenharmony_ci	encode_nops(&hdr);
275362306a36Sopenharmony_ci}
275462306a36Sopenharmony_ci
275562306a36Sopenharmony_ci/*
275662306a36Sopenharmony_ci * a SETCLIENTID request
275762306a36Sopenharmony_ci */
275862306a36Sopenharmony_cistatic void nfs4_xdr_enc_setclientid(struct rpc_rqst *req,
275962306a36Sopenharmony_ci				     struct xdr_stream *xdr,
276062306a36Sopenharmony_ci				     const void *data)
276162306a36Sopenharmony_ci{
276262306a36Sopenharmony_ci	const struct nfs4_setclientid *sc = data;
276362306a36Sopenharmony_ci	struct compound_hdr hdr = {
276462306a36Sopenharmony_ci		.nops	= 0,
276562306a36Sopenharmony_ci	};
276662306a36Sopenharmony_ci
276762306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
276862306a36Sopenharmony_ci	encode_setclientid(xdr, sc, &hdr);
276962306a36Sopenharmony_ci	encode_nops(&hdr);
277062306a36Sopenharmony_ci}
277162306a36Sopenharmony_ci
277262306a36Sopenharmony_ci/*
277362306a36Sopenharmony_ci * a SETCLIENTID_CONFIRM request
277462306a36Sopenharmony_ci */
277562306a36Sopenharmony_cistatic void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
277662306a36Sopenharmony_ci					     struct xdr_stream *xdr,
277762306a36Sopenharmony_ci					     const void *data)
277862306a36Sopenharmony_ci{
277962306a36Sopenharmony_ci	const struct nfs4_setclientid_res *arg = data;
278062306a36Sopenharmony_ci	struct compound_hdr hdr = {
278162306a36Sopenharmony_ci		.nops	= 0,
278262306a36Sopenharmony_ci	};
278362306a36Sopenharmony_ci
278462306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
278562306a36Sopenharmony_ci	encode_setclientid_confirm(xdr, arg, &hdr);
278662306a36Sopenharmony_ci	encode_nops(&hdr);
278762306a36Sopenharmony_ci}
278862306a36Sopenharmony_ci
278962306a36Sopenharmony_ci/*
279062306a36Sopenharmony_ci * DELEGRETURN request
279162306a36Sopenharmony_ci */
279262306a36Sopenharmony_cistatic void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req,
279362306a36Sopenharmony_ci				     struct xdr_stream *xdr,
279462306a36Sopenharmony_ci				     const void *data)
279562306a36Sopenharmony_ci{
279662306a36Sopenharmony_ci	const struct nfs4_delegreturnargs *args = data;
279762306a36Sopenharmony_ci	struct compound_hdr hdr = {
279862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
279962306a36Sopenharmony_ci	};
280062306a36Sopenharmony_ci
280162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
280262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
280362306a36Sopenharmony_ci	encode_putfh(xdr, args->fhandle, &hdr);
280462306a36Sopenharmony_ci	if (args->lr_args)
280562306a36Sopenharmony_ci		encode_layoutreturn(xdr, args->lr_args, &hdr);
280662306a36Sopenharmony_ci	if (args->bitmask)
280762306a36Sopenharmony_ci		encode_getfattr(xdr, args->bitmask, &hdr);
280862306a36Sopenharmony_ci	encode_delegreturn(xdr, args->stateid, &hdr);
280962306a36Sopenharmony_ci	encode_nops(&hdr);
281062306a36Sopenharmony_ci}
281162306a36Sopenharmony_ci
281262306a36Sopenharmony_ci/*
281362306a36Sopenharmony_ci * Encode FS_LOCATIONS request
281462306a36Sopenharmony_ci */
281562306a36Sopenharmony_cistatic void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
281662306a36Sopenharmony_ci				      struct xdr_stream *xdr,
281762306a36Sopenharmony_ci				      const void *data)
281862306a36Sopenharmony_ci{
281962306a36Sopenharmony_ci	const struct nfs4_fs_locations_arg *args = data;
282062306a36Sopenharmony_ci	struct compound_hdr hdr = {
282162306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
282262306a36Sopenharmony_ci	};
282362306a36Sopenharmony_ci	uint32_t replen;
282462306a36Sopenharmony_ci
282562306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
282662306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
282762306a36Sopenharmony_ci	if (args->migration) {
282862306a36Sopenharmony_ci		encode_putfh(xdr, args->fh, &hdr);
282962306a36Sopenharmony_ci		replen = hdr.replen;
283062306a36Sopenharmony_ci		encode_fs_locations(xdr, args->bitmask, &hdr);
283162306a36Sopenharmony_ci		if (args->renew)
283262306a36Sopenharmony_ci			encode_renew(xdr, args->clientid, &hdr);
283362306a36Sopenharmony_ci	} else {
283462306a36Sopenharmony_ci		encode_putfh(xdr, args->dir_fh, &hdr);
283562306a36Sopenharmony_ci		encode_lookup(xdr, args->name, &hdr);
283662306a36Sopenharmony_ci		replen = hdr.replen;
283762306a36Sopenharmony_ci		encode_fs_locations(xdr, args->bitmask, &hdr);
283862306a36Sopenharmony_ci	}
283962306a36Sopenharmony_ci
284062306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, (struct page **)&args->page, 0,
284162306a36Sopenharmony_ci				PAGE_SIZE, replen);
284262306a36Sopenharmony_ci	encode_nops(&hdr);
284362306a36Sopenharmony_ci}
284462306a36Sopenharmony_ci
284562306a36Sopenharmony_ci/*
284662306a36Sopenharmony_ci * Encode SECINFO request
284762306a36Sopenharmony_ci */
284862306a36Sopenharmony_cistatic void nfs4_xdr_enc_secinfo(struct rpc_rqst *req,
284962306a36Sopenharmony_ci				struct xdr_stream *xdr,
285062306a36Sopenharmony_ci				const void *data)
285162306a36Sopenharmony_ci{
285262306a36Sopenharmony_ci	const struct nfs4_secinfo_arg *args = data;
285362306a36Sopenharmony_ci	struct compound_hdr hdr = {
285462306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
285562306a36Sopenharmony_ci	};
285662306a36Sopenharmony_ci
285762306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
285862306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
285962306a36Sopenharmony_ci	encode_putfh(xdr, args->dir_fh, &hdr);
286062306a36Sopenharmony_ci	encode_secinfo(xdr, args->name, &hdr);
286162306a36Sopenharmony_ci	encode_nops(&hdr);
286262306a36Sopenharmony_ci}
286362306a36Sopenharmony_ci
286462306a36Sopenharmony_ci/*
286562306a36Sopenharmony_ci * Encode FSID_PRESENT request
286662306a36Sopenharmony_ci */
286762306a36Sopenharmony_cistatic void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
286862306a36Sopenharmony_ci				      struct xdr_stream *xdr,
286962306a36Sopenharmony_ci				      const void *data)
287062306a36Sopenharmony_ci{
287162306a36Sopenharmony_ci	const struct nfs4_fsid_present_arg *args = data;
287262306a36Sopenharmony_ci	struct compound_hdr hdr = {
287362306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
287462306a36Sopenharmony_ci	};
287562306a36Sopenharmony_ci
287662306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
287762306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
287862306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
287962306a36Sopenharmony_ci	encode_getfh(xdr, &hdr);
288062306a36Sopenharmony_ci	if (args->renew)
288162306a36Sopenharmony_ci		encode_renew(xdr, args->clientid, &hdr);
288262306a36Sopenharmony_ci	encode_nops(&hdr);
288362306a36Sopenharmony_ci}
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
288662306a36Sopenharmony_ci/*
288762306a36Sopenharmony_ci * BIND_CONN_TO_SESSION request
288862306a36Sopenharmony_ci */
288962306a36Sopenharmony_cistatic void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
289062306a36Sopenharmony_ci				struct xdr_stream *xdr,
289162306a36Sopenharmony_ci				const void *data)
289262306a36Sopenharmony_ci{
289362306a36Sopenharmony_ci	const struct nfs41_bind_conn_to_session_args *args = data;
289462306a36Sopenharmony_ci	struct compound_hdr hdr = {
289562306a36Sopenharmony_ci		.minorversion = args->client->cl_mvops->minor_version,
289662306a36Sopenharmony_ci	};
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
289962306a36Sopenharmony_ci	encode_bind_conn_to_session(xdr, args, &hdr);
290062306a36Sopenharmony_ci	encode_nops(&hdr);
290162306a36Sopenharmony_ci}
290262306a36Sopenharmony_ci
290362306a36Sopenharmony_ci/*
290462306a36Sopenharmony_ci * EXCHANGE_ID request
290562306a36Sopenharmony_ci */
290662306a36Sopenharmony_cistatic void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req,
290762306a36Sopenharmony_ci				     struct xdr_stream *xdr,
290862306a36Sopenharmony_ci				     const void *data)
290962306a36Sopenharmony_ci{
291062306a36Sopenharmony_ci	const struct nfs41_exchange_id_args *args = data;
291162306a36Sopenharmony_ci	struct compound_hdr hdr = {
291262306a36Sopenharmony_ci		.minorversion = args->client->cl_mvops->minor_version,
291362306a36Sopenharmony_ci	};
291462306a36Sopenharmony_ci
291562306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
291662306a36Sopenharmony_ci	encode_exchange_id(xdr, args, &hdr);
291762306a36Sopenharmony_ci	encode_nops(&hdr);
291862306a36Sopenharmony_ci}
291962306a36Sopenharmony_ci
292062306a36Sopenharmony_ci/*
292162306a36Sopenharmony_ci * a CREATE_SESSION request
292262306a36Sopenharmony_ci */
292362306a36Sopenharmony_cistatic void nfs4_xdr_enc_create_session(struct rpc_rqst *req,
292462306a36Sopenharmony_ci					struct xdr_stream *xdr,
292562306a36Sopenharmony_ci					const void *data)
292662306a36Sopenharmony_ci{
292762306a36Sopenharmony_ci	const struct nfs41_create_session_args *args = data;
292862306a36Sopenharmony_ci	struct compound_hdr hdr = {
292962306a36Sopenharmony_ci		.minorversion = args->client->cl_mvops->minor_version,
293062306a36Sopenharmony_ci	};
293162306a36Sopenharmony_ci
293262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
293362306a36Sopenharmony_ci	encode_create_session(xdr, args, &hdr);
293462306a36Sopenharmony_ci	encode_nops(&hdr);
293562306a36Sopenharmony_ci}
293662306a36Sopenharmony_ci
293762306a36Sopenharmony_ci/*
293862306a36Sopenharmony_ci * a DESTROY_SESSION request
293962306a36Sopenharmony_ci */
294062306a36Sopenharmony_cistatic void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req,
294162306a36Sopenharmony_ci					 struct xdr_stream *xdr,
294262306a36Sopenharmony_ci					 const void *data)
294362306a36Sopenharmony_ci{
294462306a36Sopenharmony_ci	const struct nfs4_session *session = data;
294562306a36Sopenharmony_ci	struct compound_hdr hdr = {
294662306a36Sopenharmony_ci		.minorversion = session->clp->cl_mvops->minor_version,
294762306a36Sopenharmony_ci	};
294862306a36Sopenharmony_ci
294962306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
295062306a36Sopenharmony_ci	encode_destroy_session(xdr, session, &hdr);
295162306a36Sopenharmony_ci	encode_nops(&hdr);
295262306a36Sopenharmony_ci}
295362306a36Sopenharmony_ci
295462306a36Sopenharmony_ci/*
295562306a36Sopenharmony_ci * a DESTROY_CLIENTID request
295662306a36Sopenharmony_ci */
295762306a36Sopenharmony_cistatic void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req,
295862306a36Sopenharmony_ci					 struct xdr_stream *xdr,
295962306a36Sopenharmony_ci					 const void *data)
296062306a36Sopenharmony_ci{
296162306a36Sopenharmony_ci	const struct nfs_client *clp = data;
296262306a36Sopenharmony_ci	struct compound_hdr hdr = {
296362306a36Sopenharmony_ci		.minorversion = clp->cl_mvops->minor_version,
296462306a36Sopenharmony_ci	};
296562306a36Sopenharmony_ci
296662306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
296762306a36Sopenharmony_ci	encode_destroy_clientid(xdr, clp->cl_clientid, &hdr);
296862306a36Sopenharmony_ci	encode_nops(&hdr);
296962306a36Sopenharmony_ci}
297062306a36Sopenharmony_ci
297162306a36Sopenharmony_ci/*
297262306a36Sopenharmony_ci * a SEQUENCE request
297362306a36Sopenharmony_ci */
297462306a36Sopenharmony_cistatic void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr,
297562306a36Sopenharmony_ci				  const void *data)
297662306a36Sopenharmony_ci{
297762306a36Sopenharmony_ci	const struct nfs4_sequence_args *args = data;
297862306a36Sopenharmony_ci	struct compound_hdr hdr = {
297962306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(args),
298062306a36Sopenharmony_ci	};
298162306a36Sopenharmony_ci
298262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
298362306a36Sopenharmony_ci	encode_sequence(xdr, args, &hdr);
298462306a36Sopenharmony_ci	encode_nops(&hdr);
298562306a36Sopenharmony_ci}
298662306a36Sopenharmony_ci
298762306a36Sopenharmony_ci#endif
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci/*
299062306a36Sopenharmony_ci * a GET_LEASE_TIME request
299162306a36Sopenharmony_ci */
299262306a36Sopenharmony_cistatic void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req,
299362306a36Sopenharmony_ci					struct xdr_stream *xdr,
299462306a36Sopenharmony_ci					const void *data)
299562306a36Sopenharmony_ci{
299662306a36Sopenharmony_ci	const struct nfs4_get_lease_time_args *args = data;
299762306a36Sopenharmony_ci	struct compound_hdr hdr = {
299862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
299962306a36Sopenharmony_ci	};
300062306a36Sopenharmony_ci	const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
300162306a36Sopenharmony_ci
300262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
300362306a36Sopenharmony_ci	encode_sequence(xdr, &args->la_seq_args, &hdr);
300462306a36Sopenharmony_ci	encode_putrootfh(xdr, &hdr);
300562306a36Sopenharmony_ci	encode_fsinfo(xdr, lease_bitmap, &hdr);
300662306a36Sopenharmony_ci	encode_nops(&hdr);
300762306a36Sopenharmony_ci}
300862306a36Sopenharmony_ci
300962306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_1
301062306a36Sopenharmony_ci
301162306a36Sopenharmony_ci/*
301262306a36Sopenharmony_ci * a RECLAIM_COMPLETE request
301362306a36Sopenharmony_ci */
301462306a36Sopenharmony_cistatic void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req,
301562306a36Sopenharmony_ci					  struct xdr_stream *xdr,
301662306a36Sopenharmony_ci					  const void *data)
301762306a36Sopenharmony_ci{
301862306a36Sopenharmony_ci	const struct nfs41_reclaim_complete_args *args = data;
301962306a36Sopenharmony_ci	struct compound_hdr hdr = {
302062306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args)
302162306a36Sopenharmony_ci	};
302262306a36Sopenharmony_ci
302362306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
302462306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
302562306a36Sopenharmony_ci	encode_reclaim_complete(xdr, args, &hdr);
302662306a36Sopenharmony_ci	encode_nops(&hdr);
302762306a36Sopenharmony_ci}
302862306a36Sopenharmony_ci
302962306a36Sopenharmony_ci/*
303062306a36Sopenharmony_ci * Encode GETDEVICEINFO request
303162306a36Sopenharmony_ci */
303262306a36Sopenharmony_cistatic void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req,
303362306a36Sopenharmony_ci				       struct xdr_stream *xdr,
303462306a36Sopenharmony_ci				       const void *data)
303562306a36Sopenharmony_ci{
303662306a36Sopenharmony_ci	const struct nfs4_getdeviceinfo_args *args = data;
303762306a36Sopenharmony_ci	struct compound_hdr hdr = {
303862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
303962306a36Sopenharmony_ci	};
304062306a36Sopenharmony_ci	uint32_t replen;
304162306a36Sopenharmony_ci
304262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
304362306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
304462306a36Sopenharmony_ci
304562306a36Sopenharmony_ci	replen = hdr.replen + op_decode_hdr_maxsz + 2;
304662306a36Sopenharmony_ci
304762306a36Sopenharmony_ci	encode_getdeviceinfo(xdr, args, &hdr);
304862306a36Sopenharmony_ci
304962306a36Sopenharmony_ci	/* set up reply kvec. device_addr4 opaque data is read into the
305062306a36Sopenharmony_ci	 * pages */
305162306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->pdev->pages, args->pdev->pgbase,
305262306a36Sopenharmony_ci				args->pdev->pglen, replen);
305362306a36Sopenharmony_ci	encode_nops(&hdr);
305462306a36Sopenharmony_ci}
305562306a36Sopenharmony_ci
305662306a36Sopenharmony_ci/*
305762306a36Sopenharmony_ci *  Encode LAYOUTGET request
305862306a36Sopenharmony_ci */
305962306a36Sopenharmony_cistatic void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
306062306a36Sopenharmony_ci				   struct xdr_stream *xdr,
306162306a36Sopenharmony_ci				   const void *data)
306262306a36Sopenharmony_ci{
306362306a36Sopenharmony_ci	const struct nfs4_layoutget_args *args = data;
306462306a36Sopenharmony_ci	struct compound_hdr hdr = {
306562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
306662306a36Sopenharmony_ci	};
306762306a36Sopenharmony_ci
306862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
306962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
307062306a36Sopenharmony_ci	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
307162306a36Sopenharmony_ci	encode_layoutget(xdr, args, &hdr);
307262306a36Sopenharmony_ci
307362306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->layout.pages, 0,
307462306a36Sopenharmony_ci				args->layout.pglen, hdr.replen - pagepad_maxsz);
307562306a36Sopenharmony_ci	encode_nops(&hdr);
307662306a36Sopenharmony_ci}
307762306a36Sopenharmony_ci
307862306a36Sopenharmony_ci/*
307962306a36Sopenharmony_ci *  Encode LAYOUTCOMMIT request
308062306a36Sopenharmony_ci */
308162306a36Sopenharmony_cistatic void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
308262306a36Sopenharmony_ci				      struct xdr_stream *xdr,
308362306a36Sopenharmony_ci				      const void *priv)
308462306a36Sopenharmony_ci{
308562306a36Sopenharmony_ci	const struct nfs4_layoutcommit_args *args = priv;
308662306a36Sopenharmony_ci	struct nfs4_layoutcommit_data *data =
308762306a36Sopenharmony_ci		container_of(args, struct nfs4_layoutcommit_data, args);
308862306a36Sopenharmony_ci	struct compound_hdr hdr = {
308962306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
309062306a36Sopenharmony_ci	};
309162306a36Sopenharmony_ci
309262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
309362306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
309462306a36Sopenharmony_ci	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
309562306a36Sopenharmony_ci	encode_layoutcommit(xdr, data->args.inode, args, &hdr);
309662306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
309762306a36Sopenharmony_ci	encode_nops(&hdr);
309862306a36Sopenharmony_ci}
309962306a36Sopenharmony_ci
310062306a36Sopenharmony_ci/*
310162306a36Sopenharmony_ci * Encode LAYOUTRETURN request
310262306a36Sopenharmony_ci */
310362306a36Sopenharmony_cistatic void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
310462306a36Sopenharmony_ci				      struct xdr_stream *xdr,
310562306a36Sopenharmony_ci				      const void *data)
310662306a36Sopenharmony_ci{
310762306a36Sopenharmony_ci	const struct nfs4_layoutreturn_args *args = data;
310862306a36Sopenharmony_ci	struct compound_hdr hdr = {
310962306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
311062306a36Sopenharmony_ci	};
311162306a36Sopenharmony_ci
311262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
311362306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
311462306a36Sopenharmony_ci	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
311562306a36Sopenharmony_ci	encode_layoutreturn(xdr, args, &hdr);
311662306a36Sopenharmony_ci	encode_nops(&hdr);
311762306a36Sopenharmony_ci}
311862306a36Sopenharmony_ci
311962306a36Sopenharmony_ci/*
312062306a36Sopenharmony_ci * Encode SECINFO_NO_NAME request
312162306a36Sopenharmony_ci */
312262306a36Sopenharmony_cistatic void nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
312362306a36Sopenharmony_ci					struct xdr_stream *xdr,
312462306a36Sopenharmony_ci					const void *data)
312562306a36Sopenharmony_ci{
312662306a36Sopenharmony_ci	const struct nfs41_secinfo_no_name_args *args = data;
312762306a36Sopenharmony_ci	struct compound_hdr hdr = {
312862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
312962306a36Sopenharmony_ci	};
313062306a36Sopenharmony_ci
313162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
313262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
313362306a36Sopenharmony_ci	encode_putrootfh(xdr, &hdr);
313462306a36Sopenharmony_ci	encode_secinfo_no_name(xdr, args, &hdr);
313562306a36Sopenharmony_ci	encode_nops(&hdr);
313662306a36Sopenharmony_ci}
313762306a36Sopenharmony_ci
313862306a36Sopenharmony_ci/*
313962306a36Sopenharmony_ci *  Encode TEST_STATEID request
314062306a36Sopenharmony_ci */
314162306a36Sopenharmony_cistatic void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req,
314262306a36Sopenharmony_ci				      struct xdr_stream *xdr,
314362306a36Sopenharmony_ci				      const void *data)
314462306a36Sopenharmony_ci{
314562306a36Sopenharmony_ci	const struct nfs41_test_stateid_args *args = data;
314662306a36Sopenharmony_ci	struct compound_hdr hdr = {
314762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
314862306a36Sopenharmony_ci	};
314962306a36Sopenharmony_ci
315062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
315162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
315262306a36Sopenharmony_ci	encode_test_stateid(xdr, args, &hdr);
315362306a36Sopenharmony_ci	encode_nops(&hdr);
315462306a36Sopenharmony_ci}
315562306a36Sopenharmony_ci
315662306a36Sopenharmony_ci/*
315762306a36Sopenharmony_ci *  Encode FREE_STATEID request
315862306a36Sopenharmony_ci */
315962306a36Sopenharmony_cistatic void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req,
316062306a36Sopenharmony_ci				     struct xdr_stream *xdr,
316162306a36Sopenharmony_ci				     const void *data)
316262306a36Sopenharmony_ci{
316362306a36Sopenharmony_ci	const struct nfs41_free_stateid_args *args = data;
316462306a36Sopenharmony_ci	struct compound_hdr hdr = {
316562306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
316662306a36Sopenharmony_ci	};
316762306a36Sopenharmony_ci
316862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
316962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
317062306a36Sopenharmony_ci	encode_free_stateid(xdr, args, &hdr);
317162306a36Sopenharmony_ci	encode_nops(&hdr);
317262306a36Sopenharmony_ci}
317362306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
317462306a36Sopenharmony_ci
317562306a36Sopenharmony_cistatic int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
317662306a36Sopenharmony_ci{
317762306a36Sopenharmony_ci	ssize_t ret = xdr_stream_decode_opaque_inline(xdr, (void **)string,
317862306a36Sopenharmony_ci			NFS4_OPAQUE_LIMIT);
317962306a36Sopenharmony_ci	if (unlikely(ret < 0))
318062306a36Sopenharmony_ci		return -EIO;
318162306a36Sopenharmony_ci	*len = ret;
318262306a36Sopenharmony_ci	return 0;
318362306a36Sopenharmony_ci}
318462306a36Sopenharmony_ci
318562306a36Sopenharmony_cistatic int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
318662306a36Sopenharmony_ci{
318762306a36Sopenharmony_ci	ssize_t ret;
318862306a36Sopenharmony_ci	void *ptr;
318962306a36Sopenharmony_ci	u32 tmp;
319062306a36Sopenharmony_ci
319162306a36Sopenharmony_ci	if (xdr_stream_decode_u32(xdr, &tmp) < 0)
319262306a36Sopenharmony_ci		return -EIO;
319362306a36Sopenharmony_ci	hdr->status = tmp;
319462306a36Sopenharmony_ci
319562306a36Sopenharmony_ci	ret = xdr_stream_decode_opaque_inline(xdr, &ptr, NFS4_OPAQUE_LIMIT);
319662306a36Sopenharmony_ci	if (ret < 0)
319762306a36Sopenharmony_ci		return -EIO;
319862306a36Sopenharmony_ci	hdr->taglen = ret;
319962306a36Sopenharmony_ci	hdr->tag = ptr;
320062306a36Sopenharmony_ci
320162306a36Sopenharmony_ci	if (xdr_stream_decode_u32(xdr, &tmp) < 0)
320262306a36Sopenharmony_ci		return -EIO;
320362306a36Sopenharmony_ci	hdr->nops = tmp;
320462306a36Sopenharmony_ci	if (unlikely(hdr->nops < 1))
320562306a36Sopenharmony_ci		return nfs4_stat_to_errno(hdr->status);
320662306a36Sopenharmony_ci	return 0;
320762306a36Sopenharmony_ci}
320862306a36Sopenharmony_ci
320962306a36Sopenharmony_cistatic bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
321062306a36Sopenharmony_ci		int *nfs_retval)
321162306a36Sopenharmony_ci{
321262306a36Sopenharmony_ci	__be32 *p;
321362306a36Sopenharmony_ci	uint32_t opnum;
321462306a36Sopenharmony_ci	int32_t nfserr;
321562306a36Sopenharmony_ci
321662306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
321762306a36Sopenharmony_ci	if (unlikely(!p))
321862306a36Sopenharmony_ci		goto out_overflow;
321962306a36Sopenharmony_ci	opnum = be32_to_cpup(p++);
322062306a36Sopenharmony_ci	if (unlikely(opnum != expected))
322162306a36Sopenharmony_ci		goto out_bad_operation;
322262306a36Sopenharmony_ci	if (unlikely(*p != cpu_to_be32(NFS_OK)))
322362306a36Sopenharmony_ci		goto out_status;
322462306a36Sopenharmony_ci	*nfs_retval = 0;
322562306a36Sopenharmony_ci	return true;
322662306a36Sopenharmony_ciout_status:
322762306a36Sopenharmony_ci	nfserr = be32_to_cpup(p);
322862306a36Sopenharmony_ci	trace_nfs4_xdr_status(xdr, opnum, nfserr);
322962306a36Sopenharmony_ci	*nfs_retval = nfs4_stat_to_errno(nfserr);
323062306a36Sopenharmony_ci	return true;
323162306a36Sopenharmony_ciout_bad_operation:
323262306a36Sopenharmony_ci	trace_nfs4_xdr_bad_operation(xdr, opnum, expected);
323362306a36Sopenharmony_ci	*nfs_retval = -EREMOTEIO;
323462306a36Sopenharmony_ci	return false;
323562306a36Sopenharmony_ciout_overflow:
323662306a36Sopenharmony_ci	*nfs_retval = -EIO;
323762306a36Sopenharmony_ci	return false;
323862306a36Sopenharmony_ci}
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_cistatic int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
324162306a36Sopenharmony_ci{
324262306a36Sopenharmony_ci	int retval;
324362306a36Sopenharmony_ci
324462306a36Sopenharmony_ci	__decode_op_hdr(xdr, expected, &retval);
324562306a36Sopenharmony_ci	return retval;
324662306a36Sopenharmony_ci}
324762306a36Sopenharmony_ci
324862306a36Sopenharmony_ci/* Dummy routine */
324962306a36Sopenharmony_cistatic int decode_ace(struct xdr_stream *xdr, void *ace)
325062306a36Sopenharmony_ci{
325162306a36Sopenharmony_ci	__be32 *p;
325262306a36Sopenharmony_ci	unsigned int strlen;
325362306a36Sopenharmony_ci	char *str;
325462306a36Sopenharmony_ci
325562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 12);
325662306a36Sopenharmony_ci	if (unlikely(!p))
325762306a36Sopenharmony_ci		return -EIO;
325862306a36Sopenharmony_ci	return decode_opaque_inline(xdr, &strlen, &str);
325962306a36Sopenharmony_ci}
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_cistatic ssize_t
326262306a36Sopenharmony_cidecode_bitmap4(struct xdr_stream *xdr, uint32_t *bitmap, size_t sz)
326362306a36Sopenharmony_ci{
326462306a36Sopenharmony_ci	ssize_t ret;
326562306a36Sopenharmony_ci
326662306a36Sopenharmony_ci	ret = xdr_stream_decode_uint32_array(xdr, bitmap, sz);
326762306a36Sopenharmony_ci	if (likely(ret >= 0))
326862306a36Sopenharmony_ci		return ret;
326962306a36Sopenharmony_ci	if (ret != -EMSGSIZE)
327062306a36Sopenharmony_ci		return -EIO;
327162306a36Sopenharmony_ci	return sz;
327262306a36Sopenharmony_ci}
327362306a36Sopenharmony_ci
327462306a36Sopenharmony_cistatic int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
327562306a36Sopenharmony_ci{
327662306a36Sopenharmony_ci	ssize_t ret;
327762306a36Sopenharmony_ci	ret = decode_bitmap4(xdr, bitmap, 3);
327862306a36Sopenharmony_ci	return ret < 0 ? ret : 0;
327962306a36Sopenharmony_ci}
328062306a36Sopenharmony_ci
328162306a36Sopenharmony_cistatic int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep)
328262306a36Sopenharmony_ci{
328362306a36Sopenharmony_ci	__be32 *p;
328462306a36Sopenharmony_ci
328562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
328662306a36Sopenharmony_ci	if (unlikely(!p))
328762306a36Sopenharmony_ci		return -EIO;
328862306a36Sopenharmony_ci	*attrlen = be32_to_cpup(p);
328962306a36Sopenharmony_ci	*savep = xdr_stream_pos(xdr);
329062306a36Sopenharmony_ci	return 0;
329162306a36Sopenharmony_ci}
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_cistatic int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
329462306a36Sopenharmony_ci{
329562306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
329662306a36Sopenharmony_ci		int ret;
329762306a36Sopenharmony_ci		ret = decode_attr_bitmap(xdr, bitmask);
329862306a36Sopenharmony_ci		if (unlikely(ret < 0))
329962306a36Sopenharmony_ci			return ret;
330062306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
330162306a36Sopenharmony_ci	} else
330262306a36Sopenharmony_ci		bitmask[0] = bitmask[1] = bitmask[2] = 0;
330362306a36Sopenharmony_ci	dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
330462306a36Sopenharmony_ci		bitmask[0], bitmask[1], bitmask[2]);
330562306a36Sopenharmony_ci	return 0;
330662306a36Sopenharmony_ci}
330762306a36Sopenharmony_ci
330862306a36Sopenharmony_cistatic int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
330962306a36Sopenharmony_ci{
331062306a36Sopenharmony_ci	__be32 *p;
331162306a36Sopenharmony_ci	int ret = 0;
331262306a36Sopenharmony_ci
331362306a36Sopenharmony_ci	*type = 0;
331462306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
331562306a36Sopenharmony_ci		return -EIO;
331662306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
331762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
331862306a36Sopenharmony_ci		if (unlikely(!p))
331962306a36Sopenharmony_ci			return -EIO;
332062306a36Sopenharmony_ci		*type = be32_to_cpup(p);
332162306a36Sopenharmony_ci		if (*type < NF4REG || *type > NF4NAMEDATTR) {
332262306a36Sopenharmony_ci			dprintk("%s: bad type %d\n", __func__, *type);
332362306a36Sopenharmony_ci			return -EIO;
332462306a36Sopenharmony_ci		}
332562306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_TYPE;
332662306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_TYPE;
332762306a36Sopenharmony_ci	}
332862306a36Sopenharmony_ci	dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
332962306a36Sopenharmony_ci	return ret;
333062306a36Sopenharmony_ci}
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_cistatic int decode_attr_fh_expire_type(struct xdr_stream *xdr,
333362306a36Sopenharmony_ci				      uint32_t *bitmap, uint32_t *type)
333462306a36Sopenharmony_ci{
333562306a36Sopenharmony_ci	__be32 *p;
333662306a36Sopenharmony_ci
333762306a36Sopenharmony_ci	*type = 0;
333862306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FH_EXPIRE_TYPE - 1U)))
333962306a36Sopenharmony_ci		return -EIO;
334062306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) {
334162306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
334262306a36Sopenharmony_ci		if (unlikely(!p))
334362306a36Sopenharmony_ci			return -EIO;
334462306a36Sopenharmony_ci		*type = be32_to_cpup(p);
334562306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE;
334662306a36Sopenharmony_ci	}
334762306a36Sopenharmony_ci	dprintk("%s: expire type=0x%x\n", __func__, *type);
334862306a36Sopenharmony_ci	return 0;
334962306a36Sopenharmony_ci}
335062306a36Sopenharmony_ci
335162306a36Sopenharmony_cistatic int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
335262306a36Sopenharmony_ci{
335362306a36Sopenharmony_ci	__be32 *p;
335462306a36Sopenharmony_ci	int ret = 0;
335562306a36Sopenharmony_ci
335662306a36Sopenharmony_ci	*change = 0;
335762306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
335862306a36Sopenharmony_ci		return -EIO;
335962306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
336062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
336162306a36Sopenharmony_ci		if (unlikely(!p))
336262306a36Sopenharmony_ci			return -EIO;
336362306a36Sopenharmony_ci		xdr_decode_hyper(p, change);
336462306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_CHANGE;
336562306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_CHANGE;
336662306a36Sopenharmony_ci	}
336762306a36Sopenharmony_ci	dprintk("%s: change attribute=%Lu\n", __func__,
336862306a36Sopenharmony_ci			(unsigned long long)*change);
336962306a36Sopenharmony_ci	return ret;
337062306a36Sopenharmony_ci}
337162306a36Sopenharmony_ci
337262306a36Sopenharmony_cistatic int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
337362306a36Sopenharmony_ci{
337462306a36Sopenharmony_ci	__be32 *p;
337562306a36Sopenharmony_ci	int ret = 0;
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci	*size = 0;
337862306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
337962306a36Sopenharmony_ci		return -EIO;
338062306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
338162306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
338262306a36Sopenharmony_ci		if (unlikely(!p))
338362306a36Sopenharmony_ci			return -EIO;
338462306a36Sopenharmony_ci		xdr_decode_hyper(p, size);
338562306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_SIZE;
338662306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_SIZE;
338762306a36Sopenharmony_ci	}
338862306a36Sopenharmony_ci	dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
338962306a36Sopenharmony_ci	return ret;
339062306a36Sopenharmony_ci}
339162306a36Sopenharmony_ci
339262306a36Sopenharmony_cistatic int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
339362306a36Sopenharmony_ci{
339462306a36Sopenharmony_ci	__be32 *p;
339562306a36Sopenharmony_ci
339662306a36Sopenharmony_ci	*res = 0;
339762306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
339862306a36Sopenharmony_ci		return -EIO;
339962306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
340062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
340162306a36Sopenharmony_ci		if (unlikely(!p))
340262306a36Sopenharmony_ci			return -EIO;
340362306a36Sopenharmony_ci		*res = be32_to_cpup(p);
340462306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
340562306a36Sopenharmony_ci	}
340662306a36Sopenharmony_ci	dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
340762306a36Sopenharmony_ci	return 0;
340862306a36Sopenharmony_ci}
340962306a36Sopenharmony_ci
341062306a36Sopenharmony_cistatic int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
341162306a36Sopenharmony_ci{
341262306a36Sopenharmony_ci	__be32 *p;
341362306a36Sopenharmony_ci
341462306a36Sopenharmony_ci	*res = 0;
341562306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
341662306a36Sopenharmony_ci		return -EIO;
341762306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
341862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
341962306a36Sopenharmony_ci		if (unlikely(!p))
342062306a36Sopenharmony_ci			return -EIO;
342162306a36Sopenharmony_ci		*res = be32_to_cpup(p);
342262306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
342362306a36Sopenharmony_ci	}
342462306a36Sopenharmony_ci	dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
342562306a36Sopenharmony_ci	return 0;
342662306a36Sopenharmony_ci}
342762306a36Sopenharmony_ci
342862306a36Sopenharmony_cistatic int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
342962306a36Sopenharmony_ci{
343062306a36Sopenharmony_ci	__be32 *p;
343162306a36Sopenharmony_ci	int ret = 0;
343262306a36Sopenharmony_ci
343362306a36Sopenharmony_ci	fsid->major = 0;
343462306a36Sopenharmony_ci	fsid->minor = 0;
343562306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
343662306a36Sopenharmony_ci		return -EIO;
343762306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
343862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 16);
343962306a36Sopenharmony_ci		if (unlikely(!p))
344062306a36Sopenharmony_ci			return -EIO;
344162306a36Sopenharmony_ci		p = xdr_decode_hyper(p, &fsid->major);
344262306a36Sopenharmony_ci		xdr_decode_hyper(p, &fsid->minor);
344362306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FSID;
344462306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_FSID;
344562306a36Sopenharmony_ci	}
344662306a36Sopenharmony_ci	dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
344762306a36Sopenharmony_ci			(unsigned long long)fsid->major,
344862306a36Sopenharmony_ci			(unsigned long long)fsid->minor);
344962306a36Sopenharmony_ci	return ret;
345062306a36Sopenharmony_ci}
345162306a36Sopenharmony_ci
345262306a36Sopenharmony_cistatic int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
345362306a36Sopenharmony_ci{
345462306a36Sopenharmony_ci	__be32 *p;
345562306a36Sopenharmony_ci
345662306a36Sopenharmony_ci	*res = 60;
345762306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
345862306a36Sopenharmony_ci		return -EIO;
345962306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
346062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
346162306a36Sopenharmony_ci		if (unlikely(!p))
346262306a36Sopenharmony_ci			return -EIO;
346362306a36Sopenharmony_ci		*res = be32_to_cpup(p);
346462306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
346562306a36Sopenharmony_ci	}
346662306a36Sopenharmony_ci	dprintk("%s: lease time=%u\n", __func__, (unsigned int)*res);
346762306a36Sopenharmony_ci	return 0;
346862306a36Sopenharmony_ci}
346962306a36Sopenharmony_ci
347062306a36Sopenharmony_cistatic int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
347162306a36Sopenharmony_ci{
347262306a36Sopenharmony_ci	__be32 *p;
347362306a36Sopenharmony_ci
347462306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
347562306a36Sopenharmony_ci		return -EIO;
347662306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
347762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
347862306a36Sopenharmony_ci		if (unlikely(!p))
347962306a36Sopenharmony_ci			return -EIO;
348062306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
348162306a36Sopenharmony_ci		*res = -be32_to_cpup(p);
348262306a36Sopenharmony_ci	}
348362306a36Sopenharmony_ci	return 0;
348462306a36Sopenharmony_ci}
348562306a36Sopenharmony_ci
348662306a36Sopenharmony_cistatic int decode_attr_exclcreat_supported(struct xdr_stream *xdr,
348762306a36Sopenharmony_ci				 uint32_t *bitmap, uint32_t *bitmask)
348862306a36Sopenharmony_ci{
348962306a36Sopenharmony_ci	if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) {
349062306a36Sopenharmony_ci		int ret;
349162306a36Sopenharmony_ci		ret = decode_attr_bitmap(xdr, bitmask);
349262306a36Sopenharmony_ci		if (unlikely(ret < 0))
349362306a36Sopenharmony_ci			return ret;
349462306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT;
349562306a36Sopenharmony_ci	} else
349662306a36Sopenharmony_ci		bitmask[0] = bitmask[1] = bitmask[2] = 0;
349762306a36Sopenharmony_ci	dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
349862306a36Sopenharmony_ci		bitmask[0], bitmask[1], bitmask[2]);
349962306a36Sopenharmony_ci	return 0;
350062306a36Sopenharmony_ci}
350162306a36Sopenharmony_ci
350262306a36Sopenharmony_cistatic int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
350362306a36Sopenharmony_ci{
350462306a36Sopenharmony_ci	__be32 *p;
350562306a36Sopenharmony_ci	u32 len;
350662306a36Sopenharmony_ci
350762306a36Sopenharmony_ci	if (fh != NULL)
350862306a36Sopenharmony_ci		memset(fh, 0, sizeof(*fh));
350962306a36Sopenharmony_ci
351062306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
351162306a36Sopenharmony_ci		return -EIO;
351262306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
351362306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
351462306a36Sopenharmony_ci		if (unlikely(!p))
351562306a36Sopenharmony_ci			return -EIO;
351662306a36Sopenharmony_ci		len = be32_to_cpup(p);
351762306a36Sopenharmony_ci		if (len > NFS4_FHSIZE || len == 0) {
351862306a36Sopenharmony_ci			trace_nfs4_xdr_bad_filehandle(xdr, OP_READDIR,
351962306a36Sopenharmony_ci						      NFS4ERR_BADHANDLE);
352062306a36Sopenharmony_ci			return -EREMOTEIO;
352162306a36Sopenharmony_ci		}
352262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, len);
352362306a36Sopenharmony_ci		if (unlikely(!p))
352462306a36Sopenharmony_ci			return -EIO;
352562306a36Sopenharmony_ci		if (fh != NULL) {
352662306a36Sopenharmony_ci			memcpy(fh->data, p, len);
352762306a36Sopenharmony_ci			fh->size = len;
352862306a36Sopenharmony_ci		}
352962306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
353062306a36Sopenharmony_ci	}
353162306a36Sopenharmony_ci	return 0;
353262306a36Sopenharmony_ci}
353362306a36Sopenharmony_ci
353462306a36Sopenharmony_cistatic int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
353562306a36Sopenharmony_ci{
353662306a36Sopenharmony_ci	__be32 *p;
353762306a36Sopenharmony_ci
353862306a36Sopenharmony_ci	*res = 0;
353962306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
354062306a36Sopenharmony_ci		return -EIO;
354162306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
354262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
354362306a36Sopenharmony_ci		if (unlikely(!p))
354462306a36Sopenharmony_ci			return -EIO;
354562306a36Sopenharmony_ci		*res = be32_to_cpup(p);
354662306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
354762306a36Sopenharmony_ci	}
354862306a36Sopenharmony_ci	dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
354962306a36Sopenharmony_ci	return 0;
355062306a36Sopenharmony_ci}
355162306a36Sopenharmony_ci
355262306a36Sopenharmony_cistatic int decode_attr_case_insensitive(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
355362306a36Sopenharmony_ci{
355462306a36Sopenharmony_ci	__be32 *p;
355562306a36Sopenharmony_ci
355662306a36Sopenharmony_ci	*res = 0;
355762306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_CASE_INSENSITIVE - 1U)))
355862306a36Sopenharmony_ci		return -EIO;
355962306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_CASE_INSENSITIVE)) {
356062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
356162306a36Sopenharmony_ci		if (unlikely(!p))
356262306a36Sopenharmony_ci			return -EIO;
356362306a36Sopenharmony_ci		*res = be32_to_cpup(p);
356462306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_CASE_INSENSITIVE;
356562306a36Sopenharmony_ci	}
356662306a36Sopenharmony_ci	dprintk("%s: case_insensitive=%s\n", __func__, *res == 0 ? "false" : "true");
356762306a36Sopenharmony_ci	return 0;
356862306a36Sopenharmony_ci}
356962306a36Sopenharmony_ci
357062306a36Sopenharmony_cistatic int decode_attr_case_preserving(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
357162306a36Sopenharmony_ci{
357262306a36Sopenharmony_ci	__be32 *p;
357362306a36Sopenharmony_ci
357462306a36Sopenharmony_ci	*res = 0;
357562306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_CASE_PRESERVING - 1U)))
357662306a36Sopenharmony_ci		return -EIO;
357762306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_CASE_PRESERVING)) {
357862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
357962306a36Sopenharmony_ci		if (unlikely(!p))
358062306a36Sopenharmony_ci			return -EIO;
358162306a36Sopenharmony_ci		*res = be32_to_cpup(p);
358262306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_CASE_PRESERVING;
358362306a36Sopenharmony_ci	}
358462306a36Sopenharmony_ci	dprintk("%s: case_preserving=%s\n", __func__, *res == 0 ? "false" : "true");
358562306a36Sopenharmony_ci	return 0;
358662306a36Sopenharmony_ci}
358762306a36Sopenharmony_ci
358862306a36Sopenharmony_cistatic int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
358962306a36Sopenharmony_ci{
359062306a36Sopenharmony_ci	__be32 *p;
359162306a36Sopenharmony_ci	int ret = 0;
359262306a36Sopenharmony_ci
359362306a36Sopenharmony_ci	*fileid = 0;
359462306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
359562306a36Sopenharmony_ci		return -EIO;
359662306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
359762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
359862306a36Sopenharmony_ci		if (unlikely(!p))
359962306a36Sopenharmony_ci			return -EIO;
360062306a36Sopenharmony_ci		xdr_decode_hyper(p, fileid);
360162306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FILEID;
360262306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_FILEID;
360362306a36Sopenharmony_ci	}
360462306a36Sopenharmony_ci	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
360562306a36Sopenharmony_ci	return ret;
360662306a36Sopenharmony_ci}
360762306a36Sopenharmony_ci
360862306a36Sopenharmony_cistatic int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
360962306a36Sopenharmony_ci{
361062306a36Sopenharmony_ci	__be32 *p;
361162306a36Sopenharmony_ci	int ret = 0;
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci	*fileid = 0;
361462306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
361562306a36Sopenharmony_ci		return -EIO;
361662306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
361762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
361862306a36Sopenharmony_ci		if (unlikely(!p))
361962306a36Sopenharmony_ci			return -EIO;
362062306a36Sopenharmony_ci		xdr_decode_hyper(p, fileid);
362162306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
362262306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
362362306a36Sopenharmony_ci	}
362462306a36Sopenharmony_ci	dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
362562306a36Sopenharmony_ci	return ret;
362662306a36Sopenharmony_ci}
362762306a36Sopenharmony_ci
362862306a36Sopenharmony_cistatic int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
362962306a36Sopenharmony_ci{
363062306a36Sopenharmony_ci	__be32 *p;
363162306a36Sopenharmony_ci	int status = 0;
363262306a36Sopenharmony_ci
363362306a36Sopenharmony_ci	*res = 0;
363462306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
363562306a36Sopenharmony_ci		return -EIO;
363662306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
363762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
363862306a36Sopenharmony_ci		if (unlikely(!p))
363962306a36Sopenharmony_ci			return -EIO;
364062306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
364162306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
364262306a36Sopenharmony_ci	}
364362306a36Sopenharmony_ci	dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
364462306a36Sopenharmony_ci	return status;
364562306a36Sopenharmony_ci}
364662306a36Sopenharmony_ci
364762306a36Sopenharmony_cistatic int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
364862306a36Sopenharmony_ci{
364962306a36Sopenharmony_ci	__be32 *p;
365062306a36Sopenharmony_ci	int status = 0;
365162306a36Sopenharmony_ci
365262306a36Sopenharmony_ci	*res = 0;
365362306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
365462306a36Sopenharmony_ci		return -EIO;
365562306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
365662306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
365762306a36Sopenharmony_ci		if (unlikely(!p))
365862306a36Sopenharmony_ci			return -EIO;
365962306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
366062306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
366162306a36Sopenharmony_ci	}
366262306a36Sopenharmony_ci	dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
366362306a36Sopenharmony_ci	return status;
366462306a36Sopenharmony_ci}
366562306a36Sopenharmony_ci
366662306a36Sopenharmony_cistatic int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
366762306a36Sopenharmony_ci{
366862306a36Sopenharmony_ci	__be32 *p;
366962306a36Sopenharmony_ci	int status = 0;
367062306a36Sopenharmony_ci
367162306a36Sopenharmony_ci	*res = 0;
367262306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
367362306a36Sopenharmony_ci		return -EIO;
367462306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
367562306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
367662306a36Sopenharmony_ci		if (unlikely(!p))
367762306a36Sopenharmony_ci			return -EIO;
367862306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
367962306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
368062306a36Sopenharmony_ci	}
368162306a36Sopenharmony_ci	dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
368262306a36Sopenharmony_ci	return status;
368362306a36Sopenharmony_ci}
368462306a36Sopenharmony_ci
368562306a36Sopenharmony_cistatic int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
368662306a36Sopenharmony_ci{
368762306a36Sopenharmony_ci	u32 n;
368862306a36Sopenharmony_ci	__be32 *p;
368962306a36Sopenharmony_ci	int status = 0;
369062306a36Sopenharmony_ci
369162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
369262306a36Sopenharmony_ci	if (unlikely(!p))
369362306a36Sopenharmony_ci		return -EIO;
369462306a36Sopenharmony_ci	n = be32_to_cpup(p);
369562306a36Sopenharmony_ci	if (n == 0)
369662306a36Sopenharmony_ci		goto root_path;
369762306a36Sopenharmony_ci	dprintk("pathname4: ");
369862306a36Sopenharmony_ci	if (n > NFS4_PATHNAME_MAXCOMPONENTS) {
369962306a36Sopenharmony_ci		dprintk("cannot parse %d components in path\n", n);
370062306a36Sopenharmony_ci		goto out_eio;
370162306a36Sopenharmony_ci	}
370262306a36Sopenharmony_ci	for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) {
370362306a36Sopenharmony_ci		struct nfs4_string *component = &path->components[path->ncomponents];
370462306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &component->len, &component->data);
370562306a36Sopenharmony_ci		if (unlikely(status != 0))
370662306a36Sopenharmony_ci			goto out_eio;
370762306a36Sopenharmony_ci		ifdebug (XDR)
370862306a36Sopenharmony_ci			pr_cont("%s%.*s ",
370962306a36Sopenharmony_ci				(path->ncomponents != n ? "/ " : ""),
371062306a36Sopenharmony_ci				component->len, component->data);
371162306a36Sopenharmony_ci	}
371262306a36Sopenharmony_ciout:
371362306a36Sopenharmony_ci	return status;
371462306a36Sopenharmony_ciroot_path:
371562306a36Sopenharmony_ci/* a root pathname is sent as a zero component4 */
371662306a36Sopenharmony_ci	path->ncomponents = 1;
371762306a36Sopenharmony_ci	path->components[0].len=0;
371862306a36Sopenharmony_ci	path->components[0].data=NULL;
371962306a36Sopenharmony_ci	dprintk("pathname4: /\n");
372062306a36Sopenharmony_ci	goto out;
372162306a36Sopenharmony_ciout_eio:
372262306a36Sopenharmony_ci	dprintk(" status %d", status);
372362306a36Sopenharmony_ci	status = -EIO;
372462306a36Sopenharmony_ci	goto out;
372562306a36Sopenharmony_ci}
372662306a36Sopenharmony_ci
372762306a36Sopenharmony_cistatic int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
372862306a36Sopenharmony_ci{
372962306a36Sopenharmony_ci	int n;
373062306a36Sopenharmony_ci	__be32 *p;
373162306a36Sopenharmony_ci	int status = -EIO;
373262306a36Sopenharmony_ci
373362306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
373462306a36Sopenharmony_ci		goto out;
373562306a36Sopenharmony_ci	status = 0;
373662306a36Sopenharmony_ci	if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
373762306a36Sopenharmony_ci		goto out;
373862306a36Sopenharmony_ci	bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS;
373962306a36Sopenharmony_ci	status = -EIO;
374062306a36Sopenharmony_ci	/* Ignore borken servers that return unrequested attrs */
374162306a36Sopenharmony_ci	if (unlikely(res == NULL))
374262306a36Sopenharmony_ci		goto out;
374362306a36Sopenharmony_ci	dprintk("%s: fsroot:\n", __func__);
374462306a36Sopenharmony_ci	status = decode_pathname(xdr, &res->fs_path);
374562306a36Sopenharmony_ci	if (unlikely(status != 0))
374662306a36Sopenharmony_ci		goto out;
374762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
374862306a36Sopenharmony_ci	if (unlikely(!p))
374962306a36Sopenharmony_ci		goto out_eio;
375062306a36Sopenharmony_ci	n = be32_to_cpup(p);
375162306a36Sopenharmony_ci	for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
375262306a36Sopenharmony_ci		u32 m;
375362306a36Sopenharmony_ci		struct nfs4_fs_location *loc;
375462306a36Sopenharmony_ci
375562306a36Sopenharmony_ci		if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES)
375662306a36Sopenharmony_ci			break;
375762306a36Sopenharmony_ci		loc = &res->locations[res->nlocations];
375862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
375962306a36Sopenharmony_ci		if (unlikely(!p))
376062306a36Sopenharmony_ci			goto out_eio;
376162306a36Sopenharmony_ci		m = be32_to_cpup(p);
376262306a36Sopenharmony_ci
376362306a36Sopenharmony_ci		dprintk("%s: servers:\n", __func__);
376462306a36Sopenharmony_ci		for (loc->nservers = 0; loc->nservers < m; loc->nservers++) {
376562306a36Sopenharmony_ci			struct nfs4_string *server;
376662306a36Sopenharmony_ci
376762306a36Sopenharmony_ci			if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) {
376862306a36Sopenharmony_ci				unsigned int i;
376962306a36Sopenharmony_ci				dprintk("%s: using first %u of %u servers "
377062306a36Sopenharmony_ci					"returned for location %u\n",
377162306a36Sopenharmony_ci						__func__,
377262306a36Sopenharmony_ci						NFS4_FS_LOCATION_MAXSERVERS,
377362306a36Sopenharmony_ci						m, res->nlocations);
377462306a36Sopenharmony_ci				for (i = loc->nservers; i < m; i++) {
377562306a36Sopenharmony_ci					unsigned int len;
377662306a36Sopenharmony_ci					char *data;
377762306a36Sopenharmony_ci					status = decode_opaque_inline(xdr, &len, &data);
377862306a36Sopenharmony_ci					if (unlikely(status != 0))
377962306a36Sopenharmony_ci						goto out_eio;
378062306a36Sopenharmony_ci				}
378162306a36Sopenharmony_ci				break;
378262306a36Sopenharmony_ci			}
378362306a36Sopenharmony_ci			server = &loc->servers[loc->nservers];
378462306a36Sopenharmony_ci			status = decode_opaque_inline(xdr, &server->len, &server->data);
378562306a36Sopenharmony_ci			if (unlikely(status != 0))
378662306a36Sopenharmony_ci				goto out_eio;
378762306a36Sopenharmony_ci			dprintk("%s ", server->data);
378862306a36Sopenharmony_ci		}
378962306a36Sopenharmony_ci		status = decode_pathname(xdr, &loc->rootpath);
379062306a36Sopenharmony_ci		if (unlikely(status != 0))
379162306a36Sopenharmony_ci			goto out_eio;
379262306a36Sopenharmony_ci	}
379362306a36Sopenharmony_ci	if (res->nlocations != 0)
379462306a36Sopenharmony_ci		status = NFS_ATTR_FATTR_V4_LOCATIONS;
379562306a36Sopenharmony_ciout:
379662306a36Sopenharmony_ci	dprintk("%s: fs_locations done, error = %d\n", __func__, status);
379762306a36Sopenharmony_ci	return status;
379862306a36Sopenharmony_ciout_eio:
379962306a36Sopenharmony_ci	status = -EIO;
380062306a36Sopenharmony_ci	goto out;
380162306a36Sopenharmony_ci}
380262306a36Sopenharmony_ci
380362306a36Sopenharmony_cistatic int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
380462306a36Sopenharmony_ci{
380562306a36Sopenharmony_ci	__be32 *p;
380662306a36Sopenharmony_ci	int status = 0;
380762306a36Sopenharmony_ci
380862306a36Sopenharmony_ci	*res = 0;
380962306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
381062306a36Sopenharmony_ci		return -EIO;
381162306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
381262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
381362306a36Sopenharmony_ci		if (unlikely(!p))
381462306a36Sopenharmony_ci			return -EIO;
381562306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
381662306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
381762306a36Sopenharmony_ci	}
381862306a36Sopenharmony_ci	dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
381962306a36Sopenharmony_ci	return status;
382062306a36Sopenharmony_ci}
382162306a36Sopenharmony_ci
382262306a36Sopenharmony_cistatic int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
382362306a36Sopenharmony_ci{
382462306a36Sopenharmony_ci	__be32 *p;
382562306a36Sopenharmony_ci	int status = 0;
382662306a36Sopenharmony_ci
382762306a36Sopenharmony_ci	*maxlink = 1;
382862306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
382962306a36Sopenharmony_ci		return -EIO;
383062306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
383162306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
383262306a36Sopenharmony_ci		if (unlikely(!p))
383362306a36Sopenharmony_ci			return -EIO;
383462306a36Sopenharmony_ci		*maxlink = be32_to_cpup(p);
383562306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
383662306a36Sopenharmony_ci	}
383762306a36Sopenharmony_ci	dprintk("%s: maxlink=%u\n", __func__, *maxlink);
383862306a36Sopenharmony_ci	return status;
383962306a36Sopenharmony_ci}
384062306a36Sopenharmony_ci
384162306a36Sopenharmony_cistatic int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
384262306a36Sopenharmony_ci{
384362306a36Sopenharmony_ci	__be32 *p;
384462306a36Sopenharmony_ci	int status = 0;
384562306a36Sopenharmony_ci
384662306a36Sopenharmony_ci	*maxname = 1024;
384762306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
384862306a36Sopenharmony_ci		return -EIO;
384962306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
385062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
385162306a36Sopenharmony_ci		if (unlikely(!p))
385262306a36Sopenharmony_ci			return -EIO;
385362306a36Sopenharmony_ci		*maxname = be32_to_cpup(p);
385462306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
385562306a36Sopenharmony_ci	}
385662306a36Sopenharmony_ci	dprintk("%s: maxname=%u\n", __func__, *maxname);
385762306a36Sopenharmony_ci	return status;
385862306a36Sopenharmony_ci}
385962306a36Sopenharmony_ci
386062306a36Sopenharmony_cistatic int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
386162306a36Sopenharmony_ci{
386262306a36Sopenharmony_ci	__be32 *p;
386362306a36Sopenharmony_ci	int status = 0;
386462306a36Sopenharmony_ci
386562306a36Sopenharmony_ci	*res = 1024;
386662306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
386762306a36Sopenharmony_ci		return -EIO;
386862306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
386962306a36Sopenharmony_ci		uint64_t maxread;
387062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
387162306a36Sopenharmony_ci		if (unlikely(!p))
387262306a36Sopenharmony_ci			return -EIO;
387362306a36Sopenharmony_ci		xdr_decode_hyper(p, &maxread);
387462306a36Sopenharmony_ci		if (maxread > 0x7FFFFFFF)
387562306a36Sopenharmony_ci			maxread = 0x7FFFFFFF;
387662306a36Sopenharmony_ci		*res = (uint32_t)maxread;
387762306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
387862306a36Sopenharmony_ci	}
387962306a36Sopenharmony_ci	dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
388062306a36Sopenharmony_ci	return status;
388162306a36Sopenharmony_ci}
388262306a36Sopenharmony_ci
388362306a36Sopenharmony_cistatic int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
388462306a36Sopenharmony_ci{
388562306a36Sopenharmony_ci	__be32 *p;
388662306a36Sopenharmony_ci	int status = 0;
388762306a36Sopenharmony_ci
388862306a36Sopenharmony_ci	*res = 1024;
388962306a36Sopenharmony_ci	if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
389062306a36Sopenharmony_ci		return -EIO;
389162306a36Sopenharmony_ci	if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
389262306a36Sopenharmony_ci		uint64_t maxwrite;
389362306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
389462306a36Sopenharmony_ci		if (unlikely(!p))
389562306a36Sopenharmony_ci			return -EIO;
389662306a36Sopenharmony_ci		xdr_decode_hyper(p, &maxwrite);
389762306a36Sopenharmony_ci		if (maxwrite > 0x7FFFFFFF)
389862306a36Sopenharmony_ci			maxwrite = 0x7FFFFFFF;
389962306a36Sopenharmony_ci		*res = (uint32_t)maxwrite;
390062306a36Sopenharmony_ci		bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
390162306a36Sopenharmony_ci	}
390262306a36Sopenharmony_ci	dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
390362306a36Sopenharmony_ci	return status;
390462306a36Sopenharmony_ci}
390562306a36Sopenharmony_ci
390662306a36Sopenharmony_cistatic int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
390762306a36Sopenharmony_ci{
390862306a36Sopenharmony_ci	uint32_t tmp;
390962306a36Sopenharmony_ci	__be32 *p;
391062306a36Sopenharmony_ci	int ret = 0;
391162306a36Sopenharmony_ci
391262306a36Sopenharmony_ci	*mode = 0;
391362306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
391462306a36Sopenharmony_ci		return -EIO;
391562306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
391662306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
391762306a36Sopenharmony_ci		if (unlikely(!p))
391862306a36Sopenharmony_ci			return -EIO;
391962306a36Sopenharmony_ci		tmp = be32_to_cpup(p);
392062306a36Sopenharmony_ci		*mode = tmp & ~S_IFMT;
392162306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_MODE;
392262306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_MODE;
392362306a36Sopenharmony_ci	}
392462306a36Sopenharmony_ci	dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
392562306a36Sopenharmony_ci	return ret;
392662306a36Sopenharmony_ci}
392762306a36Sopenharmony_ci
392862306a36Sopenharmony_cistatic int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
392962306a36Sopenharmony_ci{
393062306a36Sopenharmony_ci	__be32 *p;
393162306a36Sopenharmony_ci	int ret = 0;
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci	*nlink = 1;
393462306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
393562306a36Sopenharmony_ci		return -EIO;
393662306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
393762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
393862306a36Sopenharmony_ci		if (unlikely(!p))
393962306a36Sopenharmony_ci			return -EIO;
394062306a36Sopenharmony_ci		*nlink = be32_to_cpup(p);
394162306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
394262306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_NLINK;
394362306a36Sopenharmony_ci	}
394462306a36Sopenharmony_ci	dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
394562306a36Sopenharmony_ci	return ret;
394662306a36Sopenharmony_ci}
394762306a36Sopenharmony_ci
394862306a36Sopenharmony_cistatic ssize_t decode_nfs4_string(struct xdr_stream *xdr,
394962306a36Sopenharmony_ci		struct nfs4_string *name, gfp_t gfp_flags)
395062306a36Sopenharmony_ci{
395162306a36Sopenharmony_ci	ssize_t ret;
395262306a36Sopenharmony_ci
395362306a36Sopenharmony_ci	ret = xdr_stream_decode_string_dup(xdr, &name->data,
395462306a36Sopenharmony_ci			XDR_MAX_NETOBJ, gfp_flags);
395562306a36Sopenharmony_ci	name->len = 0;
395662306a36Sopenharmony_ci	if (ret > 0)
395762306a36Sopenharmony_ci		name->len = ret;
395862306a36Sopenharmony_ci	return ret;
395962306a36Sopenharmony_ci}
396062306a36Sopenharmony_ci
396162306a36Sopenharmony_cistatic int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
396262306a36Sopenharmony_ci		const struct nfs_server *server, kuid_t *uid,
396362306a36Sopenharmony_ci		struct nfs4_string *owner_name)
396462306a36Sopenharmony_ci{
396562306a36Sopenharmony_ci	ssize_t len;
396662306a36Sopenharmony_ci	char *p;
396762306a36Sopenharmony_ci
396862306a36Sopenharmony_ci	*uid = make_kuid(&init_user_ns, -2);
396962306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
397062306a36Sopenharmony_ci		return -EIO;
397162306a36Sopenharmony_ci	if (!(bitmap[1] & FATTR4_WORD1_OWNER))
397262306a36Sopenharmony_ci		return 0;
397362306a36Sopenharmony_ci	bitmap[1] &= ~FATTR4_WORD1_OWNER;
397462306a36Sopenharmony_ci
397562306a36Sopenharmony_ci	if (owner_name != NULL) {
397662306a36Sopenharmony_ci		len = decode_nfs4_string(xdr, owner_name, GFP_NOIO);
397762306a36Sopenharmony_ci		if (len <= 0)
397862306a36Sopenharmony_ci			goto out;
397962306a36Sopenharmony_ci		dprintk("%s: name=%s\n", __func__, owner_name->data);
398062306a36Sopenharmony_ci		return NFS_ATTR_FATTR_OWNER_NAME;
398162306a36Sopenharmony_ci	} else {
398262306a36Sopenharmony_ci		len = xdr_stream_decode_opaque_inline(xdr, (void **)&p,
398362306a36Sopenharmony_ci				XDR_MAX_NETOBJ);
398462306a36Sopenharmony_ci		if (len <= 0 || nfs_map_name_to_uid(server, p, len, uid) != 0)
398562306a36Sopenharmony_ci			goto out;
398662306a36Sopenharmony_ci		dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid));
398762306a36Sopenharmony_ci		return NFS_ATTR_FATTR_OWNER;
398862306a36Sopenharmony_ci	}
398962306a36Sopenharmony_ciout:
399062306a36Sopenharmony_ci	if (len == -EBADMSG)
399162306a36Sopenharmony_ci		return -EIO;
399262306a36Sopenharmony_ci	return 0;
399362306a36Sopenharmony_ci}
399462306a36Sopenharmony_ci
399562306a36Sopenharmony_cistatic int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
399662306a36Sopenharmony_ci		const struct nfs_server *server, kgid_t *gid,
399762306a36Sopenharmony_ci		struct nfs4_string *group_name)
399862306a36Sopenharmony_ci{
399962306a36Sopenharmony_ci	ssize_t len;
400062306a36Sopenharmony_ci	char *p;
400162306a36Sopenharmony_ci
400262306a36Sopenharmony_ci	*gid = make_kgid(&init_user_ns, -2);
400362306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
400462306a36Sopenharmony_ci		return -EIO;
400562306a36Sopenharmony_ci	if (!(bitmap[1] & FATTR4_WORD1_OWNER_GROUP))
400662306a36Sopenharmony_ci		return 0;
400762306a36Sopenharmony_ci	bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
400862306a36Sopenharmony_ci
400962306a36Sopenharmony_ci	if (group_name != NULL) {
401062306a36Sopenharmony_ci		len = decode_nfs4_string(xdr, group_name, GFP_NOIO);
401162306a36Sopenharmony_ci		if (len <= 0)
401262306a36Sopenharmony_ci			goto out;
401362306a36Sopenharmony_ci		dprintk("%s: name=%s\n", __func__, group_name->data);
401462306a36Sopenharmony_ci		return NFS_ATTR_FATTR_GROUP_NAME;
401562306a36Sopenharmony_ci	} else {
401662306a36Sopenharmony_ci		len = xdr_stream_decode_opaque_inline(xdr, (void **)&p,
401762306a36Sopenharmony_ci				XDR_MAX_NETOBJ);
401862306a36Sopenharmony_ci		if (len <= 0 || nfs_map_group_to_gid(server, p, len, gid) != 0)
401962306a36Sopenharmony_ci			goto out;
402062306a36Sopenharmony_ci		dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid));
402162306a36Sopenharmony_ci		return NFS_ATTR_FATTR_GROUP;
402262306a36Sopenharmony_ci	}
402362306a36Sopenharmony_ciout:
402462306a36Sopenharmony_ci	if (len == -EBADMSG)
402562306a36Sopenharmony_ci		return -EIO;
402662306a36Sopenharmony_ci	return 0;
402762306a36Sopenharmony_ci}
402862306a36Sopenharmony_ci
402962306a36Sopenharmony_cistatic int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
403062306a36Sopenharmony_ci{
403162306a36Sopenharmony_ci	uint32_t major = 0, minor = 0;
403262306a36Sopenharmony_ci	__be32 *p;
403362306a36Sopenharmony_ci	int ret = 0;
403462306a36Sopenharmony_ci
403562306a36Sopenharmony_ci	*rdev = MKDEV(0,0);
403662306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
403762306a36Sopenharmony_ci		return -EIO;
403862306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
403962306a36Sopenharmony_ci		dev_t tmp;
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
404262306a36Sopenharmony_ci		if (unlikely(!p))
404362306a36Sopenharmony_ci			return -EIO;
404462306a36Sopenharmony_ci		major = be32_to_cpup(p++);
404562306a36Sopenharmony_ci		minor = be32_to_cpup(p);
404662306a36Sopenharmony_ci		tmp = MKDEV(major, minor);
404762306a36Sopenharmony_ci		if (MAJOR(tmp) == major && MINOR(tmp) == minor)
404862306a36Sopenharmony_ci			*rdev = tmp;
404962306a36Sopenharmony_ci		bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
405062306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_RDEV;
405162306a36Sopenharmony_ci	}
405262306a36Sopenharmony_ci	dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
405362306a36Sopenharmony_ci	return ret;
405462306a36Sopenharmony_ci}
405562306a36Sopenharmony_ci
405662306a36Sopenharmony_cistatic int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
405762306a36Sopenharmony_ci{
405862306a36Sopenharmony_ci	__be32 *p;
405962306a36Sopenharmony_ci	int status = 0;
406062306a36Sopenharmony_ci
406162306a36Sopenharmony_ci	*res = 0;
406262306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
406362306a36Sopenharmony_ci		return -EIO;
406462306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
406562306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
406662306a36Sopenharmony_ci		if (unlikely(!p))
406762306a36Sopenharmony_ci			return -EIO;
406862306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
406962306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
407062306a36Sopenharmony_ci	}
407162306a36Sopenharmony_ci	dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
407262306a36Sopenharmony_ci	return status;
407362306a36Sopenharmony_ci}
407462306a36Sopenharmony_ci
407562306a36Sopenharmony_cistatic int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
407662306a36Sopenharmony_ci{
407762306a36Sopenharmony_ci	__be32 *p;
407862306a36Sopenharmony_ci	int status = 0;
407962306a36Sopenharmony_ci
408062306a36Sopenharmony_ci	*res = 0;
408162306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
408262306a36Sopenharmony_ci		return -EIO;
408362306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
408462306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
408562306a36Sopenharmony_ci		if (unlikely(!p))
408662306a36Sopenharmony_ci			return -EIO;
408762306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
408862306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
408962306a36Sopenharmony_ci	}
409062306a36Sopenharmony_ci	dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
409162306a36Sopenharmony_ci	return status;
409262306a36Sopenharmony_ci}
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_cistatic int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
409562306a36Sopenharmony_ci{
409662306a36Sopenharmony_ci	__be32 *p;
409762306a36Sopenharmony_ci	int status = 0;
409862306a36Sopenharmony_ci
409962306a36Sopenharmony_ci	*res = 0;
410062306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
410162306a36Sopenharmony_ci		return -EIO;
410262306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
410362306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
410462306a36Sopenharmony_ci		if (unlikely(!p))
410562306a36Sopenharmony_ci			return -EIO;
410662306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
410762306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
410862306a36Sopenharmony_ci	}
410962306a36Sopenharmony_ci	dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
411062306a36Sopenharmony_ci	return status;
411162306a36Sopenharmony_ci}
411262306a36Sopenharmony_ci
411362306a36Sopenharmony_cistatic int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
411462306a36Sopenharmony_ci{
411562306a36Sopenharmony_ci	__be32 *p;
411662306a36Sopenharmony_ci	int ret = 0;
411762306a36Sopenharmony_ci
411862306a36Sopenharmony_ci	*used = 0;
411962306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
412062306a36Sopenharmony_ci		return -EIO;
412162306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
412262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
412362306a36Sopenharmony_ci		if (unlikely(!p))
412462306a36Sopenharmony_ci			return -EIO;
412562306a36Sopenharmony_ci		xdr_decode_hyper(p, used);
412662306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
412762306a36Sopenharmony_ci		ret = NFS_ATTR_FATTR_SPACE_USED;
412862306a36Sopenharmony_ci	}
412962306a36Sopenharmony_ci	dprintk("%s: space used=%Lu\n", __func__,
413062306a36Sopenharmony_ci			(unsigned long long)*used);
413162306a36Sopenharmony_ci	return ret;
413262306a36Sopenharmony_ci}
413362306a36Sopenharmony_ci
413462306a36Sopenharmony_cistatic __be32 *
413562306a36Sopenharmony_cixdr_decode_nfstime4(__be32 *p, struct timespec64 *t)
413662306a36Sopenharmony_ci{
413762306a36Sopenharmony_ci	__u64 sec;
413862306a36Sopenharmony_ci
413962306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &sec);
414062306a36Sopenharmony_ci	t-> tv_sec = sec;
414162306a36Sopenharmony_ci	t->tv_nsec = be32_to_cpup(p++);
414262306a36Sopenharmony_ci	return p;
414362306a36Sopenharmony_ci}
414462306a36Sopenharmony_ci
414562306a36Sopenharmony_cistatic int decode_attr_time(struct xdr_stream *xdr, struct timespec64 *time)
414662306a36Sopenharmony_ci{
414762306a36Sopenharmony_ci	__be32 *p;
414862306a36Sopenharmony_ci
414962306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, nfstime4_maxsz << 2);
415062306a36Sopenharmony_ci	if (unlikely(!p))
415162306a36Sopenharmony_ci		return -EIO;
415262306a36Sopenharmony_ci	xdr_decode_nfstime4(p, time);
415362306a36Sopenharmony_ci	return 0;
415462306a36Sopenharmony_ci}
415562306a36Sopenharmony_ci
415662306a36Sopenharmony_cistatic int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time)
415762306a36Sopenharmony_ci{
415862306a36Sopenharmony_ci	int status = 0;
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci	time->tv_sec = 0;
416162306a36Sopenharmony_ci	time->tv_nsec = 0;
416262306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
416362306a36Sopenharmony_ci		return -EIO;
416462306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
416562306a36Sopenharmony_ci		status = decode_attr_time(xdr, time);
416662306a36Sopenharmony_ci		if (status == 0)
416762306a36Sopenharmony_ci			status = NFS_ATTR_FATTR_ATIME;
416862306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
416962306a36Sopenharmony_ci	}
417062306a36Sopenharmony_ci	dprintk("%s: atime=%lld\n", __func__, time->tv_sec);
417162306a36Sopenharmony_ci	return status;
417262306a36Sopenharmony_ci}
417362306a36Sopenharmony_ci
417462306a36Sopenharmony_cistatic int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time)
417562306a36Sopenharmony_ci{
417662306a36Sopenharmony_ci	int status = 0;
417762306a36Sopenharmony_ci
417862306a36Sopenharmony_ci	time->tv_sec = 0;
417962306a36Sopenharmony_ci	time->tv_nsec = 0;
418062306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
418162306a36Sopenharmony_ci		return -EIO;
418262306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
418362306a36Sopenharmony_ci		status = decode_attr_time(xdr, time);
418462306a36Sopenharmony_ci		if (status == 0)
418562306a36Sopenharmony_ci			status = NFS_ATTR_FATTR_CTIME;
418662306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
418762306a36Sopenharmony_ci	}
418862306a36Sopenharmony_ci	dprintk("%s: ctime=%lld\n", __func__, time->tv_sec);
418962306a36Sopenharmony_ci	return status;
419062306a36Sopenharmony_ci}
419162306a36Sopenharmony_ci
419262306a36Sopenharmony_cistatic int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
419362306a36Sopenharmony_ci				  struct timespec64 *time)
419462306a36Sopenharmony_ci{
419562306a36Sopenharmony_ci	int status = 0;
419662306a36Sopenharmony_ci
419762306a36Sopenharmony_ci	time->tv_sec = 0;
419862306a36Sopenharmony_ci	time->tv_nsec = 0;
419962306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
420062306a36Sopenharmony_ci		return -EIO;
420162306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
420262306a36Sopenharmony_ci		status = decode_attr_time(xdr, time);
420362306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
420462306a36Sopenharmony_ci	}
420562306a36Sopenharmony_ci	dprintk("%s: time_delta=%lld %ld\n", __func__, time->tv_sec,
420662306a36Sopenharmony_ci		time->tv_nsec);
420762306a36Sopenharmony_ci	return status;
420862306a36Sopenharmony_ci}
420962306a36Sopenharmony_ci
421062306a36Sopenharmony_cistatic int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
421162306a36Sopenharmony_ci					struct nfs4_label *label)
421262306a36Sopenharmony_ci{
421362306a36Sopenharmony_ci	uint32_t pi = 0;
421462306a36Sopenharmony_ci	uint32_t lfs = 0;
421562306a36Sopenharmony_ci	__u32 len;
421662306a36Sopenharmony_ci	__be32 *p;
421762306a36Sopenharmony_ci	int status = 0;
421862306a36Sopenharmony_ci
421962306a36Sopenharmony_ci	if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U)))
422062306a36Sopenharmony_ci		return -EIO;
422162306a36Sopenharmony_ci	if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) {
422262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
422362306a36Sopenharmony_ci		if (unlikely(!p))
422462306a36Sopenharmony_ci			return -EIO;
422562306a36Sopenharmony_ci		lfs = be32_to_cpup(p++);
422662306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
422762306a36Sopenharmony_ci		if (unlikely(!p))
422862306a36Sopenharmony_ci			return -EIO;
422962306a36Sopenharmony_ci		pi = be32_to_cpup(p++);
423062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
423162306a36Sopenharmony_ci		if (unlikely(!p))
423262306a36Sopenharmony_ci			return -EIO;
423362306a36Sopenharmony_ci		len = be32_to_cpup(p++);
423462306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, len);
423562306a36Sopenharmony_ci		if (unlikely(!p))
423662306a36Sopenharmony_ci			return -EIO;
423762306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
423862306a36Sopenharmony_ci		if (len < NFS4_MAXLABELLEN) {
423962306a36Sopenharmony_ci			if (label && label->len) {
424062306a36Sopenharmony_ci				if (label->len < len)
424162306a36Sopenharmony_ci					return -ERANGE;
424262306a36Sopenharmony_ci				memcpy(label->label, p, len);
424362306a36Sopenharmony_ci				label->len = len;
424462306a36Sopenharmony_ci				label->pi = pi;
424562306a36Sopenharmony_ci				label->lfs = lfs;
424662306a36Sopenharmony_ci				status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
424762306a36Sopenharmony_ci			}
424862306a36Sopenharmony_ci		} else
424962306a36Sopenharmony_ci			printk(KERN_WARNING "%s: label too long (%u)!\n",
425062306a36Sopenharmony_ci					__func__, len);
425162306a36Sopenharmony_ci		if (label && label->label)
425262306a36Sopenharmony_ci			dprintk("%s: label=%.*s, len=%d, PI=%d, LFS=%d\n",
425362306a36Sopenharmony_ci				__func__, label->len, (char *)label->label,
425462306a36Sopenharmony_ci				label->len, label->pi, label->lfs);
425562306a36Sopenharmony_ci	}
425662306a36Sopenharmony_ci	return status;
425762306a36Sopenharmony_ci}
425862306a36Sopenharmony_ci
425962306a36Sopenharmony_cistatic int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec64 *time)
426062306a36Sopenharmony_ci{
426162306a36Sopenharmony_ci	int status = 0;
426262306a36Sopenharmony_ci
426362306a36Sopenharmony_ci	time->tv_sec = 0;
426462306a36Sopenharmony_ci	time->tv_nsec = 0;
426562306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
426662306a36Sopenharmony_ci		return -EIO;
426762306a36Sopenharmony_ci	if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
426862306a36Sopenharmony_ci		status = decode_attr_time(xdr, time);
426962306a36Sopenharmony_ci		if (status == 0)
427062306a36Sopenharmony_ci			status = NFS_ATTR_FATTR_MTIME;
427162306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
427262306a36Sopenharmony_ci	}
427362306a36Sopenharmony_ci	dprintk("%s: mtime=%lld\n", __func__, time->tv_sec);
427462306a36Sopenharmony_ci	return status;
427562306a36Sopenharmony_ci}
427662306a36Sopenharmony_ci
427762306a36Sopenharmony_cistatic int decode_attr_xattrsupport(struct xdr_stream *xdr, uint32_t *bitmap,
427862306a36Sopenharmony_ci				    uint32_t *res)
427962306a36Sopenharmony_ci{
428062306a36Sopenharmony_ci	__be32 *p;
428162306a36Sopenharmony_ci
428262306a36Sopenharmony_ci	*res = 0;
428362306a36Sopenharmony_ci	if (unlikely(bitmap[2] & (FATTR4_WORD2_XATTR_SUPPORT - 1U)))
428462306a36Sopenharmony_ci		return -EIO;
428562306a36Sopenharmony_ci	if (likely(bitmap[2] & FATTR4_WORD2_XATTR_SUPPORT)) {
428662306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
428762306a36Sopenharmony_ci		if (unlikely(!p))
428862306a36Sopenharmony_ci			return -EIO;
428962306a36Sopenharmony_ci		*res = be32_to_cpup(p);
429062306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_XATTR_SUPPORT;
429162306a36Sopenharmony_ci	}
429262306a36Sopenharmony_ci	dprintk("%s: XATTR support=%s\n", __func__,
429362306a36Sopenharmony_ci		*res == 0 ? "false" : "true");
429462306a36Sopenharmony_ci	return 0;
429562306a36Sopenharmony_ci}
429662306a36Sopenharmony_ci
429762306a36Sopenharmony_cistatic int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen)
429862306a36Sopenharmony_ci{
429962306a36Sopenharmony_ci	unsigned int attrwords = XDR_QUADLEN(attrlen);
430062306a36Sopenharmony_ci	unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2;
430162306a36Sopenharmony_ci
430262306a36Sopenharmony_ci	if (unlikely(attrwords != nwords)) {
430362306a36Sopenharmony_ci		dprintk("%s: server returned incorrect attribute length: "
430462306a36Sopenharmony_ci			"%u %c %u\n",
430562306a36Sopenharmony_ci				__func__,
430662306a36Sopenharmony_ci				attrwords << 2,
430762306a36Sopenharmony_ci				(attrwords < nwords) ? '<' : '>',
430862306a36Sopenharmony_ci				nwords << 2);
430962306a36Sopenharmony_ci		return -EIO;
431062306a36Sopenharmony_ci	}
431162306a36Sopenharmony_ci	return 0;
431262306a36Sopenharmony_ci}
431362306a36Sopenharmony_ci
431462306a36Sopenharmony_cistatic int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
431562306a36Sopenharmony_ci{
431662306a36Sopenharmony_ci	__be32 *p;
431762306a36Sopenharmony_ci
431862306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 20);
431962306a36Sopenharmony_ci	if (unlikely(!p))
432062306a36Sopenharmony_ci		return -EIO;
432162306a36Sopenharmony_ci	cinfo->atomic = be32_to_cpup(p++);
432262306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &cinfo->before);
432362306a36Sopenharmony_ci	xdr_decode_hyper(p, &cinfo->after);
432462306a36Sopenharmony_ci	return 0;
432562306a36Sopenharmony_ci}
432662306a36Sopenharmony_ci
432762306a36Sopenharmony_cistatic int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
432862306a36Sopenharmony_ci{
432962306a36Sopenharmony_ci	__be32 *p;
433062306a36Sopenharmony_ci	uint32_t supp, acc;
433162306a36Sopenharmony_ci	int status;
433262306a36Sopenharmony_ci
433362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_ACCESS);
433462306a36Sopenharmony_ci	if (status)
433562306a36Sopenharmony_ci		return status;
433662306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
433762306a36Sopenharmony_ci	if (unlikely(!p))
433862306a36Sopenharmony_ci		return -EIO;
433962306a36Sopenharmony_ci	supp = be32_to_cpup(p++);
434062306a36Sopenharmony_ci	acc = be32_to_cpup(p);
434162306a36Sopenharmony_ci	*supported = supp;
434262306a36Sopenharmony_ci	*access = acc;
434362306a36Sopenharmony_ci	return 0;
434462306a36Sopenharmony_ci}
434562306a36Sopenharmony_ci
434662306a36Sopenharmony_cistatic int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
434762306a36Sopenharmony_ci{
434862306a36Sopenharmony_ci	ssize_t ret = xdr_stream_decode_opaque_fixed(xdr, buf, len);
434962306a36Sopenharmony_ci	if (unlikely(ret < 0))
435062306a36Sopenharmony_ci		return -EIO;
435162306a36Sopenharmony_ci	return 0;
435262306a36Sopenharmony_ci}
435362306a36Sopenharmony_ci
435462306a36Sopenharmony_cistatic int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
435562306a36Sopenharmony_ci{
435662306a36Sopenharmony_ci	return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
435762306a36Sopenharmony_ci}
435862306a36Sopenharmony_ci
435962306a36Sopenharmony_cistatic int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
436062306a36Sopenharmony_ci{
436162306a36Sopenharmony_ci	stateid->type = NFS4_OPEN_STATEID_TYPE;
436262306a36Sopenharmony_ci	return decode_stateid(xdr, stateid);
436362306a36Sopenharmony_ci}
436462306a36Sopenharmony_ci
436562306a36Sopenharmony_cistatic int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
436662306a36Sopenharmony_ci{
436762306a36Sopenharmony_ci	stateid->type = NFS4_LOCK_STATEID_TYPE;
436862306a36Sopenharmony_ci	return decode_stateid(xdr, stateid);
436962306a36Sopenharmony_ci}
437062306a36Sopenharmony_ci
437162306a36Sopenharmony_cistatic int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
437262306a36Sopenharmony_ci{
437362306a36Sopenharmony_ci	stateid->type = NFS4_DELEGATION_STATEID_TYPE;
437462306a36Sopenharmony_ci	return decode_stateid(xdr, stateid);
437562306a36Sopenharmony_ci}
437662306a36Sopenharmony_ci
437762306a36Sopenharmony_cistatic int decode_invalid_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
437862306a36Sopenharmony_ci{
437962306a36Sopenharmony_ci	nfs4_stateid dummy;
438062306a36Sopenharmony_ci
438162306a36Sopenharmony_ci	nfs4_stateid_copy(stateid, &invalid_stateid);
438262306a36Sopenharmony_ci	return decode_stateid(xdr, &dummy);
438362306a36Sopenharmony_ci}
438462306a36Sopenharmony_ci
438562306a36Sopenharmony_cistatic int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
438662306a36Sopenharmony_ci{
438762306a36Sopenharmony_ci	int status;
438862306a36Sopenharmony_ci
438962306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_CLOSE);
439062306a36Sopenharmony_ci	if (status != -EIO)
439162306a36Sopenharmony_ci		nfs_increment_open_seqid(status, res->seqid);
439262306a36Sopenharmony_ci	if (!status)
439362306a36Sopenharmony_ci		status = decode_invalid_stateid(xdr, &res->stateid);
439462306a36Sopenharmony_ci	return status;
439562306a36Sopenharmony_ci}
439662306a36Sopenharmony_ci
439762306a36Sopenharmony_cistatic int decode_verifier(struct xdr_stream *xdr, void *verifier)
439862306a36Sopenharmony_ci{
439962306a36Sopenharmony_ci	return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
440062306a36Sopenharmony_ci}
440162306a36Sopenharmony_ci
440262306a36Sopenharmony_cistatic int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
440362306a36Sopenharmony_ci{
440462306a36Sopenharmony_ci	return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE);
440562306a36Sopenharmony_ci}
440662306a36Sopenharmony_ci
440762306a36Sopenharmony_cistatic int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
440862306a36Sopenharmony_ci{
440962306a36Sopenharmony_ci	struct nfs_writeverf *verf = res->verf;
441062306a36Sopenharmony_ci	int status;
441162306a36Sopenharmony_ci
441262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_COMMIT);
441362306a36Sopenharmony_ci	if (!status)
441462306a36Sopenharmony_ci		status = decode_write_verifier(xdr, &verf->verifier);
441562306a36Sopenharmony_ci	if (!status)
441662306a36Sopenharmony_ci		verf->committed = NFS_FILE_SYNC;
441762306a36Sopenharmony_ci	return status;
441862306a36Sopenharmony_ci}
441962306a36Sopenharmony_ci
442062306a36Sopenharmony_cistatic int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
442162306a36Sopenharmony_ci{
442262306a36Sopenharmony_ci	__be32 *p;
442362306a36Sopenharmony_ci	uint32_t bmlen;
442462306a36Sopenharmony_ci	int status;
442562306a36Sopenharmony_ci
442662306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_CREATE);
442762306a36Sopenharmony_ci	if (status)
442862306a36Sopenharmony_ci		return status;
442962306a36Sopenharmony_ci	if ((status = decode_change_info(xdr, cinfo)))
443062306a36Sopenharmony_ci		return status;
443162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
443262306a36Sopenharmony_ci	if (unlikely(!p))
443362306a36Sopenharmony_ci		return -EIO;
443462306a36Sopenharmony_ci	bmlen = be32_to_cpup(p);
443562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, bmlen << 2);
443662306a36Sopenharmony_ci	if (likely(p))
443762306a36Sopenharmony_ci		return 0;
443862306a36Sopenharmony_ci	return -EIO;
443962306a36Sopenharmony_ci}
444062306a36Sopenharmony_ci
444162306a36Sopenharmony_cistatic int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
444262306a36Sopenharmony_ci{
444362306a36Sopenharmony_ci	unsigned int savep;
444462306a36Sopenharmony_ci	uint32_t attrlen, bitmap[3] = {0};
444562306a36Sopenharmony_ci	int status;
444662306a36Sopenharmony_ci
444762306a36Sopenharmony_ci	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
444862306a36Sopenharmony_ci		goto xdr_error;
444962306a36Sopenharmony_ci	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
445062306a36Sopenharmony_ci		goto xdr_error;
445162306a36Sopenharmony_ci	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
445262306a36Sopenharmony_ci		goto xdr_error;
445362306a36Sopenharmony_ci	if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
445462306a36Sopenharmony_ci		goto xdr_error;
445562306a36Sopenharmony_ci	if ((status = decode_attr_fh_expire_type(xdr, bitmap,
445662306a36Sopenharmony_ci						 &res->fh_expire_type)) != 0)
445762306a36Sopenharmony_ci		goto xdr_error;
445862306a36Sopenharmony_ci	if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
445962306a36Sopenharmony_ci		goto xdr_error;
446062306a36Sopenharmony_ci	if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
446162306a36Sopenharmony_ci		goto xdr_error;
446262306a36Sopenharmony_ci	if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
446362306a36Sopenharmony_ci		goto xdr_error;
446462306a36Sopenharmony_ci	if ((status = decode_attr_case_insensitive(xdr, bitmap, &res->case_insensitive)) != 0)
446562306a36Sopenharmony_ci		goto xdr_error;
446662306a36Sopenharmony_ci	if ((status = decode_attr_case_preserving(xdr, bitmap, &res->case_preserving)) != 0)
446762306a36Sopenharmony_ci		goto xdr_error;
446862306a36Sopenharmony_ci	if ((status = decode_attr_exclcreat_supported(xdr, bitmap,
446962306a36Sopenharmony_ci				res->exclcreat_bitmask)) != 0)
447062306a36Sopenharmony_ci		goto xdr_error;
447162306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
447262306a36Sopenharmony_cixdr_error:
447362306a36Sopenharmony_ci	dprintk("%s: xdr returned %d!\n", __func__, -status);
447462306a36Sopenharmony_ci	return status;
447562306a36Sopenharmony_ci}
447662306a36Sopenharmony_ci
447762306a36Sopenharmony_cistatic int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
447862306a36Sopenharmony_ci{
447962306a36Sopenharmony_ci	unsigned int savep;
448062306a36Sopenharmony_ci	uint32_t attrlen, bitmap[3] = {0};
448162306a36Sopenharmony_ci	int status;
448262306a36Sopenharmony_ci
448362306a36Sopenharmony_ci	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
448462306a36Sopenharmony_ci		goto xdr_error;
448562306a36Sopenharmony_ci	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
448662306a36Sopenharmony_ci		goto xdr_error;
448762306a36Sopenharmony_ci	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
448862306a36Sopenharmony_ci		goto xdr_error;
448962306a36Sopenharmony_ci
449062306a36Sopenharmony_ci	if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
449162306a36Sopenharmony_ci		goto xdr_error;
449262306a36Sopenharmony_ci	if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
449362306a36Sopenharmony_ci		goto xdr_error;
449462306a36Sopenharmony_ci	if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
449562306a36Sopenharmony_ci		goto xdr_error;
449662306a36Sopenharmony_ci
449762306a36Sopenharmony_ci	status = -EIO;
449862306a36Sopenharmony_ci	if (unlikely(bitmap[0]))
449962306a36Sopenharmony_ci		goto xdr_error;
450062306a36Sopenharmony_ci
450162306a36Sopenharmony_ci	if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
450262306a36Sopenharmony_ci		goto xdr_error;
450362306a36Sopenharmony_ci	if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
450462306a36Sopenharmony_ci		goto xdr_error;
450562306a36Sopenharmony_ci	if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
450662306a36Sopenharmony_ci		goto xdr_error;
450762306a36Sopenharmony_ci
450862306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
450962306a36Sopenharmony_cixdr_error:
451062306a36Sopenharmony_ci	dprintk("%s: xdr returned %d!\n", __func__, -status);
451162306a36Sopenharmony_ci	return status;
451262306a36Sopenharmony_ci}
451362306a36Sopenharmony_ci
451462306a36Sopenharmony_cistatic int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
451562306a36Sopenharmony_ci{
451662306a36Sopenharmony_ci	unsigned int savep;
451762306a36Sopenharmony_ci	uint32_t attrlen, bitmap[3] = {0};
451862306a36Sopenharmony_ci	int status;
451962306a36Sopenharmony_ci
452062306a36Sopenharmony_ci	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
452162306a36Sopenharmony_ci		goto xdr_error;
452262306a36Sopenharmony_ci	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
452362306a36Sopenharmony_ci		goto xdr_error;
452462306a36Sopenharmony_ci	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
452562306a36Sopenharmony_ci		goto xdr_error;
452662306a36Sopenharmony_ci
452762306a36Sopenharmony_ci	if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
452862306a36Sopenharmony_ci		goto xdr_error;
452962306a36Sopenharmony_ci	if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
453062306a36Sopenharmony_ci		goto xdr_error;
453162306a36Sopenharmony_ci
453262306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
453362306a36Sopenharmony_cixdr_error:
453462306a36Sopenharmony_ci	dprintk("%s: xdr returned %d!\n", __func__, -status);
453562306a36Sopenharmony_ci	return status;
453662306a36Sopenharmony_ci}
453762306a36Sopenharmony_ci
453862306a36Sopenharmony_cistatic int decode_threshold_hint(struct xdr_stream *xdr,
453962306a36Sopenharmony_ci				  uint32_t *bitmap,
454062306a36Sopenharmony_ci				  uint64_t *res,
454162306a36Sopenharmony_ci				  uint32_t hint_bit)
454262306a36Sopenharmony_ci{
454362306a36Sopenharmony_ci	__be32 *p;
454462306a36Sopenharmony_ci
454562306a36Sopenharmony_ci	*res = 0;
454662306a36Sopenharmony_ci	if (likely(bitmap[0] & hint_bit)) {
454762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
454862306a36Sopenharmony_ci		if (unlikely(!p))
454962306a36Sopenharmony_ci			return -EIO;
455062306a36Sopenharmony_ci		xdr_decode_hyper(p, res);
455162306a36Sopenharmony_ci	}
455262306a36Sopenharmony_ci	return 0;
455362306a36Sopenharmony_ci}
455462306a36Sopenharmony_ci
455562306a36Sopenharmony_cistatic int decode_first_threshold_item4(struct xdr_stream *xdr,
455662306a36Sopenharmony_ci					struct nfs4_threshold *res)
455762306a36Sopenharmony_ci{
455862306a36Sopenharmony_ci	__be32 *p;
455962306a36Sopenharmony_ci	unsigned int savep;
456062306a36Sopenharmony_ci	uint32_t bitmap[3] = {0,}, attrlen;
456162306a36Sopenharmony_ci	int status;
456262306a36Sopenharmony_ci
456362306a36Sopenharmony_ci	/* layout type */
456462306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
456562306a36Sopenharmony_ci	if (unlikely(!p))
456662306a36Sopenharmony_ci		return -EIO;
456762306a36Sopenharmony_ci	res->l_type = be32_to_cpup(p);
456862306a36Sopenharmony_ci
456962306a36Sopenharmony_ci	/* thi_hintset bitmap */
457062306a36Sopenharmony_ci	status = decode_attr_bitmap(xdr, bitmap);
457162306a36Sopenharmony_ci	if (status < 0)
457262306a36Sopenharmony_ci		goto xdr_error;
457362306a36Sopenharmony_ci
457462306a36Sopenharmony_ci	/* thi_hintlist length */
457562306a36Sopenharmony_ci	status = decode_attr_length(xdr, &attrlen, &savep);
457662306a36Sopenharmony_ci	if (status < 0)
457762306a36Sopenharmony_ci		goto xdr_error;
457862306a36Sopenharmony_ci	/* thi_hintlist */
457962306a36Sopenharmony_ci	status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD);
458062306a36Sopenharmony_ci	if (status < 0)
458162306a36Sopenharmony_ci		goto xdr_error;
458262306a36Sopenharmony_ci	status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR);
458362306a36Sopenharmony_ci	if (status < 0)
458462306a36Sopenharmony_ci		goto xdr_error;
458562306a36Sopenharmony_ci	status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz,
458662306a36Sopenharmony_ci				       THRESHOLD_RD_IO);
458762306a36Sopenharmony_ci	if (status < 0)
458862306a36Sopenharmony_ci		goto xdr_error;
458962306a36Sopenharmony_ci	status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz,
459062306a36Sopenharmony_ci				       THRESHOLD_WR_IO);
459162306a36Sopenharmony_ci	if (status < 0)
459262306a36Sopenharmony_ci		goto xdr_error;
459362306a36Sopenharmony_ci
459462306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
459562306a36Sopenharmony_ci	res->bm = bitmap[0];
459662306a36Sopenharmony_ci
459762306a36Sopenharmony_ci	dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n",
459862306a36Sopenharmony_ci		 __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz,
459962306a36Sopenharmony_ci		res->wr_io_sz);
460062306a36Sopenharmony_cixdr_error:
460162306a36Sopenharmony_ci	dprintk("%s ret=%d!\n", __func__, status);
460262306a36Sopenharmony_ci	return status;
460362306a36Sopenharmony_ci}
460462306a36Sopenharmony_ci
460562306a36Sopenharmony_ci/*
460662306a36Sopenharmony_ci * Thresholds on pNFS direct I/O vrs MDS I/O
460762306a36Sopenharmony_ci */
460862306a36Sopenharmony_cistatic int decode_attr_mdsthreshold(struct xdr_stream *xdr,
460962306a36Sopenharmony_ci				    uint32_t *bitmap,
461062306a36Sopenharmony_ci				    struct nfs4_threshold *res)
461162306a36Sopenharmony_ci{
461262306a36Sopenharmony_ci	__be32 *p;
461362306a36Sopenharmony_ci	int status = 0;
461462306a36Sopenharmony_ci	uint32_t num;
461562306a36Sopenharmony_ci
461662306a36Sopenharmony_ci	if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
461762306a36Sopenharmony_ci		return -EIO;
461862306a36Sopenharmony_ci	if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) {
461962306a36Sopenharmony_ci		/* Did the server return an unrequested attribute? */
462062306a36Sopenharmony_ci		if (unlikely(res == NULL))
462162306a36Sopenharmony_ci			return -EREMOTEIO;
462262306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
462362306a36Sopenharmony_ci		if (unlikely(!p))
462462306a36Sopenharmony_ci			return -EIO;
462562306a36Sopenharmony_ci		num = be32_to_cpup(p);
462662306a36Sopenharmony_ci		if (num == 0)
462762306a36Sopenharmony_ci			return 0;
462862306a36Sopenharmony_ci		if (num > 1)
462962306a36Sopenharmony_ci			printk(KERN_INFO "%s: Warning: Multiple pNFS layout "
463062306a36Sopenharmony_ci				"drivers per filesystem not supported\n",
463162306a36Sopenharmony_ci				__func__);
463262306a36Sopenharmony_ci
463362306a36Sopenharmony_ci		status = decode_first_threshold_item4(xdr, res);
463462306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
463562306a36Sopenharmony_ci	}
463662306a36Sopenharmony_ci	return status;
463762306a36Sopenharmony_ci}
463862306a36Sopenharmony_ci
463962306a36Sopenharmony_cistatic int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
464062306a36Sopenharmony_ci		struct nfs_fattr *fattr, struct nfs_fh *fh,
464162306a36Sopenharmony_ci		struct nfs4_fs_locations *fs_loc, const struct nfs_server *server)
464262306a36Sopenharmony_ci{
464362306a36Sopenharmony_ci	int status;
464462306a36Sopenharmony_ci	umode_t fmode = 0;
464562306a36Sopenharmony_ci	uint32_t type;
464662306a36Sopenharmony_ci	int32_t err;
464762306a36Sopenharmony_ci
464862306a36Sopenharmony_ci	status = decode_attr_type(xdr, bitmap, &type);
464962306a36Sopenharmony_ci	if (status < 0)
465062306a36Sopenharmony_ci		goto xdr_error;
465162306a36Sopenharmony_ci	fattr->mode = 0;
465262306a36Sopenharmony_ci	if (status != 0) {
465362306a36Sopenharmony_ci		fattr->mode |= nfs_type2fmt[type];
465462306a36Sopenharmony_ci		fattr->valid |= status;
465562306a36Sopenharmony_ci	}
465662306a36Sopenharmony_ci
465762306a36Sopenharmony_ci	status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
465862306a36Sopenharmony_ci	if (status < 0)
465962306a36Sopenharmony_ci		goto xdr_error;
466062306a36Sopenharmony_ci	fattr->valid |= status;
466162306a36Sopenharmony_ci
466262306a36Sopenharmony_ci	status = decode_attr_size(xdr, bitmap, &fattr->size);
466362306a36Sopenharmony_ci	if (status < 0)
466462306a36Sopenharmony_ci		goto xdr_error;
466562306a36Sopenharmony_ci	fattr->valid |= status;
466662306a36Sopenharmony_ci
466762306a36Sopenharmony_ci	status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
466862306a36Sopenharmony_ci	if (status < 0)
466962306a36Sopenharmony_ci		goto xdr_error;
467062306a36Sopenharmony_ci	fattr->valid |= status;
467162306a36Sopenharmony_ci
467262306a36Sopenharmony_ci	err = 0;
467362306a36Sopenharmony_ci	status = decode_attr_error(xdr, bitmap, &err);
467462306a36Sopenharmony_ci	if (status < 0)
467562306a36Sopenharmony_ci		goto xdr_error;
467662306a36Sopenharmony_ci
467762306a36Sopenharmony_ci	status = decode_attr_filehandle(xdr, bitmap, fh);
467862306a36Sopenharmony_ci	if (status < 0)
467962306a36Sopenharmony_ci		goto xdr_error;
468062306a36Sopenharmony_ci
468162306a36Sopenharmony_ci	status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
468262306a36Sopenharmony_ci	if (status < 0)
468362306a36Sopenharmony_ci		goto xdr_error;
468462306a36Sopenharmony_ci	fattr->valid |= status;
468562306a36Sopenharmony_ci
468662306a36Sopenharmony_ci	status = decode_attr_fs_locations(xdr, bitmap, fs_loc);
468762306a36Sopenharmony_ci	if (status < 0)
468862306a36Sopenharmony_ci		goto xdr_error;
468962306a36Sopenharmony_ci	fattr->valid |= status;
469062306a36Sopenharmony_ci
469162306a36Sopenharmony_ci	status = -EIO;
469262306a36Sopenharmony_ci	if (unlikely(bitmap[0]))
469362306a36Sopenharmony_ci		goto xdr_error;
469462306a36Sopenharmony_ci
469562306a36Sopenharmony_ci	status = decode_attr_mode(xdr, bitmap, &fmode);
469662306a36Sopenharmony_ci	if (status < 0)
469762306a36Sopenharmony_ci		goto xdr_error;
469862306a36Sopenharmony_ci	if (status != 0) {
469962306a36Sopenharmony_ci		fattr->mode |= fmode;
470062306a36Sopenharmony_ci		fattr->valid |= status;
470162306a36Sopenharmony_ci	}
470262306a36Sopenharmony_ci
470362306a36Sopenharmony_ci	status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
470462306a36Sopenharmony_ci	if (status < 0)
470562306a36Sopenharmony_ci		goto xdr_error;
470662306a36Sopenharmony_ci	fattr->valid |= status;
470762306a36Sopenharmony_ci
470862306a36Sopenharmony_ci	status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name);
470962306a36Sopenharmony_ci	if (status < 0)
471062306a36Sopenharmony_ci		goto xdr_error;
471162306a36Sopenharmony_ci	fattr->valid |= status;
471262306a36Sopenharmony_ci
471362306a36Sopenharmony_ci	status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name);
471462306a36Sopenharmony_ci	if (status < 0)
471562306a36Sopenharmony_ci		goto xdr_error;
471662306a36Sopenharmony_ci	fattr->valid |= status;
471762306a36Sopenharmony_ci
471862306a36Sopenharmony_ci	status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
471962306a36Sopenharmony_ci	if (status < 0)
472062306a36Sopenharmony_ci		goto xdr_error;
472162306a36Sopenharmony_ci	fattr->valid |= status;
472262306a36Sopenharmony_ci
472362306a36Sopenharmony_ci	status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
472462306a36Sopenharmony_ci	if (status < 0)
472562306a36Sopenharmony_ci		goto xdr_error;
472662306a36Sopenharmony_ci	fattr->valid |= status;
472762306a36Sopenharmony_ci
472862306a36Sopenharmony_ci	status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
472962306a36Sopenharmony_ci	if (status < 0)
473062306a36Sopenharmony_ci		goto xdr_error;
473162306a36Sopenharmony_ci	fattr->valid |= status;
473262306a36Sopenharmony_ci
473362306a36Sopenharmony_ci	status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
473462306a36Sopenharmony_ci	if (status < 0)
473562306a36Sopenharmony_ci		goto xdr_error;
473662306a36Sopenharmony_ci	fattr->valid |= status;
473762306a36Sopenharmony_ci
473862306a36Sopenharmony_ci	status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
473962306a36Sopenharmony_ci	if (status < 0)
474062306a36Sopenharmony_ci		goto xdr_error;
474162306a36Sopenharmony_ci	fattr->valid |= status;
474262306a36Sopenharmony_ci
474362306a36Sopenharmony_ci	status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid);
474462306a36Sopenharmony_ci	if (status < 0)
474562306a36Sopenharmony_ci		goto xdr_error;
474662306a36Sopenharmony_ci	fattr->valid |= status;
474762306a36Sopenharmony_ci
474862306a36Sopenharmony_ci	status = -EIO;
474962306a36Sopenharmony_ci	if (unlikely(bitmap[1]))
475062306a36Sopenharmony_ci		goto xdr_error;
475162306a36Sopenharmony_ci
475262306a36Sopenharmony_ci	status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold);
475362306a36Sopenharmony_ci	if (status < 0)
475462306a36Sopenharmony_ci		goto xdr_error;
475562306a36Sopenharmony_ci
475662306a36Sopenharmony_ci	status = decode_attr_security_label(xdr, bitmap, fattr->label);
475762306a36Sopenharmony_ci	if (status < 0)
475862306a36Sopenharmony_ci		goto xdr_error;
475962306a36Sopenharmony_ci	fattr->valid |= status;
476062306a36Sopenharmony_ci
476162306a36Sopenharmony_cixdr_error:
476262306a36Sopenharmony_ci	dprintk("%s: xdr returned %d\n", __func__, -status);
476362306a36Sopenharmony_ci	return status;
476462306a36Sopenharmony_ci}
476562306a36Sopenharmony_ci
476662306a36Sopenharmony_cistatic int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
476762306a36Sopenharmony_ci		struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
476862306a36Sopenharmony_ci		const struct nfs_server *server)
476962306a36Sopenharmony_ci{
477062306a36Sopenharmony_ci	unsigned int savep;
477162306a36Sopenharmony_ci	uint32_t attrlen,
477262306a36Sopenharmony_ci		 bitmap[3] = {0};
477362306a36Sopenharmony_ci	int status;
477462306a36Sopenharmony_ci
477562306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_GETATTR);
477662306a36Sopenharmony_ci	if (status < 0)
477762306a36Sopenharmony_ci		goto xdr_error;
477862306a36Sopenharmony_ci
477962306a36Sopenharmony_ci	status = decode_attr_bitmap(xdr, bitmap);
478062306a36Sopenharmony_ci	if (status < 0)
478162306a36Sopenharmony_ci		goto xdr_error;
478262306a36Sopenharmony_ci
478362306a36Sopenharmony_ci	status = decode_attr_length(xdr, &attrlen, &savep);
478462306a36Sopenharmony_ci	if (status < 0)
478562306a36Sopenharmony_ci		goto xdr_error;
478662306a36Sopenharmony_ci
478762306a36Sopenharmony_ci	status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc, server);
478862306a36Sopenharmony_ci	if (status < 0)
478962306a36Sopenharmony_ci		goto xdr_error;
479062306a36Sopenharmony_ci
479162306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
479262306a36Sopenharmony_cixdr_error:
479362306a36Sopenharmony_ci	dprintk("%s: xdr returned %d\n", __func__, -status);
479462306a36Sopenharmony_ci	return status;
479562306a36Sopenharmony_ci}
479662306a36Sopenharmony_ci
479762306a36Sopenharmony_cistatic int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
479862306a36Sopenharmony_ci		const struct nfs_server *server)
479962306a36Sopenharmony_ci{
480062306a36Sopenharmony_ci	return decode_getfattr_generic(xdr, fattr, NULL, NULL, server);
480162306a36Sopenharmony_ci}
480262306a36Sopenharmony_ci
480362306a36Sopenharmony_ci/*
480462306a36Sopenharmony_ci * Decode potentially multiple layout types.
480562306a36Sopenharmony_ci */
480662306a36Sopenharmony_cistatic int decode_pnfs_layout_types(struct xdr_stream *xdr,
480762306a36Sopenharmony_ci				    struct nfs_fsinfo *fsinfo)
480862306a36Sopenharmony_ci{
480962306a36Sopenharmony_ci	__be32 *p;
481062306a36Sopenharmony_ci	uint32_t i;
481162306a36Sopenharmony_ci
481262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
481362306a36Sopenharmony_ci	if (unlikely(!p))
481462306a36Sopenharmony_ci		return -EIO;
481562306a36Sopenharmony_ci	fsinfo->nlayouttypes = be32_to_cpup(p);
481662306a36Sopenharmony_ci
481762306a36Sopenharmony_ci	/* pNFS is not supported by the underlying file system */
481862306a36Sopenharmony_ci	if (fsinfo->nlayouttypes == 0)
481962306a36Sopenharmony_ci		return 0;
482062306a36Sopenharmony_ci
482162306a36Sopenharmony_ci	/* Decode and set first layout type, move xdr->p past unused types */
482262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4);
482362306a36Sopenharmony_ci	if (unlikely(!p))
482462306a36Sopenharmony_ci		return -EIO;
482562306a36Sopenharmony_ci
482662306a36Sopenharmony_ci	/* If we get too many, then just cap it at the max */
482762306a36Sopenharmony_ci	if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) {
482862306a36Sopenharmony_ci		printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n",
482962306a36Sopenharmony_ci			__func__, fsinfo->nlayouttypes);
483062306a36Sopenharmony_ci		fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES;
483162306a36Sopenharmony_ci	}
483262306a36Sopenharmony_ci
483362306a36Sopenharmony_ci	for(i = 0; i < fsinfo->nlayouttypes; ++i)
483462306a36Sopenharmony_ci		fsinfo->layouttype[i] = be32_to_cpup(p++);
483562306a36Sopenharmony_ci	return 0;
483662306a36Sopenharmony_ci}
483762306a36Sopenharmony_ci
483862306a36Sopenharmony_ci/*
483962306a36Sopenharmony_ci * The type of file system exported.
484062306a36Sopenharmony_ci * Note we must ensure that layouttype is set in any non-error case.
484162306a36Sopenharmony_ci */
484262306a36Sopenharmony_cistatic int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
484362306a36Sopenharmony_ci				struct nfs_fsinfo *fsinfo)
484462306a36Sopenharmony_ci{
484562306a36Sopenharmony_ci	int status = 0;
484662306a36Sopenharmony_ci
484762306a36Sopenharmony_ci	dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
484862306a36Sopenharmony_ci	if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
484962306a36Sopenharmony_ci		return -EIO;
485062306a36Sopenharmony_ci	if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
485162306a36Sopenharmony_ci		status = decode_pnfs_layout_types(xdr, fsinfo);
485262306a36Sopenharmony_ci		bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
485362306a36Sopenharmony_ci	}
485462306a36Sopenharmony_ci	return status;
485562306a36Sopenharmony_ci}
485662306a36Sopenharmony_ci
485762306a36Sopenharmony_ci/*
485862306a36Sopenharmony_ci * The prefered block size for layout directed io
485962306a36Sopenharmony_ci */
486062306a36Sopenharmony_cistatic int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
486162306a36Sopenharmony_ci				      uint32_t *res)
486262306a36Sopenharmony_ci{
486362306a36Sopenharmony_ci	__be32 *p;
486462306a36Sopenharmony_ci
486562306a36Sopenharmony_ci	dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
486662306a36Sopenharmony_ci	*res = 0;
486762306a36Sopenharmony_ci	if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
486862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
486962306a36Sopenharmony_ci		if (unlikely(!p))
487062306a36Sopenharmony_ci			return -EIO;
487162306a36Sopenharmony_ci		*res = be32_to_cpup(p);
487262306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
487362306a36Sopenharmony_ci	}
487462306a36Sopenharmony_ci	return 0;
487562306a36Sopenharmony_ci}
487662306a36Sopenharmony_ci
487762306a36Sopenharmony_ci/*
487862306a36Sopenharmony_ci * The granularity of a CLONE operation.
487962306a36Sopenharmony_ci */
488062306a36Sopenharmony_cistatic int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
488162306a36Sopenharmony_ci				     uint32_t *res)
488262306a36Sopenharmony_ci{
488362306a36Sopenharmony_ci	__be32 *p;
488462306a36Sopenharmony_ci
488562306a36Sopenharmony_ci	dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
488662306a36Sopenharmony_ci	*res = 0;
488762306a36Sopenharmony_ci	if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) {
488862306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
488962306a36Sopenharmony_ci		if (unlikely(!p))
489062306a36Sopenharmony_ci			return -EIO;
489162306a36Sopenharmony_ci		*res = be32_to_cpup(p);
489262306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE;
489362306a36Sopenharmony_ci	}
489462306a36Sopenharmony_ci	return 0;
489562306a36Sopenharmony_ci}
489662306a36Sopenharmony_ci
489762306a36Sopenharmony_cistatic int decode_attr_change_attr_type(struct xdr_stream *xdr,
489862306a36Sopenharmony_ci					uint32_t *bitmap,
489962306a36Sopenharmony_ci					enum nfs4_change_attr_type *res)
490062306a36Sopenharmony_ci{
490162306a36Sopenharmony_ci	u32 tmp = NFS4_CHANGE_TYPE_IS_UNDEFINED;
490262306a36Sopenharmony_ci
490362306a36Sopenharmony_ci	dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
490462306a36Sopenharmony_ci	if (bitmap[2] & FATTR4_WORD2_CHANGE_ATTR_TYPE) {
490562306a36Sopenharmony_ci		if (xdr_stream_decode_u32(xdr, &tmp))
490662306a36Sopenharmony_ci			return -EIO;
490762306a36Sopenharmony_ci		bitmap[2] &= ~FATTR4_WORD2_CHANGE_ATTR_TYPE;
490862306a36Sopenharmony_ci	}
490962306a36Sopenharmony_ci
491062306a36Sopenharmony_ci	switch(tmp) {
491162306a36Sopenharmony_ci	case NFS4_CHANGE_TYPE_IS_MONOTONIC_INCR:
491262306a36Sopenharmony_ci	case NFS4_CHANGE_TYPE_IS_VERSION_COUNTER:
491362306a36Sopenharmony_ci	case NFS4_CHANGE_TYPE_IS_VERSION_COUNTER_NOPNFS:
491462306a36Sopenharmony_ci	case NFS4_CHANGE_TYPE_IS_TIME_METADATA:
491562306a36Sopenharmony_ci		*res = tmp;
491662306a36Sopenharmony_ci		break;
491762306a36Sopenharmony_ci	default:
491862306a36Sopenharmony_ci		*res = NFS4_CHANGE_TYPE_IS_UNDEFINED;
491962306a36Sopenharmony_ci	}
492062306a36Sopenharmony_ci	return 0;
492162306a36Sopenharmony_ci}
492262306a36Sopenharmony_ci
492362306a36Sopenharmony_cistatic int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
492462306a36Sopenharmony_ci{
492562306a36Sopenharmony_ci	unsigned int savep;
492662306a36Sopenharmony_ci	uint32_t attrlen, bitmap[3];
492762306a36Sopenharmony_ci	int status;
492862306a36Sopenharmony_ci
492962306a36Sopenharmony_ci	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
493062306a36Sopenharmony_ci		goto xdr_error;
493162306a36Sopenharmony_ci	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
493262306a36Sopenharmony_ci		goto xdr_error;
493362306a36Sopenharmony_ci	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
493462306a36Sopenharmony_ci		goto xdr_error;
493562306a36Sopenharmony_ci
493662306a36Sopenharmony_ci	fsinfo->rtmult = fsinfo->wtmult = 512;	/* ??? */
493762306a36Sopenharmony_ci
493862306a36Sopenharmony_ci	if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
493962306a36Sopenharmony_ci		goto xdr_error;
494062306a36Sopenharmony_ci	if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
494162306a36Sopenharmony_ci		goto xdr_error;
494262306a36Sopenharmony_ci	if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
494362306a36Sopenharmony_ci		goto xdr_error;
494462306a36Sopenharmony_ci	fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
494562306a36Sopenharmony_ci	if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
494662306a36Sopenharmony_ci		goto xdr_error;
494762306a36Sopenharmony_ci	fsinfo->wtpref = fsinfo->wtmax;
494862306a36Sopenharmony_ci
494962306a36Sopenharmony_ci	status = -EIO;
495062306a36Sopenharmony_ci	if (unlikely(bitmap[0]))
495162306a36Sopenharmony_ci		goto xdr_error;
495262306a36Sopenharmony_ci
495362306a36Sopenharmony_ci	status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
495462306a36Sopenharmony_ci	if (status != 0)
495562306a36Sopenharmony_ci		goto xdr_error;
495662306a36Sopenharmony_ci	status = decode_attr_pnfstype(xdr, bitmap, fsinfo);
495762306a36Sopenharmony_ci	if (status != 0)
495862306a36Sopenharmony_ci		goto xdr_error;
495962306a36Sopenharmony_ci
496062306a36Sopenharmony_ci	status = -EIO;
496162306a36Sopenharmony_ci	if (unlikely(bitmap[1]))
496262306a36Sopenharmony_ci		goto xdr_error;
496362306a36Sopenharmony_ci
496462306a36Sopenharmony_ci	status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize);
496562306a36Sopenharmony_ci	if (status)
496662306a36Sopenharmony_ci		goto xdr_error;
496762306a36Sopenharmony_ci	status = decode_attr_clone_blksize(xdr, bitmap, &fsinfo->clone_blksize);
496862306a36Sopenharmony_ci	if (status)
496962306a36Sopenharmony_ci		goto xdr_error;
497062306a36Sopenharmony_ci
497162306a36Sopenharmony_ci	status = decode_attr_change_attr_type(xdr, bitmap,
497262306a36Sopenharmony_ci					      &fsinfo->change_attr_type);
497362306a36Sopenharmony_ci	if (status)
497462306a36Sopenharmony_ci		goto xdr_error;
497562306a36Sopenharmony_ci
497662306a36Sopenharmony_ci	status = decode_attr_xattrsupport(xdr, bitmap,
497762306a36Sopenharmony_ci					  &fsinfo->xattr_support);
497862306a36Sopenharmony_ci	if (status)
497962306a36Sopenharmony_ci		goto xdr_error;
498062306a36Sopenharmony_ci
498162306a36Sopenharmony_ci	status = verify_attr_len(xdr, savep, attrlen);
498262306a36Sopenharmony_cixdr_error:
498362306a36Sopenharmony_ci	dprintk("%s: xdr returned %d!\n", __func__, -status);
498462306a36Sopenharmony_ci	return status;
498562306a36Sopenharmony_ci}
498662306a36Sopenharmony_ci
498762306a36Sopenharmony_cistatic int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
498862306a36Sopenharmony_ci{
498962306a36Sopenharmony_ci	__be32 *p;
499062306a36Sopenharmony_ci	uint32_t len;
499162306a36Sopenharmony_ci	int status;
499262306a36Sopenharmony_ci
499362306a36Sopenharmony_ci	/* Zero handle first to allow comparisons */
499462306a36Sopenharmony_ci	memset(fh, 0, sizeof(*fh));
499562306a36Sopenharmony_ci
499662306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_GETFH);
499762306a36Sopenharmony_ci	if (status)
499862306a36Sopenharmony_ci		return status;
499962306a36Sopenharmony_ci
500062306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
500162306a36Sopenharmony_ci	if (unlikely(!p))
500262306a36Sopenharmony_ci		return -EIO;
500362306a36Sopenharmony_ci	len = be32_to_cpup(p);
500462306a36Sopenharmony_ci	if (len > NFS4_FHSIZE || len == 0) {
500562306a36Sopenharmony_ci		trace_nfs4_xdr_bad_filehandle(xdr, OP_GETFH, NFS4ERR_BADHANDLE);
500662306a36Sopenharmony_ci		return -EREMOTEIO;
500762306a36Sopenharmony_ci	}
500862306a36Sopenharmony_ci	fh->size = len;
500962306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, len);
501062306a36Sopenharmony_ci	if (unlikely(!p))
501162306a36Sopenharmony_ci		return -EIO;
501262306a36Sopenharmony_ci	memcpy(fh->data, p, len);
501362306a36Sopenharmony_ci	return 0;
501462306a36Sopenharmony_ci}
501562306a36Sopenharmony_ci
501662306a36Sopenharmony_cistatic int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
501762306a36Sopenharmony_ci{
501862306a36Sopenharmony_ci	int status;
501962306a36Sopenharmony_ci
502062306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LINK);
502162306a36Sopenharmony_ci	if (status)
502262306a36Sopenharmony_ci		return status;
502362306a36Sopenharmony_ci	return decode_change_info(xdr, cinfo);
502462306a36Sopenharmony_ci}
502562306a36Sopenharmony_ci
502662306a36Sopenharmony_ci/*
502762306a36Sopenharmony_ci * We create the owner, so we know a proper owner.id length is 4.
502862306a36Sopenharmony_ci */
502962306a36Sopenharmony_cistatic int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
503062306a36Sopenharmony_ci{
503162306a36Sopenharmony_ci	uint64_t offset, length, clientid;
503262306a36Sopenharmony_ci	__be32 *p;
503362306a36Sopenharmony_ci	uint32_t namelen, type;
503462306a36Sopenharmony_ci
503562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
503662306a36Sopenharmony_ci	if (unlikely(!p))
503762306a36Sopenharmony_ci		return -EIO;
503862306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
503962306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &length);
504062306a36Sopenharmony_ci	type = be32_to_cpup(p++); /* 4 byte read */
504162306a36Sopenharmony_ci	if (fl != NULL) { /* manipulate file lock */
504262306a36Sopenharmony_ci		fl->fl_start = (loff_t)offset;
504362306a36Sopenharmony_ci		fl->fl_end = fl->fl_start + (loff_t)length - 1;
504462306a36Sopenharmony_ci		if (length == ~(uint64_t)0)
504562306a36Sopenharmony_ci			fl->fl_end = OFFSET_MAX;
504662306a36Sopenharmony_ci		fl->fl_type = F_WRLCK;
504762306a36Sopenharmony_ci		if (type & 1)
504862306a36Sopenharmony_ci			fl->fl_type = F_RDLCK;
504962306a36Sopenharmony_ci		fl->fl_pid = 0;
505062306a36Sopenharmony_ci	}
505162306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
505262306a36Sopenharmony_ci	namelen = be32_to_cpup(p); /* read 4 bytes */  /* have read all 32 bytes now */
505362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, namelen); /* variable size field */
505462306a36Sopenharmony_ci	if (likely(!p))
505562306a36Sopenharmony_ci		return -EIO;
505662306a36Sopenharmony_ci	return -NFS4ERR_DENIED;
505762306a36Sopenharmony_ci}
505862306a36Sopenharmony_ci
505962306a36Sopenharmony_cistatic int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
506062306a36Sopenharmony_ci{
506162306a36Sopenharmony_ci	int status;
506262306a36Sopenharmony_ci
506362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LOCK);
506462306a36Sopenharmony_ci	if (status == -EIO)
506562306a36Sopenharmony_ci		goto out;
506662306a36Sopenharmony_ci	if (status == 0) {
506762306a36Sopenharmony_ci		status = decode_lock_stateid(xdr, &res->stateid);
506862306a36Sopenharmony_ci		if (unlikely(status))
506962306a36Sopenharmony_ci			goto out;
507062306a36Sopenharmony_ci	} else if (status == -NFS4ERR_DENIED)
507162306a36Sopenharmony_ci		status = decode_lock_denied(xdr, NULL);
507262306a36Sopenharmony_ci	if (res->open_seqid != NULL)
507362306a36Sopenharmony_ci		nfs_increment_open_seqid(status, res->open_seqid);
507462306a36Sopenharmony_ci	nfs_increment_lock_seqid(status, res->lock_seqid);
507562306a36Sopenharmony_ciout:
507662306a36Sopenharmony_ci	return status;
507762306a36Sopenharmony_ci}
507862306a36Sopenharmony_ci
507962306a36Sopenharmony_cistatic int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
508062306a36Sopenharmony_ci{
508162306a36Sopenharmony_ci	int status;
508262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LOCKT);
508362306a36Sopenharmony_ci	if (status == -NFS4ERR_DENIED)
508462306a36Sopenharmony_ci		return decode_lock_denied(xdr, res->denied);
508562306a36Sopenharmony_ci	return status;
508662306a36Sopenharmony_ci}
508762306a36Sopenharmony_ci
508862306a36Sopenharmony_cistatic int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
508962306a36Sopenharmony_ci{
509062306a36Sopenharmony_ci	int status;
509162306a36Sopenharmony_ci
509262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LOCKU);
509362306a36Sopenharmony_ci	if (status != -EIO)
509462306a36Sopenharmony_ci		nfs_increment_lock_seqid(status, res->seqid);
509562306a36Sopenharmony_ci	if (status == 0)
509662306a36Sopenharmony_ci		status = decode_lock_stateid(xdr, &res->stateid);
509762306a36Sopenharmony_ci	return status;
509862306a36Sopenharmony_ci}
509962306a36Sopenharmony_ci
510062306a36Sopenharmony_cistatic int decode_release_lockowner(struct xdr_stream *xdr)
510162306a36Sopenharmony_ci{
510262306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
510362306a36Sopenharmony_ci}
510462306a36Sopenharmony_ci
510562306a36Sopenharmony_cistatic int decode_lookup(struct xdr_stream *xdr)
510662306a36Sopenharmony_ci{
510762306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_LOOKUP);
510862306a36Sopenharmony_ci}
510962306a36Sopenharmony_ci
511062306a36Sopenharmony_cistatic int decode_lookupp(struct xdr_stream *xdr)
511162306a36Sopenharmony_ci{
511262306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_LOOKUPP);
511362306a36Sopenharmony_ci}
511462306a36Sopenharmony_ci
511562306a36Sopenharmony_ci/* This is too sick! */
511662306a36Sopenharmony_cistatic int decode_space_limit(struct xdr_stream *xdr,
511762306a36Sopenharmony_ci		unsigned long *pagemod_limit)
511862306a36Sopenharmony_ci{
511962306a36Sopenharmony_ci	__be32 *p;
512062306a36Sopenharmony_ci	uint32_t limit_type, nblocks, blocksize;
512162306a36Sopenharmony_ci	u64 maxsize = 0;
512262306a36Sopenharmony_ci
512362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 12);
512462306a36Sopenharmony_ci	if (unlikely(!p))
512562306a36Sopenharmony_ci		return -EIO;
512662306a36Sopenharmony_ci	limit_type = be32_to_cpup(p++);
512762306a36Sopenharmony_ci	switch (limit_type) {
512862306a36Sopenharmony_ci	case NFS4_LIMIT_SIZE:
512962306a36Sopenharmony_ci		xdr_decode_hyper(p, &maxsize);
513062306a36Sopenharmony_ci		break;
513162306a36Sopenharmony_ci	case NFS4_LIMIT_BLOCKS:
513262306a36Sopenharmony_ci		nblocks = be32_to_cpup(p++);
513362306a36Sopenharmony_ci		blocksize = be32_to_cpup(p);
513462306a36Sopenharmony_ci		maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
513562306a36Sopenharmony_ci	}
513662306a36Sopenharmony_ci	maxsize >>= PAGE_SHIFT;
513762306a36Sopenharmony_ci	*pagemod_limit = min_t(u64, maxsize, ULONG_MAX);
513862306a36Sopenharmony_ci	return 0;
513962306a36Sopenharmony_ci}
514062306a36Sopenharmony_ci
514162306a36Sopenharmony_cistatic int decode_rw_delegation(struct xdr_stream *xdr,
514262306a36Sopenharmony_ci		uint32_t delegation_type,
514362306a36Sopenharmony_ci		struct nfs_openres *res)
514462306a36Sopenharmony_ci{
514562306a36Sopenharmony_ci	__be32 *p;
514662306a36Sopenharmony_ci	int status;
514762306a36Sopenharmony_ci
514862306a36Sopenharmony_ci	status = decode_delegation_stateid(xdr, &res->delegation);
514962306a36Sopenharmony_ci	if (unlikely(status))
515062306a36Sopenharmony_ci		return status;
515162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
515262306a36Sopenharmony_ci	if (unlikely(!p))
515362306a36Sopenharmony_ci		return -EIO;
515462306a36Sopenharmony_ci	res->do_recall = be32_to_cpup(p);
515562306a36Sopenharmony_ci
515662306a36Sopenharmony_ci	switch (delegation_type) {
515762306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_READ:
515862306a36Sopenharmony_ci		res->delegation_type = FMODE_READ;
515962306a36Sopenharmony_ci		break;
516062306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_WRITE:
516162306a36Sopenharmony_ci		res->delegation_type = FMODE_WRITE|FMODE_READ;
516262306a36Sopenharmony_ci		if (decode_space_limit(xdr, &res->pagemod_limit) < 0)
516362306a36Sopenharmony_ci				return -EIO;
516462306a36Sopenharmony_ci	}
516562306a36Sopenharmony_ci	return decode_ace(xdr, NULL);
516662306a36Sopenharmony_ci}
516762306a36Sopenharmony_ci
516862306a36Sopenharmony_cistatic int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
516962306a36Sopenharmony_ci{
517062306a36Sopenharmony_ci	__be32 *p;
517162306a36Sopenharmony_ci	uint32_t why_no_delegation;
517262306a36Sopenharmony_ci
517362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
517462306a36Sopenharmony_ci	if (unlikely(!p))
517562306a36Sopenharmony_ci		return -EIO;
517662306a36Sopenharmony_ci	why_no_delegation = be32_to_cpup(p);
517762306a36Sopenharmony_ci	switch (why_no_delegation) {
517862306a36Sopenharmony_ci		case WND4_CONTENTION:
517962306a36Sopenharmony_ci		case WND4_RESOURCE:
518062306a36Sopenharmony_ci			xdr_inline_decode(xdr, 4);
518162306a36Sopenharmony_ci			/* Ignore for now */
518262306a36Sopenharmony_ci	}
518362306a36Sopenharmony_ci	return 0;
518462306a36Sopenharmony_ci}
518562306a36Sopenharmony_ci
518662306a36Sopenharmony_cistatic int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
518762306a36Sopenharmony_ci{
518862306a36Sopenharmony_ci	__be32 *p;
518962306a36Sopenharmony_ci	uint32_t delegation_type;
519062306a36Sopenharmony_ci
519162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
519262306a36Sopenharmony_ci	if (unlikely(!p))
519362306a36Sopenharmony_ci		return -EIO;
519462306a36Sopenharmony_ci	delegation_type = be32_to_cpup(p);
519562306a36Sopenharmony_ci	res->delegation_type = 0;
519662306a36Sopenharmony_ci	switch (delegation_type) {
519762306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_NONE:
519862306a36Sopenharmony_ci		return 0;
519962306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_READ:
520062306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_WRITE:
520162306a36Sopenharmony_ci		return decode_rw_delegation(xdr, delegation_type, res);
520262306a36Sopenharmony_ci	case NFS4_OPEN_DELEGATE_NONE_EXT:
520362306a36Sopenharmony_ci		return decode_no_delegation(xdr, res);
520462306a36Sopenharmony_ci	}
520562306a36Sopenharmony_ci	return -EIO;
520662306a36Sopenharmony_ci}
520762306a36Sopenharmony_ci
520862306a36Sopenharmony_cistatic int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
520962306a36Sopenharmony_ci{
521062306a36Sopenharmony_ci	__be32 *p;
521162306a36Sopenharmony_ci	uint32_t savewords, bmlen, i;
521262306a36Sopenharmony_ci	int status;
521362306a36Sopenharmony_ci
521462306a36Sopenharmony_ci	if (!__decode_op_hdr(xdr, OP_OPEN, &status))
521562306a36Sopenharmony_ci		return status;
521662306a36Sopenharmony_ci	nfs_increment_open_seqid(status, res->seqid);
521762306a36Sopenharmony_ci	if (status)
521862306a36Sopenharmony_ci		return status;
521962306a36Sopenharmony_ci	status = decode_open_stateid(xdr, &res->stateid);
522062306a36Sopenharmony_ci	if (unlikely(status))
522162306a36Sopenharmony_ci		return status;
522262306a36Sopenharmony_ci
522362306a36Sopenharmony_ci	decode_change_info(xdr, &res->cinfo);
522462306a36Sopenharmony_ci
522562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
522662306a36Sopenharmony_ci	if (unlikely(!p))
522762306a36Sopenharmony_ci		return -EIO;
522862306a36Sopenharmony_ci	res->rflags = be32_to_cpup(p++);
522962306a36Sopenharmony_ci	bmlen = be32_to_cpup(p);
523062306a36Sopenharmony_ci	if (bmlen > 10)
523162306a36Sopenharmony_ci		goto xdr_error;
523262306a36Sopenharmony_ci
523362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, bmlen << 2);
523462306a36Sopenharmony_ci	if (unlikely(!p))
523562306a36Sopenharmony_ci		return -EIO;
523662306a36Sopenharmony_ci	savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
523762306a36Sopenharmony_ci	for (i = 0; i < savewords; ++i)
523862306a36Sopenharmony_ci		res->attrset[i] = be32_to_cpup(p++);
523962306a36Sopenharmony_ci	for (; i < NFS4_BITMAP_SIZE; i++)
524062306a36Sopenharmony_ci		res->attrset[i] = 0;
524162306a36Sopenharmony_ci
524262306a36Sopenharmony_ci	return decode_delegation(xdr, res);
524362306a36Sopenharmony_cixdr_error:
524462306a36Sopenharmony_ci	dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
524562306a36Sopenharmony_ci	return -EIO;
524662306a36Sopenharmony_ci}
524762306a36Sopenharmony_ci
524862306a36Sopenharmony_cistatic int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
524962306a36Sopenharmony_ci{
525062306a36Sopenharmony_ci	int status;
525162306a36Sopenharmony_ci
525262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
525362306a36Sopenharmony_ci	if (status != -EIO)
525462306a36Sopenharmony_ci		nfs_increment_open_seqid(status, res->seqid);
525562306a36Sopenharmony_ci	if (!status)
525662306a36Sopenharmony_ci		status = decode_open_stateid(xdr, &res->stateid);
525762306a36Sopenharmony_ci	return status;
525862306a36Sopenharmony_ci}
525962306a36Sopenharmony_ci
526062306a36Sopenharmony_cistatic int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
526162306a36Sopenharmony_ci{
526262306a36Sopenharmony_ci	int status;
526362306a36Sopenharmony_ci
526462306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
526562306a36Sopenharmony_ci	if (status != -EIO)
526662306a36Sopenharmony_ci		nfs_increment_open_seqid(status, res->seqid);
526762306a36Sopenharmony_ci	if (!status)
526862306a36Sopenharmony_ci		status = decode_open_stateid(xdr, &res->stateid);
526962306a36Sopenharmony_ci	return status;
527062306a36Sopenharmony_ci}
527162306a36Sopenharmony_ci
527262306a36Sopenharmony_cistatic int decode_putfh(struct xdr_stream *xdr)
527362306a36Sopenharmony_ci{
527462306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_PUTFH);
527562306a36Sopenharmony_ci}
527662306a36Sopenharmony_ci
527762306a36Sopenharmony_cistatic int decode_putrootfh(struct xdr_stream *xdr)
527862306a36Sopenharmony_ci{
527962306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_PUTROOTFH);
528062306a36Sopenharmony_ci}
528162306a36Sopenharmony_ci
528262306a36Sopenharmony_cistatic int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
528362306a36Sopenharmony_ci		       struct nfs_pgio_res *res)
528462306a36Sopenharmony_ci{
528562306a36Sopenharmony_ci	__be32 *p;
528662306a36Sopenharmony_ci	uint32_t count, eof, recvd;
528762306a36Sopenharmony_ci	int status;
528862306a36Sopenharmony_ci
528962306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_READ);
529062306a36Sopenharmony_ci	if (status)
529162306a36Sopenharmony_ci		return status;
529262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
529362306a36Sopenharmony_ci	if (unlikely(!p))
529462306a36Sopenharmony_ci		return -EIO;
529562306a36Sopenharmony_ci	eof = be32_to_cpup(p++);
529662306a36Sopenharmony_ci	count = be32_to_cpup(p);
529762306a36Sopenharmony_ci	recvd = xdr_read_pages(xdr, count);
529862306a36Sopenharmony_ci	if (count > recvd) {
529962306a36Sopenharmony_ci		dprintk("NFS: server cheating in read reply: "
530062306a36Sopenharmony_ci				"count %u > recvd %u\n", count, recvd);
530162306a36Sopenharmony_ci		count = recvd;
530262306a36Sopenharmony_ci		eof = 0;
530362306a36Sopenharmony_ci	}
530462306a36Sopenharmony_ci	res->eof = eof;
530562306a36Sopenharmony_ci	res->count = count;
530662306a36Sopenharmony_ci	return 0;
530762306a36Sopenharmony_ci}
530862306a36Sopenharmony_ci
530962306a36Sopenharmony_cistatic int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
531062306a36Sopenharmony_ci{
531162306a36Sopenharmony_ci	int		status;
531262306a36Sopenharmony_ci	__be32		verf[2];
531362306a36Sopenharmony_ci
531462306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_READDIR);
531562306a36Sopenharmony_ci	if (!status)
531662306a36Sopenharmony_ci		status = decode_verifier(xdr, readdir->verifier.data);
531762306a36Sopenharmony_ci	if (unlikely(status))
531862306a36Sopenharmony_ci		return status;
531962306a36Sopenharmony_ci	memcpy(verf, readdir->verifier.data, sizeof(verf));
532062306a36Sopenharmony_ci	dprintk("%s: verifier = %08x:%08x\n",
532162306a36Sopenharmony_ci			__func__, verf[0], verf[1]);
532262306a36Sopenharmony_ci	return xdr_read_pages(xdr, xdr->buf->page_len);
532362306a36Sopenharmony_ci}
532462306a36Sopenharmony_ci
532562306a36Sopenharmony_cistatic int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
532662306a36Sopenharmony_ci{
532762306a36Sopenharmony_ci	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
532862306a36Sopenharmony_ci	u32 len, recvd;
532962306a36Sopenharmony_ci	__be32 *p;
533062306a36Sopenharmony_ci	int status;
533162306a36Sopenharmony_ci
533262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_READLINK);
533362306a36Sopenharmony_ci	if (status)
533462306a36Sopenharmony_ci		return status;
533562306a36Sopenharmony_ci
533662306a36Sopenharmony_ci	/* Convert length of symlink */
533762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
533862306a36Sopenharmony_ci	if (unlikely(!p))
533962306a36Sopenharmony_ci		return -EIO;
534062306a36Sopenharmony_ci	len = be32_to_cpup(p);
534162306a36Sopenharmony_ci	if (len >= rcvbuf->page_len || len <= 0) {
534262306a36Sopenharmony_ci		dprintk("nfs: server returned giant symlink!\n");
534362306a36Sopenharmony_ci		return -ENAMETOOLONG;
534462306a36Sopenharmony_ci	}
534562306a36Sopenharmony_ci	recvd = xdr_read_pages(xdr, len);
534662306a36Sopenharmony_ci	if (recvd < len) {
534762306a36Sopenharmony_ci		dprintk("NFS: server cheating in readlink reply: "
534862306a36Sopenharmony_ci				"count %u > recvd %u\n", len, recvd);
534962306a36Sopenharmony_ci		return -EIO;
535062306a36Sopenharmony_ci	}
535162306a36Sopenharmony_ci	/*
535262306a36Sopenharmony_ci	 * The XDR encode routine has set things up so that
535362306a36Sopenharmony_ci	 * the link text will be copied directly into the
535462306a36Sopenharmony_ci	 * buffer.  We just have to do overflow-checking,
535562306a36Sopenharmony_ci	 * and null-terminate the text (the VFS expects
535662306a36Sopenharmony_ci	 * null-termination).
535762306a36Sopenharmony_ci	 */
535862306a36Sopenharmony_ci	xdr_terminate_string(rcvbuf, len);
535962306a36Sopenharmony_ci	return 0;
536062306a36Sopenharmony_ci}
536162306a36Sopenharmony_ci
536262306a36Sopenharmony_cistatic int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
536362306a36Sopenharmony_ci{
536462306a36Sopenharmony_ci	int status;
536562306a36Sopenharmony_ci
536662306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_REMOVE);
536762306a36Sopenharmony_ci	if (status)
536862306a36Sopenharmony_ci		goto out;
536962306a36Sopenharmony_ci	status = decode_change_info(xdr, cinfo);
537062306a36Sopenharmony_ciout:
537162306a36Sopenharmony_ci	return status;
537262306a36Sopenharmony_ci}
537362306a36Sopenharmony_ci
537462306a36Sopenharmony_cistatic int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
537562306a36Sopenharmony_ci	      struct nfs4_change_info *new_cinfo)
537662306a36Sopenharmony_ci{
537762306a36Sopenharmony_ci	int status;
537862306a36Sopenharmony_ci
537962306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_RENAME);
538062306a36Sopenharmony_ci	if (status)
538162306a36Sopenharmony_ci		goto out;
538262306a36Sopenharmony_ci	if ((status = decode_change_info(xdr, old_cinfo)))
538362306a36Sopenharmony_ci		goto out;
538462306a36Sopenharmony_ci	status = decode_change_info(xdr, new_cinfo);
538562306a36Sopenharmony_ciout:
538662306a36Sopenharmony_ci	return status;
538762306a36Sopenharmony_ci}
538862306a36Sopenharmony_ci
538962306a36Sopenharmony_cistatic int decode_renew(struct xdr_stream *xdr)
539062306a36Sopenharmony_ci{
539162306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_RENEW);
539262306a36Sopenharmony_ci}
539362306a36Sopenharmony_ci
539462306a36Sopenharmony_cistatic int
539562306a36Sopenharmony_cidecode_restorefh(struct xdr_stream *xdr)
539662306a36Sopenharmony_ci{
539762306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_RESTOREFH);
539862306a36Sopenharmony_ci}
539962306a36Sopenharmony_ci
540062306a36Sopenharmony_cistatic int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
540162306a36Sopenharmony_ci			 struct nfs_getaclres *res, enum nfs4_acl_type type)
540262306a36Sopenharmony_ci{
540362306a36Sopenharmony_ci	unsigned int savep;
540462306a36Sopenharmony_ci	uint32_t attrlen,
540562306a36Sopenharmony_ci		 bitmap[3] = {0};
540662306a36Sopenharmony_ci	int status;
540762306a36Sopenharmony_ci
540862306a36Sopenharmony_ci	res->acl_len = 0;
540962306a36Sopenharmony_ci	if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
541062306a36Sopenharmony_ci		goto out;
541162306a36Sopenharmony_ci
541262306a36Sopenharmony_ci	xdr_enter_page(xdr, xdr->buf->page_len);
541362306a36Sopenharmony_ci
541462306a36Sopenharmony_ci	if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
541562306a36Sopenharmony_ci		goto out;
541662306a36Sopenharmony_ci	if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
541762306a36Sopenharmony_ci		goto out;
541862306a36Sopenharmony_ci
541962306a36Sopenharmony_ci	switch (type) {
542062306a36Sopenharmony_ci	default:
542162306a36Sopenharmony_ci		if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
542262306a36Sopenharmony_ci			return -EIO;
542362306a36Sopenharmony_ci		if (!(bitmap[0] & FATTR4_WORD0_ACL))
542462306a36Sopenharmony_ci			return -EOPNOTSUPP;
542562306a36Sopenharmony_ci		break;
542662306a36Sopenharmony_ci	case NFS4ACL_DACL:
542762306a36Sopenharmony_ci		if (unlikely(bitmap[0] || bitmap[1] & (FATTR4_WORD1_DACL - 1U)))
542862306a36Sopenharmony_ci			return -EIO;
542962306a36Sopenharmony_ci		if (!(bitmap[1] & FATTR4_WORD1_DACL))
543062306a36Sopenharmony_ci			return -EOPNOTSUPP;
543162306a36Sopenharmony_ci		break;
543262306a36Sopenharmony_ci	case NFS4ACL_SACL:
543362306a36Sopenharmony_ci		if (unlikely(bitmap[0] || bitmap[1] & (FATTR4_WORD1_SACL - 1U)))
543462306a36Sopenharmony_ci			return -EIO;
543562306a36Sopenharmony_ci		if (!(bitmap[1] & FATTR4_WORD1_SACL))
543662306a36Sopenharmony_ci			return -EOPNOTSUPP;
543762306a36Sopenharmony_ci	}
543862306a36Sopenharmony_ci
543962306a36Sopenharmony_ci	/* The bitmap (xdr len + bitmaps) and the attr xdr len words
544062306a36Sopenharmony_ci	 * are stored with the acl data to handle the problem of
544162306a36Sopenharmony_ci	 * variable length bitmaps.*/
544262306a36Sopenharmony_ci	res->acl_data_offset = xdr_page_pos(xdr);
544362306a36Sopenharmony_ci	res->acl_len = attrlen;
544462306a36Sopenharmony_ci
544562306a36Sopenharmony_ci	/* Check for receive buffer overflow */
544662306a36Sopenharmony_ci	if (res->acl_len > xdr_stream_remaining(xdr) ||
544762306a36Sopenharmony_ci	    res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
544862306a36Sopenharmony_ci		res->acl_flags |= NFS4_ACL_TRUNC;
544962306a36Sopenharmony_ci		dprintk("NFS: acl reply: attrlen %u > page_len %zu\n",
545062306a36Sopenharmony_ci			attrlen, xdr_stream_remaining(xdr));
545162306a36Sopenharmony_ci	}
545262306a36Sopenharmony_ciout:
545362306a36Sopenharmony_ci	return status;
545462306a36Sopenharmony_ci}
545562306a36Sopenharmony_ci
545662306a36Sopenharmony_cistatic int
545762306a36Sopenharmony_cidecode_savefh(struct xdr_stream *xdr)
545862306a36Sopenharmony_ci{
545962306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_SAVEFH);
546062306a36Sopenharmony_ci}
546162306a36Sopenharmony_ci
546262306a36Sopenharmony_cistatic int decode_setattr(struct xdr_stream *xdr)
546362306a36Sopenharmony_ci{
546462306a36Sopenharmony_ci	int status;
546562306a36Sopenharmony_ci
546662306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_SETATTR);
546762306a36Sopenharmony_ci	if (status)
546862306a36Sopenharmony_ci		return status;
546962306a36Sopenharmony_ci	if (decode_bitmap4(xdr, NULL, 0) >= 0)
547062306a36Sopenharmony_ci		return 0;
547162306a36Sopenharmony_ci	return -EIO;
547262306a36Sopenharmony_ci}
547362306a36Sopenharmony_ci
547462306a36Sopenharmony_cistatic int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res)
547562306a36Sopenharmony_ci{
547662306a36Sopenharmony_ci	__be32 *p;
547762306a36Sopenharmony_ci	uint32_t opnum;
547862306a36Sopenharmony_ci	int32_t nfserr;
547962306a36Sopenharmony_ci
548062306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
548162306a36Sopenharmony_ci	if (unlikely(!p))
548262306a36Sopenharmony_ci		return -EIO;
548362306a36Sopenharmony_ci	opnum = be32_to_cpup(p++);
548462306a36Sopenharmony_ci	if (opnum != OP_SETCLIENTID) {
548562306a36Sopenharmony_ci		dprintk("nfs: decode_setclientid: Server returned operation"
548662306a36Sopenharmony_ci			" %d\n", opnum);
548762306a36Sopenharmony_ci		return -EIO;
548862306a36Sopenharmony_ci	}
548962306a36Sopenharmony_ci	nfserr = be32_to_cpup(p);
549062306a36Sopenharmony_ci	if (nfserr == NFS_OK) {
549162306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
549262306a36Sopenharmony_ci		if (unlikely(!p))
549362306a36Sopenharmony_ci			return -EIO;
549462306a36Sopenharmony_ci		p = xdr_decode_hyper(p, &res->clientid);
549562306a36Sopenharmony_ci		memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
549662306a36Sopenharmony_ci	} else if (nfserr == NFSERR_CLID_INUSE) {
549762306a36Sopenharmony_ci		uint32_t len;
549862306a36Sopenharmony_ci
549962306a36Sopenharmony_ci		/* skip netid string */
550062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
550162306a36Sopenharmony_ci		if (unlikely(!p))
550262306a36Sopenharmony_ci			return -EIO;
550362306a36Sopenharmony_ci		len = be32_to_cpup(p);
550462306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, len);
550562306a36Sopenharmony_ci		if (unlikely(!p))
550662306a36Sopenharmony_ci			return -EIO;
550762306a36Sopenharmony_ci
550862306a36Sopenharmony_ci		/* skip uaddr string */
550962306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
551062306a36Sopenharmony_ci		if (unlikely(!p))
551162306a36Sopenharmony_ci			return -EIO;
551262306a36Sopenharmony_ci		len = be32_to_cpup(p);
551362306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, len);
551462306a36Sopenharmony_ci		if (unlikely(!p))
551562306a36Sopenharmony_ci			return -EIO;
551662306a36Sopenharmony_ci		return -NFSERR_CLID_INUSE;
551762306a36Sopenharmony_ci	} else
551862306a36Sopenharmony_ci		return nfs4_stat_to_errno(nfserr);
551962306a36Sopenharmony_ci
552062306a36Sopenharmony_ci	return 0;
552162306a36Sopenharmony_ci}
552262306a36Sopenharmony_ci
552362306a36Sopenharmony_cistatic int decode_setclientid_confirm(struct xdr_stream *xdr)
552462306a36Sopenharmony_ci{
552562306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
552662306a36Sopenharmony_ci}
552762306a36Sopenharmony_ci
552862306a36Sopenharmony_cistatic int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res)
552962306a36Sopenharmony_ci{
553062306a36Sopenharmony_ci	__be32 *p;
553162306a36Sopenharmony_ci	int status;
553262306a36Sopenharmony_ci
553362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_WRITE);
553462306a36Sopenharmony_ci	if (status)
553562306a36Sopenharmony_ci		return status;
553662306a36Sopenharmony_ci
553762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
553862306a36Sopenharmony_ci	if (unlikely(!p))
553962306a36Sopenharmony_ci		return -EIO;
554062306a36Sopenharmony_ci	res->count = be32_to_cpup(p++);
554162306a36Sopenharmony_ci	res->verf->committed = be32_to_cpup(p++);
554262306a36Sopenharmony_ci	return decode_write_verifier(xdr, &res->verf->verifier);
554362306a36Sopenharmony_ci}
554462306a36Sopenharmony_ci
554562306a36Sopenharmony_cistatic int decode_delegreturn(struct xdr_stream *xdr)
554662306a36Sopenharmony_ci{
554762306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_DELEGRETURN);
554862306a36Sopenharmony_ci}
554962306a36Sopenharmony_ci
555062306a36Sopenharmony_cistatic int decode_secinfo_gss(struct xdr_stream *xdr,
555162306a36Sopenharmony_ci			      struct nfs4_secinfo4 *flavor)
555262306a36Sopenharmony_ci{
555362306a36Sopenharmony_ci	u32 oid_len;
555462306a36Sopenharmony_ci	__be32 *p;
555562306a36Sopenharmony_ci
555662306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
555762306a36Sopenharmony_ci	if (unlikely(!p))
555862306a36Sopenharmony_ci		return -EIO;
555962306a36Sopenharmony_ci	oid_len = be32_to_cpup(p);
556062306a36Sopenharmony_ci	if (oid_len > GSS_OID_MAX_LEN)
556162306a36Sopenharmony_ci		return -EINVAL;
556262306a36Sopenharmony_ci
556362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, oid_len);
556462306a36Sopenharmony_ci	if (unlikely(!p))
556562306a36Sopenharmony_ci		return -EIO;
556662306a36Sopenharmony_ci	memcpy(flavor->flavor_info.oid.data, p, oid_len);
556762306a36Sopenharmony_ci	flavor->flavor_info.oid.len = oid_len;
556862306a36Sopenharmony_ci
556962306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
557062306a36Sopenharmony_ci	if (unlikely(!p))
557162306a36Sopenharmony_ci		return -EIO;
557262306a36Sopenharmony_ci	flavor->flavor_info.qop = be32_to_cpup(p++);
557362306a36Sopenharmony_ci	flavor->flavor_info.service = be32_to_cpup(p);
557462306a36Sopenharmony_ci
557562306a36Sopenharmony_ci	return 0;
557662306a36Sopenharmony_ci}
557762306a36Sopenharmony_ci
557862306a36Sopenharmony_cistatic int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
557962306a36Sopenharmony_ci{
558062306a36Sopenharmony_ci	struct nfs4_secinfo4 *sec_flavor;
558162306a36Sopenharmony_ci	unsigned int i, num_flavors;
558262306a36Sopenharmony_ci	int status;
558362306a36Sopenharmony_ci	__be32 *p;
558462306a36Sopenharmony_ci
558562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
558662306a36Sopenharmony_ci	if (unlikely(!p))
558762306a36Sopenharmony_ci		return -EIO;
558862306a36Sopenharmony_ci
558962306a36Sopenharmony_ci	res->flavors->num_flavors = 0;
559062306a36Sopenharmony_ci	num_flavors = be32_to_cpup(p);
559162306a36Sopenharmony_ci
559262306a36Sopenharmony_ci	for (i = 0; i < num_flavors; i++) {
559362306a36Sopenharmony_ci		sec_flavor = &res->flavors->flavors[i];
559462306a36Sopenharmony_ci		if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE)
559562306a36Sopenharmony_ci			break;
559662306a36Sopenharmony_ci
559762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
559862306a36Sopenharmony_ci		if (unlikely(!p))
559962306a36Sopenharmony_ci			return -EIO;
560062306a36Sopenharmony_ci		sec_flavor->flavor = be32_to_cpup(p);
560162306a36Sopenharmony_ci
560262306a36Sopenharmony_ci		if (sec_flavor->flavor == RPC_AUTH_GSS) {
560362306a36Sopenharmony_ci			status = decode_secinfo_gss(xdr, sec_flavor);
560462306a36Sopenharmony_ci			if (status)
560562306a36Sopenharmony_ci				goto out;
560662306a36Sopenharmony_ci		}
560762306a36Sopenharmony_ci		res->flavors->num_flavors++;
560862306a36Sopenharmony_ci	}
560962306a36Sopenharmony_ci
561062306a36Sopenharmony_ci	status = 0;
561162306a36Sopenharmony_ciout:
561262306a36Sopenharmony_ci	return status;
561362306a36Sopenharmony_ci}
561462306a36Sopenharmony_ci
561562306a36Sopenharmony_cistatic int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
561662306a36Sopenharmony_ci{
561762306a36Sopenharmony_ci	int status = decode_op_hdr(xdr, OP_SECINFO);
561862306a36Sopenharmony_ci	if (status)
561962306a36Sopenharmony_ci		return status;
562062306a36Sopenharmony_ci	return decode_secinfo_common(xdr, res);
562162306a36Sopenharmony_ci}
562262306a36Sopenharmony_ci
562362306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
562462306a36Sopenharmony_cistatic int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
562562306a36Sopenharmony_ci{
562662306a36Sopenharmony_ci	int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME);
562762306a36Sopenharmony_ci	if (status)
562862306a36Sopenharmony_ci		return status;
562962306a36Sopenharmony_ci	return decode_secinfo_common(xdr, res);
563062306a36Sopenharmony_ci}
563162306a36Sopenharmony_ci
563262306a36Sopenharmony_cistatic int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
563362306a36Sopenharmony_ci{
563462306a36Sopenharmony_ci	if (xdr_stream_decode_uint32_array(xdr, op_map->u.words,
563562306a36Sopenharmony_ci					   ARRAY_SIZE(op_map->u.words)) < 0)
563662306a36Sopenharmony_ci		return -EIO;
563762306a36Sopenharmony_ci	return 0;
563862306a36Sopenharmony_ci}
563962306a36Sopenharmony_ci
564062306a36Sopenharmony_cistatic int decode_exchange_id(struct xdr_stream *xdr,
564162306a36Sopenharmony_ci			      struct nfs41_exchange_id_res *res)
564262306a36Sopenharmony_ci{
564362306a36Sopenharmony_ci	__be32 *p;
564462306a36Sopenharmony_ci	uint32_t dummy;
564562306a36Sopenharmony_ci	char *dummy_str;
564662306a36Sopenharmony_ci	int status;
564762306a36Sopenharmony_ci	uint32_t impl_id_count;
564862306a36Sopenharmony_ci
564962306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
565062306a36Sopenharmony_ci	if (status)
565162306a36Sopenharmony_ci		return status;
565262306a36Sopenharmony_ci
565362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
565462306a36Sopenharmony_ci	if (unlikely(!p))
565562306a36Sopenharmony_ci		return -EIO;
565662306a36Sopenharmony_ci	xdr_decode_hyper(p, &res->clientid);
565762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 12);
565862306a36Sopenharmony_ci	if (unlikely(!p))
565962306a36Sopenharmony_ci		return -EIO;
566062306a36Sopenharmony_ci	res->seqid = be32_to_cpup(p++);
566162306a36Sopenharmony_ci	res->flags = be32_to_cpup(p++);
566262306a36Sopenharmony_ci
566362306a36Sopenharmony_ci	res->state_protect.how = be32_to_cpup(p);
566462306a36Sopenharmony_ci	switch (res->state_protect.how) {
566562306a36Sopenharmony_ci	case SP4_NONE:
566662306a36Sopenharmony_ci		break;
566762306a36Sopenharmony_ci	case SP4_MACH_CRED:
566862306a36Sopenharmony_ci		status = decode_op_map(xdr, &res->state_protect.enforce);
566962306a36Sopenharmony_ci		if (status)
567062306a36Sopenharmony_ci			return status;
567162306a36Sopenharmony_ci		status = decode_op_map(xdr, &res->state_protect.allow);
567262306a36Sopenharmony_ci		if (status)
567362306a36Sopenharmony_ci			return status;
567462306a36Sopenharmony_ci		break;
567562306a36Sopenharmony_ci	default:
567662306a36Sopenharmony_ci		WARN_ON_ONCE(1);
567762306a36Sopenharmony_ci		return -EIO;
567862306a36Sopenharmony_ci	}
567962306a36Sopenharmony_ci
568062306a36Sopenharmony_ci	/* server_owner4.so_minor_id */
568162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
568262306a36Sopenharmony_ci	if (unlikely(!p))
568362306a36Sopenharmony_ci		return -EIO;
568462306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->server_owner->minor_id);
568562306a36Sopenharmony_ci
568662306a36Sopenharmony_ci	/* server_owner4.so_major_id */
568762306a36Sopenharmony_ci	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
568862306a36Sopenharmony_ci	if (unlikely(status))
568962306a36Sopenharmony_ci		return status;
569062306a36Sopenharmony_ci	memcpy(res->server_owner->major_id, dummy_str, dummy);
569162306a36Sopenharmony_ci	res->server_owner->major_id_sz = dummy;
569262306a36Sopenharmony_ci
569362306a36Sopenharmony_ci	/* server_scope4 */
569462306a36Sopenharmony_ci	status = decode_opaque_inline(xdr, &dummy, &dummy_str);
569562306a36Sopenharmony_ci	if (unlikely(status))
569662306a36Sopenharmony_ci		return status;
569762306a36Sopenharmony_ci	memcpy(res->server_scope->server_scope, dummy_str, dummy);
569862306a36Sopenharmony_ci	res->server_scope->server_scope_sz = dummy;
569962306a36Sopenharmony_ci
570062306a36Sopenharmony_ci	/* Implementation Id */
570162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
570262306a36Sopenharmony_ci	if (unlikely(!p))
570362306a36Sopenharmony_ci		return -EIO;
570462306a36Sopenharmony_ci	impl_id_count = be32_to_cpup(p++);
570562306a36Sopenharmony_ci
570662306a36Sopenharmony_ci	if (impl_id_count) {
570762306a36Sopenharmony_ci		/* nii_domain */
570862306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
570962306a36Sopenharmony_ci		if (unlikely(status))
571062306a36Sopenharmony_ci			return status;
571162306a36Sopenharmony_ci		memcpy(res->impl_id->domain, dummy_str, dummy);
571262306a36Sopenharmony_ci
571362306a36Sopenharmony_ci		/* nii_name */
571462306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
571562306a36Sopenharmony_ci		if (unlikely(status))
571662306a36Sopenharmony_ci			return status;
571762306a36Sopenharmony_ci		memcpy(res->impl_id->name, dummy_str, dummy);
571862306a36Sopenharmony_ci
571962306a36Sopenharmony_ci		/* nii_date */
572062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 12);
572162306a36Sopenharmony_ci		if (unlikely(!p))
572262306a36Sopenharmony_ci			return -EIO;
572362306a36Sopenharmony_ci		p = xdr_decode_hyper(p, &res->impl_id->date.seconds);
572462306a36Sopenharmony_ci		res->impl_id->date.nseconds = be32_to_cpup(p);
572562306a36Sopenharmony_ci
572662306a36Sopenharmony_ci		/* if there's more than one entry, ignore the rest */
572762306a36Sopenharmony_ci	}
572862306a36Sopenharmony_ci	return 0;
572962306a36Sopenharmony_ci}
573062306a36Sopenharmony_ci
573162306a36Sopenharmony_cistatic int decode_chan_attrs(struct xdr_stream *xdr,
573262306a36Sopenharmony_ci			     struct nfs4_channel_attrs *attrs)
573362306a36Sopenharmony_ci{
573462306a36Sopenharmony_ci	__be32 *p;
573562306a36Sopenharmony_ci	u32 nr_attrs, val;
573662306a36Sopenharmony_ci
573762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 28);
573862306a36Sopenharmony_ci	if (unlikely(!p))
573962306a36Sopenharmony_ci		return -EIO;
574062306a36Sopenharmony_ci	val = be32_to_cpup(p++);	/* headerpadsz */
574162306a36Sopenharmony_ci	if (val)
574262306a36Sopenharmony_ci		return -EINVAL;		/* no support for header padding yet */
574362306a36Sopenharmony_ci	attrs->max_rqst_sz = be32_to_cpup(p++);
574462306a36Sopenharmony_ci	attrs->max_resp_sz = be32_to_cpup(p++);
574562306a36Sopenharmony_ci	attrs->max_resp_sz_cached = be32_to_cpup(p++);
574662306a36Sopenharmony_ci	attrs->max_ops = be32_to_cpup(p++);
574762306a36Sopenharmony_ci	attrs->max_reqs = be32_to_cpup(p++);
574862306a36Sopenharmony_ci	nr_attrs = be32_to_cpup(p);
574962306a36Sopenharmony_ci	if (unlikely(nr_attrs > 1)) {
575062306a36Sopenharmony_ci		printk(KERN_WARNING "NFS: %s: Invalid rdma channel attrs "
575162306a36Sopenharmony_ci			"count %u\n", __func__, nr_attrs);
575262306a36Sopenharmony_ci		return -EINVAL;
575362306a36Sopenharmony_ci	}
575462306a36Sopenharmony_ci	if (nr_attrs == 1) {
575562306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
575662306a36Sopenharmony_ci		if (unlikely(!p))
575762306a36Sopenharmony_ci			return -EIO;
575862306a36Sopenharmony_ci	}
575962306a36Sopenharmony_ci	return 0;
576062306a36Sopenharmony_ci}
576162306a36Sopenharmony_ci
576262306a36Sopenharmony_cistatic int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
576362306a36Sopenharmony_ci{
576462306a36Sopenharmony_ci	return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
576562306a36Sopenharmony_ci}
576662306a36Sopenharmony_ci
576762306a36Sopenharmony_cistatic int decode_bind_conn_to_session(struct xdr_stream *xdr,
576862306a36Sopenharmony_ci				struct nfs41_bind_conn_to_session_res *res)
576962306a36Sopenharmony_ci{
577062306a36Sopenharmony_ci	__be32 *p;
577162306a36Sopenharmony_ci	int status;
577262306a36Sopenharmony_ci
577362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
577462306a36Sopenharmony_ci	if (!status)
577562306a36Sopenharmony_ci		status = decode_sessionid(xdr, &res->sessionid);
577662306a36Sopenharmony_ci	if (unlikely(status))
577762306a36Sopenharmony_ci		return status;
577862306a36Sopenharmony_ci
577962306a36Sopenharmony_ci	/* dir flags, rdma mode bool */
578062306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
578162306a36Sopenharmony_ci	if (unlikely(!p))
578262306a36Sopenharmony_ci		return -EIO;
578362306a36Sopenharmony_ci
578462306a36Sopenharmony_ci	res->dir = be32_to_cpup(p++);
578562306a36Sopenharmony_ci	if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH)
578662306a36Sopenharmony_ci		return -EIO;
578762306a36Sopenharmony_ci	if (be32_to_cpup(p) == 0)
578862306a36Sopenharmony_ci		res->use_conn_in_rdma_mode = false;
578962306a36Sopenharmony_ci	else
579062306a36Sopenharmony_ci		res->use_conn_in_rdma_mode = true;
579162306a36Sopenharmony_ci
579262306a36Sopenharmony_ci	return 0;
579362306a36Sopenharmony_ci}
579462306a36Sopenharmony_ci
579562306a36Sopenharmony_cistatic int decode_create_session(struct xdr_stream *xdr,
579662306a36Sopenharmony_ci				 struct nfs41_create_session_res *res)
579762306a36Sopenharmony_ci{
579862306a36Sopenharmony_ci	__be32 *p;
579962306a36Sopenharmony_ci	int status;
580062306a36Sopenharmony_ci
580162306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_CREATE_SESSION);
580262306a36Sopenharmony_ci	if (!status)
580362306a36Sopenharmony_ci		status = decode_sessionid(xdr, &res->sessionid);
580462306a36Sopenharmony_ci	if (unlikely(status))
580562306a36Sopenharmony_ci		return status;
580662306a36Sopenharmony_ci
580762306a36Sopenharmony_ci	/* seqid, flags */
580862306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
580962306a36Sopenharmony_ci	if (unlikely(!p))
581062306a36Sopenharmony_ci		return -EIO;
581162306a36Sopenharmony_ci	res->seqid = be32_to_cpup(p++);
581262306a36Sopenharmony_ci	res->flags = be32_to_cpup(p);
581362306a36Sopenharmony_ci
581462306a36Sopenharmony_ci	/* Channel attributes */
581562306a36Sopenharmony_ci	status = decode_chan_attrs(xdr, &res->fc_attrs);
581662306a36Sopenharmony_ci	if (!status)
581762306a36Sopenharmony_ci		status = decode_chan_attrs(xdr, &res->bc_attrs);
581862306a36Sopenharmony_ci	return status;
581962306a36Sopenharmony_ci}
582062306a36Sopenharmony_ci
582162306a36Sopenharmony_cistatic int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
582262306a36Sopenharmony_ci{
582362306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_DESTROY_SESSION);
582462306a36Sopenharmony_ci}
582562306a36Sopenharmony_ci
582662306a36Sopenharmony_cistatic int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy)
582762306a36Sopenharmony_ci{
582862306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_DESTROY_CLIENTID);
582962306a36Sopenharmony_ci}
583062306a36Sopenharmony_ci
583162306a36Sopenharmony_cistatic int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
583262306a36Sopenharmony_ci{
583362306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
583462306a36Sopenharmony_ci}
583562306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
583662306a36Sopenharmony_ci
583762306a36Sopenharmony_cistatic int decode_sequence(struct xdr_stream *xdr,
583862306a36Sopenharmony_ci			   struct nfs4_sequence_res *res,
583962306a36Sopenharmony_ci			   struct rpc_rqst *rqstp)
584062306a36Sopenharmony_ci{
584162306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
584262306a36Sopenharmony_ci	struct nfs4_session *session;
584362306a36Sopenharmony_ci	struct nfs4_sessionid id;
584462306a36Sopenharmony_ci	u32 dummy;
584562306a36Sopenharmony_ci	int status;
584662306a36Sopenharmony_ci	__be32 *p;
584762306a36Sopenharmony_ci
584862306a36Sopenharmony_ci	if (res->sr_slot == NULL)
584962306a36Sopenharmony_ci		return 0;
585062306a36Sopenharmony_ci	if (!res->sr_slot->table->session)
585162306a36Sopenharmony_ci		return 0;
585262306a36Sopenharmony_ci
585362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_SEQUENCE);
585462306a36Sopenharmony_ci	if (!status)
585562306a36Sopenharmony_ci		status = decode_sessionid(xdr, &id);
585662306a36Sopenharmony_ci	if (unlikely(status))
585762306a36Sopenharmony_ci		goto out_err;
585862306a36Sopenharmony_ci
585962306a36Sopenharmony_ci	/*
586062306a36Sopenharmony_ci	 * If the server returns different values for sessionID, slotID or
586162306a36Sopenharmony_ci	 * sequence number, the server is looney tunes.
586262306a36Sopenharmony_ci	 */
586362306a36Sopenharmony_ci	status = -EREMOTEIO;
586462306a36Sopenharmony_ci	session = res->sr_slot->table->session;
586562306a36Sopenharmony_ci
586662306a36Sopenharmony_ci	if (memcmp(id.data, session->sess_id.data,
586762306a36Sopenharmony_ci		   NFS4_MAX_SESSIONID_LEN)) {
586862306a36Sopenharmony_ci		dprintk("%s Invalid session id\n", __func__);
586962306a36Sopenharmony_ci		goto out_err;
587062306a36Sopenharmony_ci	}
587162306a36Sopenharmony_ci
587262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 20);
587362306a36Sopenharmony_ci	if (unlikely(!p))
587462306a36Sopenharmony_ci		goto out_overflow;
587562306a36Sopenharmony_ci
587662306a36Sopenharmony_ci	/* seqid */
587762306a36Sopenharmony_ci	dummy = be32_to_cpup(p++);
587862306a36Sopenharmony_ci	if (dummy != res->sr_slot->seq_nr) {
587962306a36Sopenharmony_ci		dprintk("%s Invalid sequence number\n", __func__);
588062306a36Sopenharmony_ci		goto out_err;
588162306a36Sopenharmony_ci	}
588262306a36Sopenharmony_ci	/* slot id */
588362306a36Sopenharmony_ci	dummy = be32_to_cpup(p++);
588462306a36Sopenharmony_ci	if (dummy != res->sr_slot->slot_nr) {
588562306a36Sopenharmony_ci		dprintk("%s Invalid slot id\n", __func__);
588662306a36Sopenharmony_ci		goto out_err;
588762306a36Sopenharmony_ci	}
588862306a36Sopenharmony_ci	/* highest slot id */
588962306a36Sopenharmony_ci	res->sr_highest_slotid = be32_to_cpup(p++);
589062306a36Sopenharmony_ci	/* target highest slot id */
589162306a36Sopenharmony_ci	res->sr_target_highest_slotid = be32_to_cpup(p++);
589262306a36Sopenharmony_ci	/* result flags */
589362306a36Sopenharmony_ci	res->sr_status_flags = be32_to_cpup(p);
589462306a36Sopenharmony_ci	status = 0;
589562306a36Sopenharmony_ciout_err:
589662306a36Sopenharmony_ci	res->sr_status = status;
589762306a36Sopenharmony_ci	return status;
589862306a36Sopenharmony_ciout_overflow:
589962306a36Sopenharmony_ci	status = -EIO;
590062306a36Sopenharmony_ci	goto out_err;
590162306a36Sopenharmony_ci#else  /* CONFIG_NFS_V4_1 */
590262306a36Sopenharmony_ci	return 0;
590362306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
590462306a36Sopenharmony_ci}
590562306a36Sopenharmony_ci
590662306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
590762306a36Sopenharmony_cistatic int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
590862306a36Sopenharmony_ci{
590962306a36Sopenharmony_ci	stateid->type = NFS4_LAYOUT_STATEID_TYPE;
591062306a36Sopenharmony_ci	return decode_stateid(xdr, stateid);
591162306a36Sopenharmony_ci}
591262306a36Sopenharmony_ci
591362306a36Sopenharmony_cistatic int decode_getdeviceinfo(struct xdr_stream *xdr,
591462306a36Sopenharmony_ci				struct nfs4_getdeviceinfo_res *res)
591562306a36Sopenharmony_ci{
591662306a36Sopenharmony_ci	struct pnfs_device *pdev = res->pdev;
591762306a36Sopenharmony_ci	__be32 *p;
591862306a36Sopenharmony_ci	uint32_t len, type;
591962306a36Sopenharmony_ci	int status;
592062306a36Sopenharmony_ci
592162306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_GETDEVICEINFO);
592262306a36Sopenharmony_ci	if (status) {
592362306a36Sopenharmony_ci		if (status == -ETOOSMALL) {
592462306a36Sopenharmony_ci			p = xdr_inline_decode(xdr, 4);
592562306a36Sopenharmony_ci			if (unlikely(!p))
592662306a36Sopenharmony_ci				return -EIO;
592762306a36Sopenharmony_ci			pdev->mincount = be32_to_cpup(p);
592862306a36Sopenharmony_ci			dprintk("%s: Min count too small. mincnt = %u\n",
592962306a36Sopenharmony_ci				__func__, pdev->mincount);
593062306a36Sopenharmony_ci		}
593162306a36Sopenharmony_ci		return status;
593262306a36Sopenharmony_ci	}
593362306a36Sopenharmony_ci
593462306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
593562306a36Sopenharmony_ci	if (unlikely(!p))
593662306a36Sopenharmony_ci		return -EIO;
593762306a36Sopenharmony_ci	type = be32_to_cpup(p++);
593862306a36Sopenharmony_ci	if (type != pdev->layout_type) {
593962306a36Sopenharmony_ci		dprintk("%s: layout mismatch req: %u pdev: %u\n",
594062306a36Sopenharmony_ci			__func__, pdev->layout_type, type);
594162306a36Sopenharmony_ci		return -EINVAL;
594262306a36Sopenharmony_ci	}
594362306a36Sopenharmony_ci	/*
594462306a36Sopenharmony_ci	 * Get the length of the opaque device_addr4. xdr_read_pages places
594562306a36Sopenharmony_ci	 * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages)
594662306a36Sopenharmony_ci	 * and places the remaining xdr data in xdr_buf->tail
594762306a36Sopenharmony_ci	 */
594862306a36Sopenharmony_ci	pdev->mincount = be32_to_cpup(p);
594962306a36Sopenharmony_ci	if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount)
595062306a36Sopenharmony_ci		return -EIO;
595162306a36Sopenharmony_ci
595262306a36Sopenharmony_ci	/* Parse notification bitmap, verifying that it is zero. */
595362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
595462306a36Sopenharmony_ci	if (unlikely(!p))
595562306a36Sopenharmony_ci		return -EIO;
595662306a36Sopenharmony_ci	len = be32_to_cpup(p);
595762306a36Sopenharmony_ci	if (len) {
595862306a36Sopenharmony_ci		uint32_t i;
595962306a36Sopenharmony_ci
596062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4 * len);
596162306a36Sopenharmony_ci		if (unlikely(!p))
596262306a36Sopenharmony_ci			return -EIO;
596362306a36Sopenharmony_ci
596462306a36Sopenharmony_ci		res->notification = be32_to_cpup(p++);
596562306a36Sopenharmony_ci		for (i = 1; i < len; i++) {
596662306a36Sopenharmony_ci			if (be32_to_cpup(p++)) {
596762306a36Sopenharmony_ci				dprintk("%s: unsupported notification\n",
596862306a36Sopenharmony_ci					__func__);
596962306a36Sopenharmony_ci				return -EIO;
597062306a36Sopenharmony_ci			}
597162306a36Sopenharmony_ci		}
597262306a36Sopenharmony_ci	}
597362306a36Sopenharmony_ci	return 0;
597462306a36Sopenharmony_ci}
597562306a36Sopenharmony_ci
597662306a36Sopenharmony_cistatic int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
597762306a36Sopenharmony_ci			    struct nfs4_layoutget_res *res)
597862306a36Sopenharmony_ci{
597962306a36Sopenharmony_ci	__be32 *p;
598062306a36Sopenharmony_ci	int status;
598162306a36Sopenharmony_ci	u32 layout_count;
598262306a36Sopenharmony_ci	u32 recvd;
598362306a36Sopenharmony_ci
598462306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LAYOUTGET);
598562306a36Sopenharmony_ci	if (status)
598662306a36Sopenharmony_ci		goto out;
598762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
598862306a36Sopenharmony_ci	if (unlikely(!p))
598962306a36Sopenharmony_ci		goto out_overflow;
599062306a36Sopenharmony_ci	res->return_on_close = be32_to_cpup(p);
599162306a36Sopenharmony_ci	decode_layout_stateid(xdr, &res->stateid);
599262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
599362306a36Sopenharmony_ci	if (unlikely(!p))
599462306a36Sopenharmony_ci		goto out_overflow;
599562306a36Sopenharmony_ci	layout_count = be32_to_cpup(p);
599662306a36Sopenharmony_ci	if (!layout_count) {
599762306a36Sopenharmony_ci		dprintk("%s: server responded with empty layout array\n",
599862306a36Sopenharmony_ci			__func__);
599962306a36Sopenharmony_ci		status = -EINVAL;
600062306a36Sopenharmony_ci		goto out;
600162306a36Sopenharmony_ci	}
600262306a36Sopenharmony_ci
600362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 28);
600462306a36Sopenharmony_ci	if (unlikely(!p))
600562306a36Sopenharmony_ci		goto out_overflow;
600662306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->range.offset);
600762306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->range.length);
600862306a36Sopenharmony_ci	res->range.iomode = be32_to_cpup(p++);
600962306a36Sopenharmony_ci	res->type = be32_to_cpup(p++);
601062306a36Sopenharmony_ci	res->layoutp->len = be32_to_cpup(p);
601162306a36Sopenharmony_ci
601262306a36Sopenharmony_ci	dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
601362306a36Sopenharmony_ci		__func__,
601462306a36Sopenharmony_ci		(unsigned long)res->range.offset,
601562306a36Sopenharmony_ci		(unsigned long)res->range.length,
601662306a36Sopenharmony_ci		res->range.iomode,
601762306a36Sopenharmony_ci		res->type,
601862306a36Sopenharmony_ci		res->layoutp->len);
601962306a36Sopenharmony_ci
602062306a36Sopenharmony_ci	recvd = xdr_read_pages(xdr, res->layoutp->len);
602162306a36Sopenharmony_ci	if (res->layoutp->len > recvd) {
602262306a36Sopenharmony_ci		dprintk("NFS: server cheating in layoutget reply: "
602362306a36Sopenharmony_ci				"layout len %u > recvd %u\n",
602462306a36Sopenharmony_ci				res->layoutp->len, recvd);
602562306a36Sopenharmony_ci		status = -EINVAL;
602662306a36Sopenharmony_ci		goto out;
602762306a36Sopenharmony_ci	}
602862306a36Sopenharmony_ci
602962306a36Sopenharmony_ci	if (layout_count > 1) {
603062306a36Sopenharmony_ci		/* We only handle a length one array at the moment.  Any
603162306a36Sopenharmony_ci		 * further entries are just ignored.  Note that this means
603262306a36Sopenharmony_ci		 * the client may see a response that is less than the
603362306a36Sopenharmony_ci		 * minimum it requested.
603462306a36Sopenharmony_ci		 */
603562306a36Sopenharmony_ci		dprintk("%s: server responded with %d layouts, dropping tail\n",
603662306a36Sopenharmony_ci			__func__, layout_count);
603762306a36Sopenharmony_ci	}
603862306a36Sopenharmony_ci
603962306a36Sopenharmony_ciout:
604062306a36Sopenharmony_ci	res->status = status;
604162306a36Sopenharmony_ci	return status;
604262306a36Sopenharmony_ciout_overflow:
604362306a36Sopenharmony_ci	status = -EIO;
604462306a36Sopenharmony_ci	goto out;
604562306a36Sopenharmony_ci}
604662306a36Sopenharmony_ci
604762306a36Sopenharmony_cistatic int decode_layoutreturn(struct xdr_stream *xdr,
604862306a36Sopenharmony_ci			       struct nfs4_layoutreturn_res *res)
604962306a36Sopenharmony_ci{
605062306a36Sopenharmony_ci	__be32 *p;
605162306a36Sopenharmony_ci	int status;
605262306a36Sopenharmony_ci
605362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LAYOUTRETURN);
605462306a36Sopenharmony_ci	if (status)
605562306a36Sopenharmony_ci		return status;
605662306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
605762306a36Sopenharmony_ci	if (unlikely(!p))
605862306a36Sopenharmony_ci		return -EIO;
605962306a36Sopenharmony_ci	res->lrs_present = be32_to_cpup(p);
606062306a36Sopenharmony_ci	if (res->lrs_present)
606162306a36Sopenharmony_ci		status = decode_layout_stateid(xdr, &res->stateid);
606262306a36Sopenharmony_ci	else
606362306a36Sopenharmony_ci		nfs4_stateid_copy(&res->stateid, &invalid_stateid);
606462306a36Sopenharmony_ci	return status;
606562306a36Sopenharmony_ci}
606662306a36Sopenharmony_ci
606762306a36Sopenharmony_cistatic int decode_layoutcommit(struct xdr_stream *xdr,
606862306a36Sopenharmony_ci			       struct rpc_rqst *req,
606962306a36Sopenharmony_ci			       struct nfs4_layoutcommit_res *res)
607062306a36Sopenharmony_ci{
607162306a36Sopenharmony_ci	__be32 *p;
607262306a36Sopenharmony_ci	__u32 sizechanged;
607362306a36Sopenharmony_ci	int status;
607462306a36Sopenharmony_ci
607562306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT);
607662306a36Sopenharmony_ci	res->status = status;
607762306a36Sopenharmony_ci	if (status)
607862306a36Sopenharmony_ci		return status;
607962306a36Sopenharmony_ci
608062306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
608162306a36Sopenharmony_ci	if (unlikely(!p))
608262306a36Sopenharmony_ci		return -EIO;
608362306a36Sopenharmony_ci	sizechanged = be32_to_cpup(p);
608462306a36Sopenharmony_ci
608562306a36Sopenharmony_ci	if (sizechanged) {
608662306a36Sopenharmony_ci		/* throw away new size */
608762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 8);
608862306a36Sopenharmony_ci		if (unlikely(!p))
608962306a36Sopenharmony_ci			return -EIO;
609062306a36Sopenharmony_ci	}
609162306a36Sopenharmony_ci	return 0;
609262306a36Sopenharmony_ci}
609362306a36Sopenharmony_ci
609462306a36Sopenharmony_cistatic int decode_test_stateid(struct xdr_stream *xdr,
609562306a36Sopenharmony_ci			       struct nfs41_test_stateid_res *res)
609662306a36Sopenharmony_ci{
609762306a36Sopenharmony_ci	__be32 *p;
609862306a36Sopenharmony_ci	int status;
609962306a36Sopenharmony_ci	int num_res;
610062306a36Sopenharmony_ci
610162306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_TEST_STATEID);
610262306a36Sopenharmony_ci	if (status)
610362306a36Sopenharmony_ci		return status;
610462306a36Sopenharmony_ci
610562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
610662306a36Sopenharmony_ci	if (unlikely(!p))
610762306a36Sopenharmony_ci		return -EIO;
610862306a36Sopenharmony_ci	num_res = be32_to_cpup(p++);
610962306a36Sopenharmony_ci	if (num_res != 1)
611062306a36Sopenharmony_ci		return -EIO;
611162306a36Sopenharmony_ci
611262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
611362306a36Sopenharmony_ci	if (unlikely(!p))
611462306a36Sopenharmony_ci		return -EIO;
611562306a36Sopenharmony_ci	res->status = be32_to_cpup(p++);
611662306a36Sopenharmony_ci
611762306a36Sopenharmony_ci	return status;
611862306a36Sopenharmony_ci}
611962306a36Sopenharmony_ci
612062306a36Sopenharmony_cistatic int decode_free_stateid(struct xdr_stream *xdr,
612162306a36Sopenharmony_ci			       struct nfs41_free_stateid_res *res)
612262306a36Sopenharmony_ci{
612362306a36Sopenharmony_ci	res->status = decode_op_hdr(xdr, OP_FREE_STATEID);
612462306a36Sopenharmony_ci	return res->status;
612562306a36Sopenharmony_ci}
612662306a36Sopenharmony_ci#else
612762306a36Sopenharmony_cistatic inline
612862306a36Sopenharmony_ciint decode_layoutreturn(struct xdr_stream *xdr,
612962306a36Sopenharmony_ci			       struct nfs4_layoutreturn_res *res)
613062306a36Sopenharmony_ci{
613162306a36Sopenharmony_ci	return 0;
613262306a36Sopenharmony_ci}
613362306a36Sopenharmony_ci
613462306a36Sopenharmony_cistatic int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
613562306a36Sopenharmony_ci			    struct nfs4_layoutget_res *res)
613662306a36Sopenharmony_ci{
613762306a36Sopenharmony_ci	return 0;
613862306a36Sopenharmony_ci}
613962306a36Sopenharmony_ci
614062306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
614162306a36Sopenharmony_ci
614262306a36Sopenharmony_ci/*
614362306a36Sopenharmony_ci * END OF "GENERIC" DECODE ROUTINES.
614462306a36Sopenharmony_ci */
614562306a36Sopenharmony_ci
614662306a36Sopenharmony_ci/*
614762306a36Sopenharmony_ci * Decode OPEN_DOWNGRADE response
614862306a36Sopenharmony_ci */
614962306a36Sopenharmony_cistatic int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp,
615062306a36Sopenharmony_ci				       struct xdr_stream *xdr,
615162306a36Sopenharmony_ci				       void *data)
615262306a36Sopenharmony_ci{
615362306a36Sopenharmony_ci	struct nfs_closeres *res = data;
615462306a36Sopenharmony_ci	struct compound_hdr hdr;
615562306a36Sopenharmony_ci	int status;
615662306a36Sopenharmony_ci
615762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
615862306a36Sopenharmony_ci	if (status)
615962306a36Sopenharmony_ci		goto out;
616062306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
616162306a36Sopenharmony_ci	if (status)
616262306a36Sopenharmony_ci		goto out;
616362306a36Sopenharmony_ci	status = decode_putfh(xdr);
616462306a36Sopenharmony_ci	if (status)
616562306a36Sopenharmony_ci		goto out;
616662306a36Sopenharmony_ci	if (res->lr_res) {
616762306a36Sopenharmony_ci		status = decode_layoutreturn(xdr, res->lr_res);
616862306a36Sopenharmony_ci		res->lr_ret = status;
616962306a36Sopenharmony_ci		if (status)
617062306a36Sopenharmony_ci			goto out;
617162306a36Sopenharmony_ci	}
617262306a36Sopenharmony_ci	status = decode_open_downgrade(xdr, res);
617362306a36Sopenharmony_ciout:
617462306a36Sopenharmony_ci	return status;
617562306a36Sopenharmony_ci}
617662306a36Sopenharmony_ci
617762306a36Sopenharmony_ci/*
617862306a36Sopenharmony_ci * Decode ACCESS response
617962306a36Sopenharmony_ci */
618062306a36Sopenharmony_cistatic int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
618162306a36Sopenharmony_ci			       void *data)
618262306a36Sopenharmony_ci{
618362306a36Sopenharmony_ci	struct nfs4_accessres *res = data;
618462306a36Sopenharmony_ci	struct compound_hdr hdr;
618562306a36Sopenharmony_ci	int status;
618662306a36Sopenharmony_ci
618762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
618862306a36Sopenharmony_ci	if (status)
618962306a36Sopenharmony_ci		goto out;
619062306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
619162306a36Sopenharmony_ci	if (status)
619262306a36Sopenharmony_ci		goto out;
619362306a36Sopenharmony_ci	status = decode_putfh(xdr);
619462306a36Sopenharmony_ci	if (status != 0)
619562306a36Sopenharmony_ci		goto out;
619662306a36Sopenharmony_ci	status = decode_access(xdr, &res->supported, &res->access);
619762306a36Sopenharmony_ci	if (status != 0)
619862306a36Sopenharmony_ci		goto out;
619962306a36Sopenharmony_ci	if (res->fattr)
620062306a36Sopenharmony_ci		decode_getfattr(xdr, res->fattr, res->server);
620162306a36Sopenharmony_ciout:
620262306a36Sopenharmony_ci	return status;
620362306a36Sopenharmony_ci}
620462306a36Sopenharmony_ci
620562306a36Sopenharmony_ci/*
620662306a36Sopenharmony_ci * Decode LOOKUP response
620762306a36Sopenharmony_ci */
620862306a36Sopenharmony_cistatic int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
620962306a36Sopenharmony_ci			       void *data)
621062306a36Sopenharmony_ci{
621162306a36Sopenharmony_ci	struct nfs4_lookup_res *res = data;
621262306a36Sopenharmony_ci	struct compound_hdr hdr;
621362306a36Sopenharmony_ci	int status;
621462306a36Sopenharmony_ci
621562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
621662306a36Sopenharmony_ci	if (status)
621762306a36Sopenharmony_ci		goto out;
621862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
621962306a36Sopenharmony_ci	if (status)
622062306a36Sopenharmony_ci		goto out;
622162306a36Sopenharmony_ci	status = decode_putfh(xdr);
622262306a36Sopenharmony_ci	if (status)
622362306a36Sopenharmony_ci		goto out;
622462306a36Sopenharmony_ci	status = decode_lookup(xdr);
622562306a36Sopenharmony_ci	if (status)
622662306a36Sopenharmony_ci		goto out;
622762306a36Sopenharmony_ci	status = decode_getfh(xdr, res->fh);
622862306a36Sopenharmony_ci	if (status)
622962306a36Sopenharmony_ci		goto out;
623062306a36Sopenharmony_ci	status = decode_getfattr(xdr, res->fattr, res->server);
623162306a36Sopenharmony_ciout:
623262306a36Sopenharmony_ci	return status;
623362306a36Sopenharmony_ci}
623462306a36Sopenharmony_ci
623562306a36Sopenharmony_ci/*
623662306a36Sopenharmony_ci * Decode LOOKUPP response
623762306a36Sopenharmony_ci */
623862306a36Sopenharmony_cistatic int nfs4_xdr_dec_lookupp(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
623962306a36Sopenharmony_ci		void *data)
624062306a36Sopenharmony_ci{
624162306a36Sopenharmony_ci	struct nfs4_lookupp_res *res = data;
624262306a36Sopenharmony_ci	struct compound_hdr hdr;
624362306a36Sopenharmony_ci	int status;
624462306a36Sopenharmony_ci
624562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
624662306a36Sopenharmony_ci	if (status)
624762306a36Sopenharmony_ci		goto out;
624862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
624962306a36Sopenharmony_ci	if (status)
625062306a36Sopenharmony_ci		goto out;
625162306a36Sopenharmony_ci	status = decode_putfh(xdr);
625262306a36Sopenharmony_ci	if (status)
625362306a36Sopenharmony_ci		goto out;
625462306a36Sopenharmony_ci	status = decode_lookupp(xdr);
625562306a36Sopenharmony_ci	if (status)
625662306a36Sopenharmony_ci		goto out;
625762306a36Sopenharmony_ci	status = decode_getfh(xdr, res->fh);
625862306a36Sopenharmony_ci	if (status)
625962306a36Sopenharmony_ci		goto out;
626062306a36Sopenharmony_ci	status = decode_getfattr(xdr, res->fattr, res->server);
626162306a36Sopenharmony_ciout:
626262306a36Sopenharmony_ci	return status;
626362306a36Sopenharmony_ci}
626462306a36Sopenharmony_ci
626562306a36Sopenharmony_ci/*
626662306a36Sopenharmony_ci * Decode LOOKUP_ROOT response
626762306a36Sopenharmony_ci */
626862306a36Sopenharmony_cistatic int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp,
626962306a36Sopenharmony_ci				    struct xdr_stream *xdr,
627062306a36Sopenharmony_ci				    void *data)
627162306a36Sopenharmony_ci{
627262306a36Sopenharmony_ci	struct nfs4_lookup_res *res = data;
627362306a36Sopenharmony_ci	struct compound_hdr hdr;
627462306a36Sopenharmony_ci	int status;
627562306a36Sopenharmony_ci
627662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
627762306a36Sopenharmony_ci	if (status)
627862306a36Sopenharmony_ci		goto out;
627962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
628062306a36Sopenharmony_ci	if (status)
628162306a36Sopenharmony_ci		goto out;
628262306a36Sopenharmony_ci	status = decode_putrootfh(xdr);
628362306a36Sopenharmony_ci	if (status)
628462306a36Sopenharmony_ci		goto out;
628562306a36Sopenharmony_ci	status = decode_getfh(xdr, res->fh);
628662306a36Sopenharmony_ci	if (status == 0)
628762306a36Sopenharmony_ci		status = decode_getfattr(xdr, res->fattr, res->server);
628862306a36Sopenharmony_ciout:
628962306a36Sopenharmony_ci	return status;
629062306a36Sopenharmony_ci}
629162306a36Sopenharmony_ci
629262306a36Sopenharmony_ci/*
629362306a36Sopenharmony_ci * Decode REMOVE response
629462306a36Sopenharmony_ci */
629562306a36Sopenharmony_cistatic int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
629662306a36Sopenharmony_ci			       void *data)
629762306a36Sopenharmony_ci{
629862306a36Sopenharmony_ci	struct nfs_removeres *res = data;
629962306a36Sopenharmony_ci	struct compound_hdr hdr;
630062306a36Sopenharmony_ci	int status;
630162306a36Sopenharmony_ci
630262306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
630362306a36Sopenharmony_ci	if (status)
630462306a36Sopenharmony_ci		goto out;
630562306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
630662306a36Sopenharmony_ci	if (status)
630762306a36Sopenharmony_ci		goto out;
630862306a36Sopenharmony_ci	status = decode_putfh(xdr);
630962306a36Sopenharmony_ci	if (status)
631062306a36Sopenharmony_ci		goto out;
631162306a36Sopenharmony_ci	status = decode_remove(xdr, &res->cinfo);
631262306a36Sopenharmony_ciout:
631362306a36Sopenharmony_ci	return status;
631462306a36Sopenharmony_ci}
631562306a36Sopenharmony_ci
631662306a36Sopenharmony_ci/*
631762306a36Sopenharmony_ci * Decode RENAME response
631862306a36Sopenharmony_ci */
631962306a36Sopenharmony_cistatic int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
632062306a36Sopenharmony_ci			       void *data)
632162306a36Sopenharmony_ci{
632262306a36Sopenharmony_ci	struct nfs_renameres *res = data;
632362306a36Sopenharmony_ci	struct compound_hdr hdr;
632462306a36Sopenharmony_ci	int status;
632562306a36Sopenharmony_ci
632662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
632762306a36Sopenharmony_ci	if (status)
632862306a36Sopenharmony_ci		goto out;
632962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
633062306a36Sopenharmony_ci	if (status)
633162306a36Sopenharmony_ci		goto out;
633262306a36Sopenharmony_ci	status = decode_putfh(xdr);
633362306a36Sopenharmony_ci	if (status)
633462306a36Sopenharmony_ci		goto out;
633562306a36Sopenharmony_ci	status = decode_savefh(xdr);
633662306a36Sopenharmony_ci	if (status)
633762306a36Sopenharmony_ci		goto out;
633862306a36Sopenharmony_ci	status = decode_putfh(xdr);
633962306a36Sopenharmony_ci	if (status)
634062306a36Sopenharmony_ci		goto out;
634162306a36Sopenharmony_ci	status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo);
634262306a36Sopenharmony_ciout:
634362306a36Sopenharmony_ci	return status;
634462306a36Sopenharmony_ci}
634562306a36Sopenharmony_ci
634662306a36Sopenharmony_ci/*
634762306a36Sopenharmony_ci * Decode LINK response
634862306a36Sopenharmony_ci */
634962306a36Sopenharmony_cistatic int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
635062306a36Sopenharmony_ci			     void *data)
635162306a36Sopenharmony_ci{
635262306a36Sopenharmony_ci	struct nfs4_link_res *res = data;
635362306a36Sopenharmony_ci	struct compound_hdr hdr;
635462306a36Sopenharmony_ci	int status;
635562306a36Sopenharmony_ci
635662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
635762306a36Sopenharmony_ci	if (status)
635862306a36Sopenharmony_ci		goto out;
635962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
636062306a36Sopenharmony_ci	if (status)
636162306a36Sopenharmony_ci		goto out;
636262306a36Sopenharmony_ci	status = decode_putfh(xdr);
636362306a36Sopenharmony_ci	if (status)
636462306a36Sopenharmony_ci		goto out;
636562306a36Sopenharmony_ci	status = decode_savefh(xdr);
636662306a36Sopenharmony_ci	if (status)
636762306a36Sopenharmony_ci		goto out;
636862306a36Sopenharmony_ci	status = decode_putfh(xdr);
636962306a36Sopenharmony_ci	if (status)
637062306a36Sopenharmony_ci		goto out;
637162306a36Sopenharmony_ci	status = decode_link(xdr, &res->cinfo);
637262306a36Sopenharmony_ci	if (status)
637362306a36Sopenharmony_ci		goto out;
637462306a36Sopenharmony_ci	/*
637562306a36Sopenharmony_ci	 * Note order: OP_LINK leaves the directory as the current
637662306a36Sopenharmony_ci	 *             filehandle.
637762306a36Sopenharmony_ci	 */
637862306a36Sopenharmony_ci	status = decode_restorefh(xdr);
637962306a36Sopenharmony_ci	if (status)
638062306a36Sopenharmony_ci		goto out;
638162306a36Sopenharmony_ci	decode_getfattr(xdr, res->fattr, res->server);
638262306a36Sopenharmony_ciout:
638362306a36Sopenharmony_ci	return status;
638462306a36Sopenharmony_ci}
638562306a36Sopenharmony_ci
638662306a36Sopenharmony_ci/*
638762306a36Sopenharmony_ci * Decode CREATE response
638862306a36Sopenharmony_ci */
638962306a36Sopenharmony_cistatic int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
639062306a36Sopenharmony_ci			       void *data)
639162306a36Sopenharmony_ci{
639262306a36Sopenharmony_ci	struct nfs4_create_res *res = data;
639362306a36Sopenharmony_ci	struct compound_hdr hdr;
639462306a36Sopenharmony_ci	int status;
639562306a36Sopenharmony_ci
639662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
639762306a36Sopenharmony_ci	if (status)
639862306a36Sopenharmony_ci		goto out;
639962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
640062306a36Sopenharmony_ci	if (status)
640162306a36Sopenharmony_ci		goto out;
640262306a36Sopenharmony_ci	status = decode_putfh(xdr);
640362306a36Sopenharmony_ci	if (status)
640462306a36Sopenharmony_ci		goto out;
640562306a36Sopenharmony_ci	status = decode_create(xdr, &res->dir_cinfo);
640662306a36Sopenharmony_ci	if (status)
640762306a36Sopenharmony_ci		goto out;
640862306a36Sopenharmony_ci	status = decode_getfh(xdr, res->fh);
640962306a36Sopenharmony_ci	if (status)
641062306a36Sopenharmony_ci		goto out;
641162306a36Sopenharmony_ci	decode_getfattr(xdr, res->fattr, res->server);
641262306a36Sopenharmony_ciout:
641362306a36Sopenharmony_ci	return status;
641462306a36Sopenharmony_ci}
641562306a36Sopenharmony_ci
641662306a36Sopenharmony_ci/*
641762306a36Sopenharmony_ci * Decode SYMLINK response
641862306a36Sopenharmony_ci */
641962306a36Sopenharmony_cistatic int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
642062306a36Sopenharmony_ci				void *res)
642162306a36Sopenharmony_ci{
642262306a36Sopenharmony_ci	return nfs4_xdr_dec_create(rqstp, xdr, res);
642362306a36Sopenharmony_ci}
642462306a36Sopenharmony_ci
642562306a36Sopenharmony_ci/*
642662306a36Sopenharmony_ci * Decode GETATTR response
642762306a36Sopenharmony_ci */
642862306a36Sopenharmony_cistatic int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
642962306a36Sopenharmony_ci				void *data)
643062306a36Sopenharmony_ci{
643162306a36Sopenharmony_ci	struct nfs4_getattr_res *res = data;
643262306a36Sopenharmony_ci	struct compound_hdr hdr;
643362306a36Sopenharmony_ci	int status;
643462306a36Sopenharmony_ci
643562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
643662306a36Sopenharmony_ci	if (status)
643762306a36Sopenharmony_ci		goto out;
643862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
643962306a36Sopenharmony_ci	if (status)
644062306a36Sopenharmony_ci		goto out;
644162306a36Sopenharmony_ci	status = decode_putfh(xdr);
644262306a36Sopenharmony_ci	if (status)
644362306a36Sopenharmony_ci		goto out;
644462306a36Sopenharmony_ci	status = decode_getfattr(xdr, res->fattr, res->server);
644562306a36Sopenharmony_ciout:
644662306a36Sopenharmony_ci	return status;
644762306a36Sopenharmony_ci}
644862306a36Sopenharmony_ci
644962306a36Sopenharmony_ci/*
645062306a36Sopenharmony_ci * Encode an SETACL request
645162306a36Sopenharmony_ci */
645262306a36Sopenharmony_cistatic void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr,
645362306a36Sopenharmony_ci				const void *data)
645462306a36Sopenharmony_ci{
645562306a36Sopenharmony_ci	const struct nfs_setaclargs *args = data;
645662306a36Sopenharmony_ci	struct compound_hdr hdr = {
645762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
645862306a36Sopenharmony_ci	};
645962306a36Sopenharmony_ci
646062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
646162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
646262306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
646362306a36Sopenharmony_ci	encode_setacl(xdr, args, &hdr);
646462306a36Sopenharmony_ci	encode_nops(&hdr);
646562306a36Sopenharmony_ci}
646662306a36Sopenharmony_ci
646762306a36Sopenharmony_ci/*
646862306a36Sopenharmony_ci * Decode SETACL response
646962306a36Sopenharmony_ci */
647062306a36Sopenharmony_cistatic int
647162306a36Sopenharmony_cinfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
647262306a36Sopenharmony_ci		    void *data)
647362306a36Sopenharmony_ci{
647462306a36Sopenharmony_ci	struct nfs_setaclres *res = data;
647562306a36Sopenharmony_ci	struct compound_hdr hdr;
647662306a36Sopenharmony_ci	int status;
647762306a36Sopenharmony_ci
647862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
647962306a36Sopenharmony_ci	if (status)
648062306a36Sopenharmony_ci		goto out;
648162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
648262306a36Sopenharmony_ci	if (status)
648362306a36Sopenharmony_ci		goto out;
648462306a36Sopenharmony_ci	status = decode_putfh(xdr);
648562306a36Sopenharmony_ci	if (status)
648662306a36Sopenharmony_ci		goto out;
648762306a36Sopenharmony_ci	status = decode_setattr(xdr);
648862306a36Sopenharmony_ciout:
648962306a36Sopenharmony_ci	return status;
649062306a36Sopenharmony_ci}
649162306a36Sopenharmony_ci
649262306a36Sopenharmony_ci/*
649362306a36Sopenharmony_ci * Decode GETACL response
649462306a36Sopenharmony_ci */
649562306a36Sopenharmony_cistatic int
649662306a36Sopenharmony_cinfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
649762306a36Sopenharmony_ci		    void *data)
649862306a36Sopenharmony_ci{
649962306a36Sopenharmony_ci	struct nfs_getaclres *res = data;
650062306a36Sopenharmony_ci	struct compound_hdr hdr;
650162306a36Sopenharmony_ci	int status;
650262306a36Sopenharmony_ci
650362306a36Sopenharmony_ci	if (res->acl_scratch != NULL)
650462306a36Sopenharmony_ci		xdr_set_scratch_page(xdr, res->acl_scratch);
650562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
650662306a36Sopenharmony_ci	if (status)
650762306a36Sopenharmony_ci		goto out;
650862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
650962306a36Sopenharmony_ci	if (status)
651062306a36Sopenharmony_ci		goto out;
651162306a36Sopenharmony_ci	status = decode_putfh(xdr);
651262306a36Sopenharmony_ci	if (status)
651362306a36Sopenharmony_ci		goto out;
651462306a36Sopenharmony_ci	status = decode_getacl(xdr, rqstp, res, res->acl_type);
651562306a36Sopenharmony_ci
651662306a36Sopenharmony_ciout:
651762306a36Sopenharmony_ci	return status;
651862306a36Sopenharmony_ci}
651962306a36Sopenharmony_ci
652062306a36Sopenharmony_ci/*
652162306a36Sopenharmony_ci * Decode CLOSE response
652262306a36Sopenharmony_ci */
652362306a36Sopenharmony_cistatic int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
652462306a36Sopenharmony_ci			      void *data)
652562306a36Sopenharmony_ci{
652662306a36Sopenharmony_ci	struct nfs_closeres *res = data;
652762306a36Sopenharmony_ci	struct compound_hdr hdr;
652862306a36Sopenharmony_ci	int status;
652962306a36Sopenharmony_ci
653062306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
653162306a36Sopenharmony_ci	if (status)
653262306a36Sopenharmony_ci		goto out;
653362306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
653462306a36Sopenharmony_ci	if (status)
653562306a36Sopenharmony_ci		goto out;
653662306a36Sopenharmony_ci	status = decode_putfh(xdr);
653762306a36Sopenharmony_ci	if (status)
653862306a36Sopenharmony_ci		goto out;
653962306a36Sopenharmony_ci	if (res->lr_res) {
654062306a36Sopenharmony_ci		status = decode_layoutreturn(xdr, res->lr_res);
654162306a36Sopenharmony_ci		res->lr_ret = status;
654262306a36Sopenharmony_ci		if (status)
654362306a36Sopenharmony_ci			goto out;
654462306a36Sopenharmony_ci	}
654562306a36Sopenharmony_ci	if (res->fattr != NULL) {
654662306a36Sopenharmony_ci		status = decode_getfattr(xdr, res->fattr, res->server);
654762306a36Sopenharmony_ci		if (status != 0)
654862306a36Sopenharmony_ci			goto out;
654962306a36Sopenharmony_ci	}
655062306a36Sopenharmony_ci	status = decode_close(xdr, res);
655162306a36Sopenharmony_ciout:
655262306a36Sopenharmony_ci	return status;
655362306a36Sopenharmony_ci}
655462306a36Sopenharmony_ci
655562306a36Sopenharmony_ci/*
655662306a36Sopenharmony_ci * Decode OPEN response
655762306a36Sopenharmony_ci */
655862306a36Sopenharmony_cistatic int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
655962306a36Sopenharmony_ci			     void *data)
656062306a36Sopenharmony_ci{
656162306a36Sopenharmony_ci	struct nfs_openres *res = data;
656262306a36Sopenharmony_ci	struct compound_hdr hdr;
656362306a36Sopenharmony_ci	int status;
656462306a36Sopenharmony_ci
656562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
656662306a36Sopenharmony_ci	if (status)
656762306a36Sopenharmony_ci		goto out;
656862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
656962306a36Sopenharmony_ci	if (status)
657062306a36Sopenharmony_ci		goto out;
657162306a36Sopenharmony_ci	status = decode_putfh(xdr);
657262306a36Sopenharmony_ci	if (status)
657362306a36Sopenharmony_ci		goto out;
657462306a36Sopenharmony_ci	status = decode_open(xdr, res);
657562306a36Sopenharmony_ci	if (status)
657662306a36Sopenharmony_ci		goto out;
657762306a36Sopenharmony_ci	status = decode_getfh(xdr, &res->fh);
657862306a36Sopenharmony_ci	if (status)
657962306a36Sopenharmony_ci		goto out;
658062306a36Sopenharmony_ci	if (res->access_request)
658162306a36Sopenharmony_ci		decode_access(xdr, &res->access_supported, &res->access_result);
658262306a36Sopenharmony_ci	decode_getfattr(xdr, res->f_attr, res->server);
658362306a36Sopenharmony_ci	if (res->lg_res)
658462306a36Sopenharmony_ci		decode_layoutget(xdr, rqstp, res->lg_res);
658562306a36Sopenharmony_ciout:
658662306a36Sopenharmony_ci	return status;
658762306a36Sopenharmony_ci}
658862306a36Sopenharmony_ci
658962306a36Sopenharmony_ci/*
659062306a36Sopenharmony_ci * Decode OPEN_CONFIRM response
659162306a36Sopenharmony_ci */
659262306a36Sopenharmony_cistatic int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp,
659362306a36Sopenharmony_ci				     struct xdr_stream *xdr,
659462306a36Sopenharmony_ci				     void *data)
659562306a36Sopenharmony_ci{
659662306a36Sopenharmony_ci	struct nfs_open_confirmres *res = data;
659762306a36Sopenharmony_ci	struct compound_hdr hdr;
659862306a36Sopenharmony_ci	int status;
659962306a36Sopenharmony_ci
660062306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
660162306a36Sopenharmony_ci	if (status)
660262306a36Sopenharmony_ci		goto out;
660362306a36Sopenharmony_ci	status = decode_putfh(xdr);
660462306a36Sopenharmony_ci	if (status)
660562306a36Sopenharmony_ci		goto out;
660662306a36Sopenharmony_ci	status = decode_open_confirm(xdr, res);
660762306a36Sopenharmony_ciout:
660862306a36Sopenharmony_ci	return status;
660962306a36Sopenharmony_ci}
661062306a36Sopenharmony_ci
661162306a36Sopenharmony_ci/*
661262306a36Sopenharmony_ci * Decode OPEN response
661362306a36Sopenharmony_ci */
661462306a36Sopenharmony_cistatic int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
661562306a36Sopenharmony_ci				    struct xdr_stream *xdr,
661662306a36Sopenharmony_ci				    void *data)
661762306a36Sopenharmony_ci{
661862306a36Sopenharmony_ci	struct nfs_openres *res = data;
661962306a36Sopenharmony_ci	struct compound_hdr hdr;
662062306a36Sopenharmony_ci	int status;
662162306a36Sopenharmony_ci
662262306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
662362306a36Sopenharmony_ci	if (status)
662462306a36Sopenharmony_ci		goto out;
662562306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
662662306a36Sopenharmony_ci	if (status)
662762306a36Sopenharmony_ci		goto out;
662862306a36Sopenharmony_ci	status = decode_putfh(xdr);
662962306a36Sopenharmony_ci	if (status)
663062306a36Sopenharmony_ci		goto out;
663162306a36Sopenharmony_ci	status = decode_open(xdr, res);
663262306a36Sopenharmony_ci	if (status)
663362306a36Sopenharmony_ci		goto out;
663462306a36Sopenharmony_ci	if (res->access_request)
663562306a36Sopenharmony_ci		decode_access(xdr, &res->access_supported, &res->access_result);
663662306a36Sopenharmony_ci	decode_getfattr(xdr, res->f_attr, res->server);
663762306a36Sopenharmony_ci	if (res->lg_res)
663862306a36Sopenharmony_ci		decode_layoutget(xdr, rqstp, res->lg_res);
663962306a36Sopenharmony_ciout:
664062306a36Sopenharmony_ci	return status;
664162306a36Sopenharmony_ci}
664262306a36Sopenharmony_ci
664362306a36Sopenharmony_ci/*
664462306a36Sopenharmony_ci * Decode SETATTR response
664562306a36Sopenharmony_ci */
664662306a36Sopenharmony_cistatic int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp,
664762306a36Sopenharmony_ci				struct xdr_stream *xdr,
664862306a36Sopenharmony_ci				void *data)
664962306a36Sopenharmony_ci{
665062306a36Sopenharmony_ci	struct nfs_setattrres *res = data;
665162306a36Sopenharmony_ci	struct compound_hdr hdr;
665262306a36Sopenharmony_ci	int status;
665362306a36Sopenharmony_ci
665462306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
665562306a36Sopenharmony_ci	if (status)
665662306a36Sopenharmony_ci		goto out;
665762306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
665862306a36Sopenharmony_ci	if (status)
665962306a36Sopenharmony_ci		goto out;
666062306a36Sopenharmony_ci	status = decode_putfh(xdr);
666162306a36Sopenharmony_ci	if (status)
666262306a36Sopenharmony_ci		goto out;
666362306a36Sopenharmony_ci	status = decode_setattr(xdr);
666462306a36Sopenharmony_ci	if (status)
666562306a36Sopenharmony_ci		goto out;
666662306a36Sopenharmony_ci	decode_getfattr(xdr, res->fattr, res->server);
666762306a36Sopenharmony_ciout:
666862306a36Sopenharmony_ci	return status;
666962306a36Sopenharmony_ci}
667062306a36Sopenharmony_ci
667162306a36Sopenharmony_ci/*
667262306a36Sopenharmony_ci * Decode LOCK response
667362306a36Sopenharmony_ci */
667462306a36Sopenharmony_cistatic int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
667562306a36Sopenharmony_ci			     void *data)
667662306a36Sopenharmony_ci{
667762306a36Sopenharmony_ci	struct nfs_lock_res *res = data;
667862306a36Sopenharmony_ci	struct compound_hdr hdr;
667962306a36Sopenharmony_ci	int status;
668062306a36Sopenharmony_ci
668162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
668262306a36Sopenharmony_ci	if (status)
668362306a36Sopenharmony_ci		goto out;
668462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
668562306a36Sopenharmony_ci	if (status)
668662306a36Sopenharmony_ci		goto out;
668762306a36Sopenharmony_ci	status = decode_putfh(xdr);
668862306a36Sopenharmony_ci	if (status)
668962306a36Sopenharmony_ci		goto out;
669062306a36Sopenharmony_ci	status = decode_lock(xdr, res);
669162306a36Sopenharmony_ciout:
669262306a36Sopenharmony_ci	return status;
669362306a36Sopenharmony_ci}
669462306a36Sopenharmony_ci
669562306a36Sopenharmony_ci/*
669662306a36Sopenharmony_ci * Decode LOCKT response
669762306a36Sopenharmony_ci */
669862306a36Sopenharmony_cistatic int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
669962306a36Sopenharmony_ci			      void *data)
670062306a36Sopenharmony_ci{
670162306a36Sopenharmony_ci	struct nfs_lockt_res *res = data;
670262306a36Sopenharmony_ci	struct compound_hdr hdr;
670362306a36Sopenharmony_ci	int status;
670462306a36Sopenharmony_ci
670562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
670662306a36Sopenharmony_ci	if (status)
670762306a36Sopenharmony_ci		goto out;
670862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
670962306a36Sopenharmony_ci	if (status)
671062306a36Sopenharmony_ci		goto out;
671162306a36Sopenharmony_ci	status = decode_putfh(xdr);
671262306a36Sopenharmony_ci	if (status)
671362306a36Sopenharmony_ci		goto out;
671462306a36Sopenharmony_ci	status = decode_lockt(xdr, res);
671562306a36Sopenharmony_ciout:
671662306a36Sopenharmony_ci	return status;
671762306a36Sopenharmony_ci}
671862306a36Sopenharmony_ci
671962306a36Sopenharmony_ci/*
672062306a36Sopenharmony_ci * Decode LOCKU response
672162306a36Sopenharmony_ci */
672262306a36Sopenharmony_cistatic int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
672362306a36Sopenharmony_ci			      void *data)
672462306a36Sopenharmony_ci{
672562306a36Sopenharmony_ci	struct nfs_locku_res *res = data;
672662306a36Sopenharmony_ci	struct compound_hdr hdr;
672762306a36Sopenharmony_ci	int status;
672862306a36Sopenharmony_ci
672962306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
673062306a36Sopenharmony_ci	if (status)
673162306a36Sopenharmony_ci		goto out;
673262306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
673362306a36Sopenharmony_ci	if (status)
673462306a36Sopenharmony_ci		goto out;
673562306a36Sopenharmony_ci	status = decode_putfh(xdr);
673662306a36Sopenharmony_ci	if (status)
673762306a36Sopenharmony_ci		goto out;
673862306a36Sopenharmony_ci	status = decode_locku(xdr, res);
673962306a36Sopenharmony_ciout:
674062306a36Sopenharmony_ci	return status;
674162306a36Sopenharmony_ci}
674262306a36Sopenharmony_ci
674362306a36Sopenharmony_cistatic int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp,
674462306a36Sopenharmony_ci					  struct xdr_stream *xdr, void *dummy)
674562306a36Sopenharmony_ci{
674662306a36Sopenharmony_ci	struct compound_hdr hdr;
674762306a36Sopenharmony_ci	int status;
674862306a36Sopenharmony_ci
674962306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
675062306a36Sopenharmony_ci	if (!status)
675162306a36Sopenharmony_ci		status = decode_release_lockowner(xdr);
675262306a36Sopenharmony_ci	return status;
675362306a36Sopenharmony_ci}
675462306a36Sopenharmony_ci
675562306a36Sopenharmony_ci/*
675662306a36Sopenharmony_ci * Decode READLINK response
675762306a36Sopenharmony_ci */
675862306a36Sopenharmony_cistatic int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp,
675962306a36Sopenharmony_ci				 struct xdr_stream *xdr,
676062306a36Sopenharmony_ci				 void *data)
676162306a36Sopenharmony_ci{
676262306a36Sopenharmony_ci	struct nfs4_readlink_res *res = data;
676362306a36Sopenharmony_ci	struct compound_hdr hdr;
676462306a36Sopenharmony_ci	int status;
676562306a36Sopenharmony_ci
676662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
676762306a36Sopenharmony_ci	if (status)
676862306a36Sopenharmony_ci		goto out;
676962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
677062306a36Sopenharmony_ci	if (status)
677162306a36Sopenharmony_ci		goto out;
677262306a36Sopenharmony_ci	status = decode_putfh(xdr);
677362306a36Sopenharmony_ci	if (status)
677462306a36Sopenharmony_ci		goto out;
677562306a36Sopenharmony_ci	status = decode_readlink(xdr, rqstp);
677662306a36Sopenharmony_ciout:
677762306a36Sopenharmony_ci	return status;
677862306a36Sopenharmony_ci}
677962306a36Sopenharmony_ci
678062306a36Sopenharmony_ci/*
678162306a36Sopenharmony_ci * Decode READDIR response
678262306a36Sopenharmony_ci */
678362306a36Sopenharmony_cistatic int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
678462306a36Sopenharmony_ci				void *data)
678562306a36Sopenharmony_ci{
678662306a36Sopenharmony_ci	struct nfs4_readdir_res *res = data;
678762306a36Sopenharmony_ci	struct compound_hdr hdr;
678862306a36Sopenharmony_ci	int status;
678962306a36Sopenharmony_ci
679062306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
679162306a36Sopenharmony_ci	if (status)
679262306a36Sopenharmony_ci		goto out;
679362306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
679462306a36Sopenharmony_ci	if (status)
679562306a36Sopenharmony_ci		goto out;
679662306a36Sopenharmony_ci	status = decode_putfh(xdr);
679762306a36Sopenharmony_ci	if (status)
679862306a36Sopenharmony_ci		goto out;
679962306a36Sopenharmony_ci	status = decode_readdir(xdr, rqstp, res);
680062306a36Sopenharmony_ciout:
680162306a36Sopenharmony_ci	return status;
680262306a36Sopenharmony_ci}
680362306a36Sopenharmony_ci
680462306a36Sopenharmony_ci/*
680562306a36Sopenharmony_ci * Decode Read response
680662306a36Sopenharmony_ci */
680762306a36Sopenharmony_cistatic int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
680862306a36Sopenharmony_ci			     void *data)
680962306a36Sopenharmony_ci{
681062306a36Sopenharmony_ci	struct nfs_pgio_res *res = data;
681162306a36Sopenharmony_ci	struct compound_hdr hdr;
681262306a36Sopenharmony_ci	int status;
681362306a36Sopenharmony_ci
681462306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
681562306a36Sopenharmony_ci	res->op_status = hdr.status;
681662306a36Sopenharmony_ci	if (status)
681762306a36Sopenharmony_ci		goto out;
681862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
681962306a36Sopenharmony_ci	if (status)
682062306a36Sopenharmony_ci		goto out;
682162306a36Sopenharmony_ci	status = decode_putfh(xdr);
682262306a36Sopenharmony_ci	if (status)
682362306a36Sopenharmony_ci		goto out;
682462306a36Sopenharmony_ci	status = decode_read(xdr, rqstp, res);
682562306a36Sopenharmony_ci	if (!status)
682662306a36Sopenharmony_ci		status = res->count;
682762306a36Sopenharmony_ciout:
682862306a36Sopenharmony_ci	return status;
682962306a36Sopenharmony_ci}
683062306a36Sopenharmony_ci
683162306a36Sopenharmony_ci/*
683262306a36Sopenharmony_ci * Decode WRITE response
683362306a36Sopenharmony_ci */
683462306a36Sopenharmony_cistatic int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
683562306a36Sopenharmony_ci			      void *data)
683662306a36Sopenharmony_ci{
683762306a36Sopenharmony_ci	struct nfs_pgio_res *res = data;
683862306a36Sopenharmony_ci	struct compound_hdr hdr;
683962306a36Sopenharmony_ci	int status;
684062306a36Sopenharmony_ci
684162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
684262306a36Sopenharmony_ci	res->op_status = hdr.status;
684362306a36Sopenharmony_ci	if (status)
684462306a36Sopenharmony_ci		goto out;
684562306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
684662306a36Sopenharmony_ci	if (status)
684762306a36Sopenharmony_ci		goto out;
684862306a36Sopenharmony_ci	status = decode_putfh(xdr);
684962306a36Sopenharmony_ci	if (status)
685062306a36Sopenharmony_ci		goto out;
685162306a36Sopenharmony_ci	status = decode_write(xdr, res);
685262306a36Sopenharmony_ci	if (status)
685362306a36Sopenharmony_ci		goto out;
685462306a36Sopenharmony_ci	if (res->fattr)
685562306a36Sopenharmony_ci		decode_getfattr(xdr, res->fattr, res->server);
685662306a36Sopenharmony_ci	if (!status)
685762306a36Sopenharmony_ci		status = res->count;
685862306a36Sopenharmony_ciout:
685962306a36Sopenharmony_ci	return status;
686062306a36Sopenharmony_ci}
686162306a36Sopenharmony_ci
686262306a36Sopenharmony_ci/*
686362306a36Sopenharmony_ci * Decode COMMIT response
686462306a36Sopenharmony_ci */
686562306a36Sopenharmony_cistatic int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
686662306a36Sopenharmony_ci			       void *data)
686762306a36Sopenharmony_ci{
686862306a36Sopenharmony_ci	struct nfs_commitres *res = data;
686962306a36Sopenharmony_ci	struct compound_hdr hdr;
687062306a36Sopenharmony_ci	int status;
687162306a36Sopenharmony_ci
687262306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
687362306a36Sopenharmony_ci	res->op_status = hdr.status;
687462306a36Sopenharmony_ci	if (status)
687562306a36Sopenharmony_ci		goto out;
687662306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
687762306a36Sopenharmony_ci	if (status)
687862306a36Sopenharmony_ci		goto out;
687962306a36Sopenharmony_ci	status = decode_putfh(xdr);
688062306a36Sopenharmony_ci	if (status)
688162306a36Sopenharmony_ci		goto out;
688262306a36Sopenharmony_ci	status = decode_commit(xdr, res);
688362306a36Sopenharmony_ciout:
688462306a36Sopenharmony_ci	return status;
688562306a36Sopenharmony_ci}
688662306a36Sopenharmony_ci
688762306a36Sopenharmony_ci/*
688862306a36Sopenharmony_ci * Decode FSINFO response
688962306a36Sopenharmony_ci */
689062306a36Sopenharmony_cistatic int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
689162306a36Sopenharmony_ci			       void *data)
689262306a36Sopenharmony_ci{
689362306a36Sopenharmony_ci	struct nfs4_fsinfo_res *res = data;
689462306a36Sopenharmony_ci	struct compound_hdr hdr;
689562306a36Sopenharmony_ci	int status;
689662306a36Sopenharmony_ci
689762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
689862306a36Sopenharmony_ci	if (!status)
689962306a36Sopenharmony_ci		status = decode_sequence(xdr, &res->seq_res, req);
690062306a36Sopenharmony_ci	if (!status)
690162306a36Sopenharmony_ci		status = decode_putfh(xdr);
690262306a36Sopenharmony_ci	if (!status)
690362306a36Sopenharmony_ci		status = decode_fsinfo(xdr, res->fsinfo);
690462306a36Sopenharmony_ci	return status;
690562306a36Sopenharmony_ci}
690662306a36Sopenharmony_ci
690762306a36Sopenharmony_ci/*
690862306a36Sopenharmony_ci * Decode PATHCONF response
690962306a36Sopenharmony_ci */
691062306a36Sopenharmony_cistatic int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
691162306a36Sopenharmony_ci				 void *data)
691262306a36Sopenharmony_ci{
691362306a36Sopenharmony_ci	struct nfs4_pathconf_res *res = data;
691462306a36Sopenharmony_ci	struct compound_hdr hdr;
691562306a36Sopenharmony_ci	int status;
691662306a36Sopenharmony_ci
691762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
691862306a36Sopenharmony_ci	if (!status)
691962306a36Sopenharmony_ci		status = decode_sequence(xdr, &res->seq_res, req);
692062306a36Sopenharmony_ci	if (!status)
692162306a36Sopenharmony_ci		status = decode_putfh(xdr);
692262306a36Sopenharmony_ci	if (!status)
692362306a36Sopenharmony_ci		status = decode_pathconf(xdr, res->pathconf);
692462306a36Sopenharmony_ci	return status;
692562306a36Sopenharmony_ci}
692662306a36Sopenharmony_ci
692762306a36Sopenharmony_ci/*
692862306a36Sopenharmony_ci * Decode STATFS response
692962306a36Sopenharmony_ci */
693062306a36Sopenharmony_cistatic int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
693162306a36Sopenharmony_ci			       void *data)
693262306a36Sopenharmony_ci{
693362306a36Sopenharmony_ci	struct nfs4_statfs_res *res = data;
693462306a36Sopenharmony_ci	struct compound_hdr hdr;
693562306a36Sopenharmony_ci	int status;
693662306a36Sopenharmony_ci
693762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
693862306a36Sopenharmony_ci	if (!status)
693962306a36Sopenharmony_ci		status = decode_sequence(xdr, &res->seq_res, req);
694062306a36Sopenharmony_ci	if (!status)
694162306a36Sopenharmony_ci		status = decode_putfh(xdr);
694262306a36Sopenharmony_ci	if (!status)
694362306a36Sopenharmony_ci		status = decode_statfs(xdr, res->fsstat);
694462306a36Sopenharmony_ci	return status;
694562306a36Sopenharmony_ci}
694662306a36Sopenharmony_ci
694762306a36Sopenharmony_ci/*
694862306a36Sopenharmony_ci * Decode GETATTR_BITMAP response
694962306a36Sopenharmony_ci */
695062306a36Sopenharmony_cistatic int nfs4_xdr_dec_server_caps(struct rpc_rqst *req,
695162306a36Sopenharmony_ci				    struct xdr_stream *xdr,
695262306a36Sopenharmony_ci				    void *data)
695362306a36Sopenharmony_ci{
695462306a36Sopenharmony_ci	struct nfs4_server_caps_res *res = data;
695562306a36Sopenharmony_ci	struct compound_hdr hdr;
695662306a36Sopenharmony_ci	int status;
695762306a36Sopenharmony_ci
695862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
695962306a36Sopenharmony_ci	if (status)
696062306a36Sopenharmony_ci		goto out;
696162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, req);
696262306a36Sopenharmony_ci	if (status)
696362306a36Sopenharmony_ci		goto out;
696462306a36Sopenharmony_ci	status = decode_putfh(xdr);
696562306a36Sopenharmony_ci	if (status)
696662306a36Sopenharmony_ci		goto out;
696762306a36Sopenharmony_ci	status = decode_server_caps(xdr, res);
696862306a36Sopenharmony_ciout:
696962306a36Sopenharmony_ci	return status;
697062306a36Sopenharmony_ci}
697162306a36Sopenharmony_ci
697262306a36Sopenharmony_ci/*
697362306a36Sopenharmony_ci * Decode RENEW response
697462306a36Sopenharmony_ci */
697562306a36Sopenharmony_cistatic int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
697662306a36Sopenharmony_ci			      void *__unused)
697762306a36Sopenharmony_ci{
697862306a36Sopenharmony_ci	struct compound_hdr hdr;
697962306a36Sopenharmony_ci	int status;
698062306a36Sopenharmony_ci
698162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
698262306a36Sopenharmony_ci	if (!status)
698362306a36Sopenharmony_ci		status = decode_renew(xdr);
698462306a36Sopenharmony_ci	return status;
698562306a36Sopenharmony_ci}
698662306a36Sopenharmony_ci
698762306a36Sopenharmony_ci/*
698862306a36Sopenharmony_ci * Decode SETCLIENTID response
698962306a36Sopenharmony_ci */
699062306a36Sopenharmony_cistatic int nfs4_xdr_dec_setclientid(struct rpc_rqst *req,
699162306a36Sopenharmony_ci				    struct xdr_stream *xdr,
699262306a36Sopenharmony_ci				    void *data)
699362306a36Sopenharmony_ci{
699462306a36Sopenharmony_ci	struct nfs4_setclientid_res *res = data;
699562306a36Sopenharmony_ci	struct compound_hdr hdr;
699662306a36Sopenharmony_ci	int status;
699762306a36Sopenharmony_ci
699862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
699962306a36Sopenharmony_ci	if (!status)
700062306a36Sopenharmony_ci		status = decode_setclientid(xdr, res);
700162306a36Sopenharmony_ci	return status;
700262306a36Sopenharmony_ci}
700362306a36Sopenharmony_ci
700462306a36Sopenharmony_ci/*
700562306a36Sopenharmony_ci * Decode SETCLIENTID_CONFIRM response
700662306a36Sopenharmony_ci */
700762306a36Sopenharmony_cistatic int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req,
700862306a36Sopenharmony_ci					    struct xdr_stream *xdr,
700962306a36Sopenharmony_ci					    void *data)
701062306a36Sopenharmony_ci{
701162306a36Sopenharmony_ci	struct compound_hdr hdr;
701262306a36Sopenharmony_ci	int status;
701362306a36Sopenharmony_ci
701462306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
701562306a36Sopenharmony_ci	if (!status)
701662306a36Sopenharmony_ci		status = decode_setclientid_confirm(xdr);
701762306a36Sopenharmony_ci	return status;
701862306a36Sopenharmony_ci}
701962306a36Sopenharmony_ci
702062306a36Sopenharmony_ci/*
702162306a36Sopenharmony_ci * Decode DELEGRETURN response
702262306a36Sopenharmony_ci */
702362306a36Sopenharmony_cistatic int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp,
702462306a36Sopenharmony_ci				    struct xdr_stream *xdr,
702562306a36Sopenharmony_ci				    void *data)
702662306a36Sopenharmony_ci{
702762306a36Sopenharmony_ci	struct nfs4_delegreturnres *res = data;
702862306a36Sopenharmony_ci	struct compound_hdr hdr;
702962306a36Sopenharmony_ci	int status;
703062306a36Sopenharmony_ci
703162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
703262306a36Sopenharmony_ci	if (status)
703362306a36Sopenharmony_ci		goto out;
703462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
703562306a36Sopenharmony_ci	if (status)
703662306a36Sopenharmony_ci		goto out;
703762306a36Sopenharmony_ci	status = decode_putfh(xdr);
703862306a36Sopenharmony_ci	if (status != 0)
703962306a36Sopenharmony_ci		goto out;
704062306a36Sopenharmony_ci	if (res->lr_res) {
704162306a36Sopenharmony_ci		status = decode_layoutreturn(xdr, res->lr_res);
704262306a36Sopenharmony_ci		res->lr_ret = status;
704362306a36Sopenharmony_ci		if (status)
704462306a36Sopenharmony_ci			goto out;
704562306a36Sopenharmony_ci	}
704662306a36Sopenharmony_ci	if (res->fattr) {
704762306a36Sopenharmony_ci		status = decode_getfattr(xdr, res->fattr, res->server);
704862306a36Sopenharmony_ci		if (status != 0)
704962306a36Sopenharmony_ci			goto out;
705062306a36Sopenharmony_ci	}
705162306a36Sopenharmony_ci	status = decode_delegreturn(xdr);
705262306a36Sopenharmony_ciout:
705362306a36Sopenharmony_ci	return status;
705462306a36Sopenharmony_ci}
705562306a36Sopenharmony_ci
705662306a36Sopenharmony_ci/*
705762306a36Sopenharmony_ci * Decode FS_LOCATIONS response
705862306a36Sopenharmony_ci */
705962306a36Sopenharmony_cistatic int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req,
706062306a36Sopenharmony_ci				     struct xdr_stream *xdr,
706162306a36Sopenharmony_ci				     void *data)
706262306a36Sopenharmony_ci{
706362306a36Sopenharmony_ci	struct nfs4_fs_locations_res *res = data;
706462306a36Sopenharmony_ci	struct compound_hdr hdr;
706562306a36Sopenharmony_ci	int status;
706662306a36Sopenharmony_ci
706762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
706862306a36Sopenharmony_ci	if (status)
706962306a36Sopenharmony_ci		goto out;
707062306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, req);
707162306a36Sopenharmony_ci	if (status)
707262306a36Sopenharmony_ci		goto out;
707362306a36Sopenharmony_ci	status = decode_putfh(xdr);
707462306a36Sopenharmony_ci	if (status)
707562306a36Sopenharmony_ci		goto out;
707662306a36Sopenharmony_ci	if (res->migration) {
707762306a36Sopenharmony_ci		xdr_enter_page(xdr, PAGE_SIZE);
707862306a36Sopenharmony_ci		status = decode_getfattr_generic(xdr,
707962306a36Sopenharmony_ci					res->fs_locations->fattr,
708062306a36Sopenharmony_ci					 NULL, res->fs_locations,
708162306a36Sopenharmony_ci					 res->fs_locations->server);
708262306a36Sopenharmony_ci		if (status)
708362306a36Sopenharmony_ci			goto out;
708462306a36Sopenharmony_ci		if (res->renew)
708562306a36Sopenharmony_ci			status = decode_renew(xdr);
708662306a36Sopenharmony_ci	} else {
708762306a36Sopenharmony_ci		status = decode_lookup(xdr);
708862306a36Sopenharmony_ci		if (status)
708962306a36Sopenharmony_ci			goto out;
709062306a36Sopenharmony_ci		xdr_enter_page(xdr, PAGE_SIZE);
709162306a36Sopenharmony_ci		status = decode_getfattr_generic(xdr,
709262306a36Sopenharmony_ci					res->fs_locations->fattr,
709362306a36Sopenharmony_ci					 NULL, res->fs_locations,
709462306a36Sopenharmony_ci					 res->fs_locations->server);
709562306a36Sopenharmony_ci	}
709662306a36Sopenharmony_ciout:
709762306a36Sopenharmony_ci	return status;
709862306a36Sopenharmony_ci}
709962306a36Sopenharmony_ci
710062306a36Sopenharmony_ci/*
710162306a36Sopenharmony_ci * Decode SECINFO response
710262306a36Sopenharmony_ci */
710362306a36Sopenharmony_cistatic int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp,
710462306a36Sopenharmony_ci				struct xdr_stream *xdr,
710562306a36Sopenharmony_ci				void *data)
710662306a36Sopenharmony_ci{
710762306a36Sopenharmony_ci	struct nfs4_secinfo_res *res = data;
710862306a36Sopenharmony_ci	struct compound_hdr hdr;
710962306a36Sopenharmony_ci	int status;
711062306a36Sopenharmony_ci
711162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
711262306a36Sopenharmony_ci	if (status)
711362306a36Sopenharmony_ci		goto out;
711462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
711562306a36Sopenharmony_ci	if (status)
711662306a36Sopenharmony_ci		goto out;
711762306a36Sopenharmony_ci	status = decode_putfh(xdr);
711862306a36Sopenharmony_ci	if (status)
711962306a36Sopenharmony_ci		goto out;
712062306a36Sopenharmony_ci	status = decode_secinfo(xdr, res);
712162306a36Sopenharmony_ciout:
712262306a36Sopenharmony_ci	return status;
712362306a36Sopenharmony_ci}
712462306a36Sopenharmony_ci
712562306a36Sopenharmony_ci/*
712662306a36Sopenharmony_ci * Decode FSID_PRESENT response
712762306a36Sopenharmony_ci */
712862306a36Sopenharmony_cistatic int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp,
712962306a36Sopenharmony_ci				     struct xdr_stream *xdr,
713062306a36Sopenharmony_ci				     void *data)
713162306a36Sopenharmony_ci{
713262306a36Sopenharmony_ci	struct nfs4_fsid_present_res *res = data;
713362306a36Sopenharmony_ci	struct compound_hdr hdr;
713462306a36Sopenharmony_ci	int status;
713562306a36Sopenharmony_ci
713662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
713762306a36Sopenharmony_ci	if (status)
713862306a36Sopenharmony_ci		goto out;
713962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
714062306a36Sopenharmony_ci	if (status)
714162306a36Sopenharmony_ci		goto out;
714262306a36Sopenharmony_ci	status = decode_putfh(xdr);
714362306a36Sopenharmony_ci	if (status)
714462306a36Sopenharmony_ci		goto out;
714562306a36Sopenharmony_ci	status = decode_getfh(xdr, res->fh);
714662306a36Sopenharmony_ci	if (status)
714762306a36Sopenharmony_ci		goto out;
714862306a36Sopenharmony_ci	if (res->renew)
714962306a36Sopenharmony_ci		status = decode_renew(xdr);
715062306a36Sopenharmony_ciout:
715162306a36Sopenharmony_ci	return status;
715262306a36Sopenharmony_ci}
715362306a36Sopenharmony_ci
715462306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
715562306a36Sopenharmony_ci/*
715662306a36Sopenharmony_ci * Decode BIND_CONN_TO_SESSION response
715762306a36Sopenharmony_ci */
715862306a36Sopenharmony_cistatic int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp,
715962306a36Sopenharmony_ci					struct xdr_stream *xdr,
716062306a36Sopenharmony_ci					void *res)
716162306a36Sopenharmony_ci{
716262306a36Sopenharmony_ci	struct compound_hdr hdr;
716362306a36Sopenharmony_ci	int status;
716462306a36Sopenharmony_ci
716562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
716662306a36Sopenharmony_ci	if (!status)
716762306a36Sopenharmony_ci		status = decode_bind_conn_to_session(xdr, res);
716862306a36Sopenharmony_ci	return status;
716962306a36Sopenharmony_ci}
717062306a36Sopenharmony_ci
717162306a36Sopenharmony_ci/*
717262306a36Sopenharmony_ci * Decode EXCHANGE_ID response
717362306a36Sopenharmony_ci */
717462306a36Sopenharmony_cistatic int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp,
717562306a36Sopenharmony_ci				    struct xdr_stream *xdr,
717662306a36Sopenharmony_ci				    void *res)
717762306a36Sopenharmony_ci{
717862306a36Sopenharmony_ci	struct compound_hdr hdr;
717962306a36Sopenharmony_ci	int status;
718062306a36Sopenharmony_ci
718162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
718262306a36Sopenharmony_ci	if (!status)
718362306a36Sopenharmony_ci		status = decode_exchange_id(xdr, res);
718462306a36Sopenharmony_ci	return status;
718562306a36Sopenharmony_ci}
718662306a36Sopenharmony_ci
718762306a36Sopenharmony_ci/*
718862306a36Sopenharmony_ci * Decode CREATE_SESSION response
718962306a36Sopenharmony_ci */
719062306a36Sopenharmony_cistatic int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp,
719162306a36Sopenharmony_ci				       struct xdr_stream *xdr,
719262306a36Sopenharmony_ci				       void *res)
719362306a36Sopenharmony_ci{
719462306a36Sopenharmony_ci	struct compound_hdr hdr;
719562306a36Sopenharmony_ci	int status;
719662306a36Sopenharmony_ci
719762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
719862306a36Sopenharmony_ci	if (!status)
719962306a36Sopenharmony_ci		status = decode_create_session(xdr, res);
720062306a36Sopenharmony_ci	return status;
720162306a36Sopenharmony_ci}
720262306a36Sopenharmony_ci
720362306a36Sopenharmony_ci/*
720462306a36Sopenharmony_ci * Decode DESTROY_SESSION response
720562306a36Sopenharmony_ci */
720662306a36Sopenharmony_cistatic int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp,
720762306a36Sopenharmony_ci					struct xdr_stream *xdr,
720862306a36Sopenharmony_ci					void *res)
720962306a36Sopenharmony_ci{
721062306a36Sopenharmony_ci	struct compound_hdr hdr;
721162306a36Sopenharmony_ci	int status;
721262306a36Sopenharmony_ci
721362306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
721462306a36Sopenharmony_ci	if (!status)
721562306a36Sopenharmony_ci		status = decode_destroy_session(xdr, res);
721662306a36Sopenharmony_ci	return status;
721762306a36Sopenharmony_ci}
721862306a36Sopenharmony_ci
721962306a36Sopenharmony_ci/*
722062306a36Sopenharmony_ci * Decode DESTROY_CLIENTID response
722162306a36Sopenharmony_ci */
722262306a36Sopenharmony_cistatic int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp,
722362306a36Sopenharmony_ci					struct xdr_stream *xdr,
722462306a36Sopenharmony_ci					void *res)
722562306a36Sopenharmony_ci{
722662306a36Sopenharmony_ci	struct compound_hdr hdr;
722762306a36Sopenharmony_ci	int status;
722862306a36Sopenharmony_ci
722962306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
723062306a36Sopenharmony_ci	if (!status)
723162306a36Sopenharmony_ci		status = decode_destroy_clientid(xdr, res);
723262306a36Sopenharmony_ci	return status;
723362306a36Sopenharmony_ci}
723462306a36Sopenharmony_ci
723562306a36Sopenharmony_ci/*
723662306a36Sopenharmony_ci * Decode SEQUENCE response
723762306a36Sopenharmony_ci */
723862306a36Sopenharmony_cistatic int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp,
723962306a36Sopenharmony_ci				 struct xdr_stream *xdr,
724062306a36Sopenharmony_ci				 void *res)
724162306a36Sopenharmony_ci{
724262306a36Sopenharmony_ci	struct compound_hdr hdr;
724362306a36Sopenharmony_ci	int status;
724462306a36Sopenharmony_ci
724562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
724662306a36Sopenharmony_ci	if (!status)
724762306a36Sopenharmony_ci		status = decode_sequence(xdr, res, rqstp);
724862306a36Sopenharmony_ci	return status;
724962306a36Sopenharmony_ci}
725062306a36Sopenharmony_ci
725162306a36Sopenharmony_ci#endif
725262306a36Sopenharmony_ci
725362306a36Sopenharmony_ci/*
725462306a36Sopenharmony_ci * Decode GET_LEASE_TIME response
725562306a36Sopenharmony_ci */
725662306a36Sopenharmony_cistatic int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp,
725762306a36Sopenharmony_ci				       struct xdr_stream *xdr,
725862306a36Sopenharmony_ci				       void *data)
725962306a36Sopenharmony_ci{
726062306a36Sopenharmony_ci	struct nfs4_get_lease_time_res *res = data;
726162306a36Sopenharmony_ci	struct compound_hdr hdr;
726262306a36Sopenharmony_ci	int status;
726362306a36Sopenharmony_ci
726462306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
726562306a36Sopenharmony_ci	if (!status)
726662306a36Sopenharmony_ci		status = decode_sequence(xdr, &res->lr_seq_res, rqstp);
726762306a36Sopenharmony_ci	if (!status)
726862306a36Sopenharmony_ci		status = decode_putrootfh(xdr);
726962306a36Sopenharmony_ci	if (!status)
727062306a36Sopenharmony_ci		status = decode_fsinfo(xdr, res->lr_fsinfo);
727162306a36Sopenharmony_ci	return status;
727262306a36Sopenharmony_ci}
727362306a36Sopenharmony_ci
727462306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_1
727562306a36Sopenharmony_ci
727662306a36Sopenharmony_ci/*
727762306a36Sopenharmony_ci * Decode RECLAIM_COMPLETE response
727862306a36Sopenharmony_ci */
727962306a36Sopenharmony_cistatic int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp,
728062306a36Sopenharmony_ci					 struct xdr_stream *xdr,
728162306a36Sopenharmony_ci					 void *data)
728262306a36Sopenharmony_ci{
728362306a36Sopenharmony_ci	struct nfs41_reclaim_complete_res *res = data;
728462306a36Sopenharmony_ci	struct compound_hdr hdr;
728562306a36Sopenharmony_ci	int status;
728662306a36Sopenharmony_ci
728762306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
728862306a36Sopenharmony_ci	if (!status)
728962306a36Sopenharmony_ci		status = decode_sequence(xdr, &res->seq_res, rqstp);
729062306a36Sopenharmony_ci	if (!status)
729162306a36Sopenharmony_ci		status = decode_reclaim_complete(xdr, NULL);
729262306a36Sopenharmony_ci	return status;
729362306a36Sopenharmony_ci}
729462306a36Sopenharmony_ci
729562306a36Sopenharmony_ci/*
729662306a36Sopenharmony_ci * Decode GETDEVINFO response
729762306a36Sopenharmony_ci */
729862306a36Sopenharmony_cistatic int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp,
729962306a36Sopenharmony_ci				      struct xdr_stream *xdr,
730062306a36Sopenharmony_ci				      void *data)
730162306a36Sopenharmony_ci{
730262306a36Sopenharmony_ci	struct nfs4_getdeviceinfo_res *res = data;
730362306a36Sopenharmony_ci	struct compound_hdr hdr;
730462306a36Sopenharmony_ci	int status;
730562306a36Sopenharmony_ci
730662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
730762306a36Sopenharmony_ci	if (status != 0)
730862306a36Sopenharmony_ci		goto out;
730962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
731062306a36Sopenharmony_ci	if (status != 0)
731162306a36Sopenharmony_ci		goto out;
731262306a36Sopenharmony_ci	status = decode_getdeviceinfo(xdr, res);
731362306a36Sopenharmony_ciout:
731462306a36Sopenharmony_ci	return status;
731562306a36Sopenharmony_ci}
731662306a36Sopenharmony_ci
731762306a36Sopenharmony_ci/*
731862306a36Sopenharmony_ci * Decode LAYOUTGET response
731962306a36Sopenharmony_ci */
732062306a36Sopenharmony_cistatic int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp,
732162306a36Sopenharmony_ci				  struct xdr_stream *xdr,
732262306a36Sopenharmony_ci				  void *data)
732362306a36Sopenharmony_ci{
732462306a36Sopenharmony_ci	struct nfs4_layoutget_res *res = data;
732562306a36Sopenharmony_ci	struct compound_hdr hdr;
732662306a36Sopenharmony_ci	int status;
732762306a36Sopenharmony_ci
732862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
732962306a36Sopenharmony_ci	if (status)
733062306a36Sopenharmony_ci		goto out;
733162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
733262306a36Sopenharmony_ci	if (status)
733362306a36Sopenharmony_ci		goto out;
733462306a36Sopenharmony_ci	status = decode_putfh(xdr);
733562306a36Sopenharmony_ci	if (status)
733662306a36Sopenharmony_ci		goto out;
733762306a36Sopenharmony_ci	status = decode_layoutget(xdr, rqstp, res);
733862306a36Sopenharmony_ciout:
733962306a36Sopenharmony_ci	return status;
734062306a36Sopenharmony_ci}
734162306a36Sopenharmony_ci
734262306a36Sopenharmony_ci/*
734362306a36Sopenharmony_ci * Decode LAYOUTRETURN response
734462306a36Sopenharmony_ci */
734562306a36Sopenharmony_cistatic int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp,
734662306a36Sopenharmony_ci				     struct xdr_stream *xdr,
734762306a36Sopenharmony_ci				     void *data)
734862306a36Sopenharmony_ci{
734962306a36Sopenharmony_ci	struct nfs4_layoutreturn_res *res = data;
735062306a36Sopenharmony_ci	struct compound_hdr hdr;
735162306a36Sopenharmony_ci	int status;
735262306a36Sopenharmony_ci
735362306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
735462306a36Sopenharmony_ci	if (status)
735562306a36Sopenharmony_ci		goto out;
735662306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
735762306a36Sopenharmony_ci	if (status)
735862306a36Sopenharmony_ci		goto out;
735962306a36Sopenharmony_ci	status = decode_putfh(xdr);
736062306a36Sopenharmony_ci	if (status)
736162306a36Sopenharmony_ci		goto out;
736262306a36Sopenharmony_ci	status = decode_layoutreturn(xdr, res);
736362306a36Sopenharmony_ciout:
736462306a36Sopenharmony_ci	return status;
736562306a36Sopenharmony_ci}
736662306a36Sopenharmony_ci
736762306a36Sopenharmony_ci/*
736862306a36Sopenharmony_ci * Decode LAYOUTCOMMIT response
736962306a36Sopenharmony_ci */
737062306a36Sopenharmony_cistatic int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
737162306a36Sopenharmony_ci				     struct xdr_stream *xdr,
737262306a36Sopenharmony_ci				     void *data)
737362306a36Sopenharmony_ci{
737462306a36Sopenharmony_ci	struct nfs4_layoutcommit_res *res = data;
737562306a36Sopenharmony_ci	struct compound_hdr hdr;
737662306a36Sopenharmony_ci	int status;
737762306a36Sopenharmony_ci
737862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
737962306a36Sopenharmony_ci	if (status)
738062306a36Sopenharmony_ci		goto out;
738162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
738262306a36Sopenharmony_ci	if (status)
738362306a36Sopenharmony_ci		goto out;
738462306a36Sopenharmony_ci	status = decode_putfh(xdr);
738562306a36Sopenharmony_ci	if (status)
738662306a36Sopenharmony_ci		goto out;
738762306a36Sopenharmony_ci	status = decode_layoutcommit(xdr, rqstp, res);
738862306a36Sopenharmony_ci	if (status)
738962306a36Sopenharmony_ci		goto out;
739062306a36Sopenharmony_ci	decode_getfattr(xdr, res->fattr, res->server);
739162306a36Sopenharmony_ciout:
739262306a36Sopenharmony_ci	return status;
739362306a36Sopenharmony_ci}
739462306a36Sopenharmony_ci
739562306a36Sopenharmony_ci/*
739662306a36Sopenharmony_ci * Decode SECINFO_NO_NAME response
739762306a36Sopenharmony_ci */
739862306a36Sopenharmony_cistatic int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
739962306a36Sopenharmony_ci					struct xdr_stream *xdr,
740062306a36Sopenharmony_ci					void *data)
740162306a36Sopenharmony_ci{
740262306a36Sopenharmony_ci	struct nfs4_secinfo_res *res = data;
740362306a36Sopenharmony_ci	struct compound_hdr hdr;
740462306a36Sopenharmony_ci	int status;
740562306a36Sopenharmony_ci
740662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
740762306a36Sopenharmony_ci	if (status)
740862306a36Sopenharmony_ci		goto out;
740962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
741062306a36Sopenharmony_ci	if (status)
741162306a36Sopenharmony_ci		goto out;
741262306a36Sopenharmony_ci	status = decode_putrootfh(xdr);
741362306a36Sopenharmony_ci	if (status)
741462306a36Sopenharmony_ci		goto out;
741562306a36Sopenharmony_ci	status = decode_secinfo_no_name(xdr, res);
741662306a36Sopenharmony_ciout:
741762306a36Sopenharmony_ci	return status;
741862306a36Sopenharmony_ci}
741962306a36Sopenharmony_ci
742062306a36Sopenharmony_ci/*
742162306a36Sopenharmony_ci * Decode TEST_STATEID response
742262306a36Sopenharmony_ci */
742362306a36Sopenharmony_cistatic int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp,
742462306a36Sopenharmony_ci				     struct xdr_stream *xdr,
742562306a36Sopenharmony_ci				     void *data)
742662306a36Sopenharmony_ci{
742762306a36Sopenharmony_ci	struct nfs41_test_stateid_res *res = data;
742862306a36Sopenharmony_ci	struct compound_hdr hdr;
742962306a36Sopenharmony_ci	int status;
743062306a36Sopenharmony_ci
743162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
743262306a36Sopenharmony_ci	if (status)
743362306a36Sopenharmony_ci		goto out;
743462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
743562306a36Sopenharmony_ci	if (status)
743662306a36Sopenharmony_ci		goto out;
743762306a36Sopenharmony_ci	status = decode_test_stateid(xdr, res);
743862306a36Sopenharmony_ciout:
743962306a36Sopenharmony_ci	return status;
744062306a36Sopenharmony_ci}
744162306a36Sopenharmony_ci
744262306a36Sopenharmony_ci/*
744362306a36Sopenharmony_ci * Decode FREE_STATEID response
744462306a36Sopenharmony_ci */
744562306a36Sopenharmony_cistatic int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
744662306a36Sopenharmony_ci				     struct xdr_stream *xdr,
744762306a36Sopenharmony_ci				     void *data)
744862306a36Sopenharmony_ci{
744962306a36Sopenharmony_ci	struct nfs41_free_stateid_res *res = data;
745062306a36Sopenharmony_ci	struct compound_hdr hdr;
745162306a36Sopenharmony_ci	int status;
745262306a36Sopenharmony_ci
745362306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
745462306a36Sopenharmony_ci	if (status)
745562306a36Sopenharmony_ci		goto out;
745662306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
745762306a36Sopenharmony_ci	if (status)
745862306a36Sopenharmony_ci		goto out;
745962306a36Sopenharmony_ci	status = decode_free_stateid(xdr, res);
746062306a36Sopenharmony_ciout:
746162306a36Sopenharmony_ci	return status;
746262306a36Sopenharmony_ci}
746362306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_1 */
746462306a36Sopenharmony_ci
746562306a36Sopenharmony_ci/**
746662306a36Sopenharmony_ci * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in
746762306a36Sopenharmony_ci *                      the local page cache.
746862306a36Sopenharmony_ci * @xdr: XDR stream where entry resides
746962306a36Sopenharmony_ci * @entry: buffer to fill in with entry data
747062306a36Sopenharmony_ci * @plus: boolean indicating whether this should be a readdirplus entry
747162306a36Sopenharmony_ci *
747262306a36Sopenharmony_ci * Returns zero if successful, otherwise a negative errno value is
747362306a36Sopenharmony_ci * returned.
747462306a36Sopenharmony_ci *
747562306a36Sopenharmony_ci * This function is not invoked during READDIR reply decoding, but
747662306a36Sopenharmony_ci * rather whenever an application invokes the getdents(2) system call
747762306a36Sopenharmony_ci * on a directory already in our cache.
747862306a36Sopenharmony_ci */
747962306a36Sopenharmony_ciint nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
748062306a36Sopenharmony_ci		       bool plus)
748162306a36Sopenharmony_ci{
748262306a36Sopenharmony_ci	unsigned int savep;
748362306a36Sopenharmony_ci	uint32_t bitmap[3] = {0};
748462306a36Sopenharmony_ci	uint32_t len;
748562306a36Sopenharmony_ci	uint64_t new_cookie;
748662306a36Sopenharmony_ci	__be32 *p = xdr_inline_decode(xdr, 4);
748762306a36Sopenharmony_ci	if (unlikely(!p))
748862306a36Sopenharmony_ci		return -EAGAIN;
748962306a36Sopenharmony_ci	if (*p == xdr_zero) {
749062306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
749162306a36Sopenharmony_ci		if (unlikely(!p))
749262306a36Sopenharmony_ci			return -EAGAIN;
749362306a36Sopenharmony_ci		if (*p == xdr_zero)
749462306a36Sopenharmony_ci			return -EAGAIN;
749562306a36Sopenharmony_ci		entry->eof = 1;
749662306a36Sopenharmony_ci		return -EBADCOOKIE;
749762306a36Sopenharmony_ci	}
749862306a36Sopenharmony_ci
749962306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 12);
750062306a36Sopenharmony_ci	if (unlikely(!p))
750162306a36Sopenharmony_ci		return -EAGAIN;
750262306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &new_cookie);
750362306a36Sopenharmony_ci	entry->len = be32_to_cpup(p);
750462306a36Sopenharmony_ci
750562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, entry->len);
750662306a36Sopenharmony_ci	if (unlikely(!p))
750762306a36Sopenharmony_ci		return -EAGAIN;
750862306a36Sopenharmony_ci	entry->name = (const char *) p;
750962306a36Sopenharmony_ci
751062306a36Sopenharmony_ci	/*
751162306a36Sopenharmony_ci	 * In case the server doesn't return an inode number,
751262306a36Sopenharmony_ci	 * we fake one here.  (We don't use inode number 0,
751362306a36Sopenharmony_ci	 * since glibc seems to choke on it...)
751462306a36Sopenharmony_ci	 */
751562306a36Sopenharmony_ci	entry->ino = 1;
751662306a36Sopenharmony_ci	entry->fattr->valid = 0;
751762306a36Sopenharmony_ci
751862306a36Sopenharmony_ci	if (decode_attr_bitmap(xdr, bitmap) < 0)
751962306a36Sopenharmony_ci		return -EAGAIN;
752062306a36Sopenharmony_ci
752162306a36Sopenharmony_ci	if (decode_attr_length(xdr, &len, &savep) < 0)
752262306a36Sopenharmony_ci		return -EAGAIN;
752362306a36Sopenharmony_ci
752462306a36Sopenharmony_ci	if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
752562306a36Sopenharmony_ci			NULL, entry->server) < 0)
752662306a36Sopenharmony_ci		return -EAGAIN;
752762306a36Sopenharmony_ci	if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
752862306a36Sopenharmony_ci		entry->ino = entry->fattr->mounted_on_fileid;
752962306a36Sopenharmony_ci	else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
753062306a36Sopenharmony_ci		entry->ino = entry->fattr->fileid;
753162306a36Sopenharmony_ci
753262306a36Sopenharmony_ci	entry->d_type = DT_UNKNOWN;
753362306a36Sopenharmony_ci	if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
753462306a36Sopenharmony_ci		entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
753562306a36Sopenharmony_ci
753662306a36Sopenharmony_ci	entry->cookie = new_cookie;
753762306a36Sopenharmony_ci
753862306a36Sopenharmony_ci	return 0;
753962306a36Sopenharmony_ci}
754062306a36Sopenharmony_ci
754162306a36Sopenharmony_ci/*
754262306a36Sopenharmony_ci * We need to translate between nfs status return values and
754362306a36Sopenharmony_ci * the local errno values which may not be the same.
754462306a36Sopenharmony_ci */
754562306a36Sopenharmony_cistatic struct {
754662306a36Sopenharmony_ci	int stat;
754762306a36Sopenharmony_ci	int errno;
754862306a36Sopenharmony_ci} nfs_errtbl[] = {
754962306a36Sopenharmony_ci	{ NFS4_OK,		0		},
755062306a36Sopenharmony_ci	{ NFS4ERR_PERM,		-EPERM		},
755162306a36Sopenharmony_ci	{ NFS4ERR_NOENT,	-ENOENT		},
755262306a36Sopenharmony_ci	{ NFS4ERR_IO,		-errno_NFSERR_IO},
755362306a36Sopenharmony_ci	{ NFS4ERR_NXIO,		-ENXIO		},
755462306a36Sopenharmony_ci	{ NFS4ERR_ACCESS,	-EACCES		},
755562306a36Sopenharmony_ci	{ NFS4ERR_EXIST,	-EEXIST		},
755662306a36Sopenharmony_ci	{ NFS4ERR_XDEV,		-EXDEV		},
755762306a36Sopenharmony_ci	{ NFS4ERR_NOTDIR,	-ENOTDIR	},
755862306a36Sopenharmony_ci	{ NFS4ERR_ISDIR,	-EISDIR		},
755962306a36Sopenharmony_ci	{ NFS4ERR_INVAL,	-EINVAL		},
756062306a36Sopenharmony_ci	{ NFS4ERR_FBIG,		-EFBIG		},
756162306a36Sopenharmony_ci	{ NFS4ERR_NOSPC,	-ENOSPC		},
756262306a36Sopenharmony_ci	{ NFS4ERR_ROFS,		-EROFS		},
756362306a36Sopenharmony_ci	{ NFS4ERR_MLINK,	-EMLINK		},
756462306a36Sopenharmony_ci	{ NFS4ERR_NAMETOOLONG,	-ENAMETOOLONG	},
756562306a36Sopenharmony_ci	{ NFS4ERR_NOTEMPTY,	-ENOTEMPTY	},
756662306a36Sopenharmony_ci	{ NFS4ERR_DQUOT,	-EDQUOT		},
756762306a36Sopenharmony_ci	{ NFS4ERR_STALE,	-ESTALE		},
756862306a36Sopenharmony_ci	{ NFS4ERR_BADHANDLE,	-EBADHANDLE	},
756962306a36Sopenharmony_ci	{ NFS4ERR_BAD_COOKIE,	-EBADCOOKIE	},
757062306a36Sopenharmony_ci	{ NFS4ERR_NOTSUPP,	-ENOTSUPP	},
757162306a36Sopenharmony_ci	{ NFS4ERR_TOOSMALL,	-ETOOSMALL	},
757262306a36Sopenharmony_ci	{ NFS4ERR_SERVERFAULT,	-EREMOTEIO	},
757362306a36Sopenharmony_ci	{ NFS4ERR_BADTYPE,	-EBADTYPE	},
757462306a36Sopenharmony_ci	{ NFS4ERR_LOCKED,	-EAGAIN		},
757562306a36Sopenharmony_ci	{ NFS4ERR_SYMLINK,	-ELOOP		},
757662306a36Sopenharmony_ci	{ NFS4ERR_OP_ILLEGAL,	-EOPNOTSUPP	},
757762306a36Sopenharmony_ci	{ NFS4ERR_DEADLOCK,	-EDEADLK	},
757862306a36Sopenharmony_ci	{ NFS4ERR_NOXATTR,	-ENODATA	},
757962306a36Sopenharmony_ci	{ NFS4ERR_XATTR2BIG,	-E2BIG		},
758062306a36Sopenharmony_ci	{ -1,			-EIO		}
758162306a36Sopenharmony_ci};
758262306a36Sopenharmony_ci
758362306a36Sopenharmony_ci/*
758462306a36Sopenharmony_ci * Convert an NFS error code to a local one.
758562306a36Sopenharmony_ci * This one is used jointly by NFSv2 and NFSv3.
758662306a36Sopenharmony_ci */
758762306a36Sopenharmony_cistatic int
758862306a36Sopenharmony_cinfs4_stat_to_errno(int stat)
758962306a36Sopenharmony_ci{
759062306a36Sopenharmony_ci	int i;
759162306a36Sopenharmony_ci	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
759262306a36Sopenharmony_ci		if (nfs_errtbl[i].stat == stat)
759362306a36Sopenharmony_ci			return nfs_errtbl[i].errno;
759462306a36Sopenharmony_ci	}
759562306a36Sopenharmony_ci	if (stat <= 10000 || stat > 10100) {
759662306a36Sopenharmony_ci		/* The server is looney tunes. */
759762306a36Sopenharmony_ci		return -EREMOTEIO;
759862306a36Sopenharmony_ci	}
759962306a36Sopenharmony_ci	/* If we cannot translate the error, the recovery routines should
760062306a36Sopenharmony_ci	 * handle it.
760162306a36Sopenharmony_ci	 * Note: remaining NFSv4 error codes have values > 10000, so should
760262306a36Sopenharmony_ci	 * not conflict with native Linux error codes.
760362306a36Sopenharmony_ci	 */
760462306a36Sopenharmony_ci	return -stat;
760562306a36Sopenharmony_ci}
760662306a36Sopenharmony_ci
760762306a36Sopenharmony_ci#ifdef CONFIG_NFS_V4_2
760862306a36Sopenharmony_ci#include "nfs42xdr.c"
760962306a36Sopenharmony_ci#endif /* CONFIG_NFS_V4_2 */
761062306a36Sopenharmony_ci
761162306a36Sopenharmony_ci#define PROC(proc, argtype, restype)				\
761262306a36Sopenharmony_ci[NFSPROC4_CLNT_##proc] = {					\
761362306a36Sopenharmony_ci	.p_proc   = NFSPROC4_COMPOUND,				\
761462306a36Sopenharmony_ci	.p_encode = nfs4_xdr_##argtype,				\
761562306a36Sopenharmony_ci	.p_decode = nfs4_xdr_##restype,				\
761662306a36Sopenharmony_ci	.p_arglen = NFS4_##argtype##_sz,			\
761762306a36Sopenharmony_ci	.p_replen = NFS4_##restype##_sz,			\
761862306a36Sopenharmony_ci	.p_statidx = NFSPROC4_CLNT_##proc,			\
761962306a36Sopenharmony_ci	.p_name   = #proc,					\
762062306a36Sopenharmony_ci}
762162306a36Sopenharmony_ci
762262306a36Sopenharmony_ci#define STUB(proc)		\
762362306a36Sopenharmony_ci[NFSPROC4_CLNT_##proc] = {	\
762462306a36Sopenharmony_ci	.p_name = #proc,	\
762562306a36Sopenharmony_ci}
762662306a36Sopenharmony_ci
762762306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_1)
762862306a36Sopenharmony_ci#define PROC41(proc, argtype, restype)				\
762962306a36Sopenharmony_ci	PROC(proc, argtype, restype)
763062306a36Sopenharmony_ci#else
763162306a36Sopenharmony_ci#define PROC41(proc, argtype, restype)				\
763262306a36Sopenharmony_ci	STUB(proc)
763362306a36Sopenharmony_ci#endif
763462306a36Sopenharmony_ci
763562306a36Sopenharmony_ci#if defined(CONFIG_NFS_V4_2)
763662306a36Sopenharmony_ci#define PROC42(proc, argtype, restype)				\
763762306a36Sopenharmony_ci	PROC(proc, argtype, restype)
763862306a36Sopenharmony_ci#else
763962306a36Sopenharmony_ci#define PROC42(proc, argtype, restype)				\
764062306a36Sopenharmony_ci	STUB(proc)
764162306a36Sopenharmony_ci#endif
764262306a36Sopenharmony_ci
764362306a36Sopenharmony_ciconst struct rpc_procinfo nfs4_procedures[] = {
764462306a36Sopenharmony_ci	PROC(READ,		enc_read,		dec_read),
764562306a36Sopenharmony_ci	PROC(WRITE,		enc_write,		dec_write),
764662306a36Sopenharmony_ci	PROC(COMMIT,		enc_commit,		dec_commit),
764762306a36Sopenharmony_ci	PROC(OPEN,		enc_open,		dec_open),
764862306a36Sopenharmony_ci	PROC(OPEN_CONFIRM,	enc_open_confirm,	dec_open_confirm),
764962306a36Sopenharmony_ci	PROC(OPEN_NOATTR,	enc_open_noattr,	dec_open_noattr),
765062306a36Sopenharmony_ci	PROC(OPEN_DOWNGRADE,	enc_open_downgrade,	dec_open_downgrade),
765162306a36Sopenharmony_ci	PROC(CLOSE,		enc_close,		dec_close),
765262306a36Sopenharmony_ci	PROC(SETATTR,		enc_setattr,		dec_setattr),
765362306a36Sopenharmony_ci	PROC(FSINFO,		enc_fsinfo,		dec_fsinfo),
765462306a36Sopenharmony_ci	PROC(RENEW,		enc_renew,		dec_renew),
765562306a36Sopenharmony_ci	PROC(SETCLIENTID,	enc_setclientid,	dec_setclientid),
765662306a36Sopenharmony_ci	PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm),
765762306a36Sopenharmony_ci	PROC(LOCK,		enc_lock,		dec_lock),
765862306a36Sopenharmony_ci	PROC(LOCKT,		enc_lockt,		dec_lockt),
765962306a36Sopenharmony_ci	PROC(LOCKU,		enc_locku,		dec_locku),
766062306a36Sopenharmony_ci	PROC(ACCESS,		enc_access,		dec_access),
766162306a36Sopenharmony_ci	PROC(GETATTR,		enc_getattr,		dec_getattr),
766262306a36Sopenharmony_ci	PROC(LOOKUP,		enc_lookup,		dec_lookup),
766362306a36Sopenharmony_ci	PROC(LOOKUP_ROOT,	enc_lookup_root,	dec_lookup_root),
766462306a36Sopenharmony_ci	PROC(REMOVE,		enc_remove,		dec_remove),
766562306a36Sopenharmony_ci	PROC(RENAME,		enc_rename,		dec_rename),
766662306a36Sopenharmony_ci	PROC(LINK,		enc_link,		dec_link),
766762306a36Sopenharmony_ci	PROC(SYMLINK,		enc_symlink,		dec_symlink),
766862306a36Sopenharmony_ci	PROC(CREATE,		enc_create,		dec_create),
766962306a36Sopenharmony_ci	PROC(PATHCONF,		enc_pathconf,		dec_pathconf),
767062306a36Sopenharmony_ci	PROC(STATFS,		enc_statfs,		dec_statfs),
767162306a36Sopenharmony_ci	PROC(READLINK,		enc_readlink,		dec_readlink),
767262306a36Sopenharmony_ci	PROC(READDIR,		enc_readdir,		dec_readdir),
767362306a36Sopenharmony_ci	PROC(SERVER_CAPS,	enc_server_caps,	dec_server_caps),
767462306a36Sopenharmony_ci	PROC(DELEGRETURN,	enc_delegreturn,	dec_delegreturn),
767562306a36Sopenharmony_ci	PROC(GETACL,		enc_getacl,		dec_getacl),
767662306a36Sopenharmony_ci	PROC(SETACL,		enc_setacl,		dec_setacl),
767762306a36Sopenharmony_ci	PROC(FS_LOCATIONS,	enc_fs_locations,	dec_fs_locations),
767862306a36Sopenharmony_ci	PROC(RELEASE_LOCKOWNER,	enc_release_lockowner,	dec_release_lockowner),
767962306a36Sopenharmony_ci	PROC(SECINFO,		enc_secinfo,		dec_secinfo),
768062306a36Sopenharmony_ci	PROC(FSID_PRESENT,	enc_fsid_present,	dec_fsid_present),
768162306a36Sopenharmony_ci	PROC41(EXCHANGE_ID,	enc_exchange_id,	dec_exchange_id),
768262306a36Sopenharmony_ci	PROC41(CREATE_SESSION,	enc_create_session,	dec_create_session),
768362306a36Sopenharmony_ci	PROC41(DESTROY_SESSION,	enc_destroy_session,	dec_destroy_session),
768462306a36Sopenharmony_ci	PROC41(SEQUENCE,	enc_sequence,		dec_sequence),
768562306a36Sopenharmony_ci	PROC(GET_LEASE_TIME,	enc_get_lease_time,	dec_get_lease_time),
768662306a36Sopenharmony_ci	PROC41(RECLAIM_COMPLETE,enc_reclaim_complete,	dec_reclaim_complete),
768762306a36Sopenharmony_ci	PROC41(GETDEVICEINFO,	enc_getdeviceinfo,	dec_getdeviceinfo),
768862306a36Sopenharmony_ci	PROC41(LAYOUTGET,	enc_layoutget,		dec_layoutget),
768962306a36Sopenharmony_ci	PROC41(LAYOUTCOMMIT,	enc_layoutcommit,	dec_layoutcommit),
769062306a36Sopenharmony_ci	PROC41(LAYOUTRETURN,	enc_layoutreturn,	dec_layoutreturn),
769162306a36Sopenharmony_ci	PROC41(SECINFO_NO_NAME,	enc_secinfo_no_name,	dec_secinfo_no_name),
769262306a36Sopenharmony_ci	PROC41(TEST_STATEID,	enc_test_stateid,	dec_test_stateid),
769362306a36Sopenharmony_ci	PROC41(FREE_STATEID,	enc_free_stateid,	dec_free_stateid),
769462306a36Sopenharmony_ci	STUB(GETDEVICELIST),
769562306a36Sopenharmony_ci	PROC41(BIND_CONN_TO_SESSION,
769662306a36Sopenharmony_ci			enc_bind_conn_to_session, dec_bind_conn_to_session),
769762306a36Sopenharmony_ci	PROC41(DESTROY_CLIENTID,enc_destroy_clientid,	dec_destroy_clientid),
769862306a36Sopenharmony_ci	PROC42(SEEK,		enc_seek,		dec_seek),
769962306a36Sopenharmony_ci	PROC42(ALLOCATE,	enc_allocate,		dec_allocate),
770062306a36Sopenharmony_ci	PROC42(DEALLOCATE,	enc_deallocate,		dec_deallocate),
770162306a36Sopenharmony_ci	PROC42(LAYOUTSTATS,	enc_layoutstats,	dec_layoutstats),
770262306a36Sopenharmony_ci	PROC42(CLONE,		enc_clone,		dec_clone),
770362306a36Sopenharmony_ci	PROC42(COPY,		enc_copy,		dec_copy),
770462306a36Sopenharmony_ci	PROC42(OFFLOAD_CANCEL,	enc_offload_cancel,	dec_offload_cancel),
770562306a36Sopenharmony_ci	PROC42(COPY_NOTIFY,	enc_copy_notify,	dec_copy_notify),
770662306a36Sopenharmony_ci	PROC(LOOKUPP,		enc_lookupp,		dec_lookupp),
770762306a36Sopenharmony_ci	PROC42(LAYOUTERROR,	enc_layouterror,	dec_layouterror),
770862306a36Sopenharmony_ci	PROC42(GETXATTR,	enc_getxattr,		dec_getxattr),
770962306a36Sopenharmony_ci	PROC42(SETXATTR,	enc_setxattr,		dec_setxattr),
771062306a36Sopenharmony_ci	PROC42(LISTXATTRS,	enc_listxattrs,		dec_listxattrs),
771162306a36Sopenharmony_ci	PROC42(REMOVEXATTR,	enc_removexattr,	dec_removexattr),
771262306a36Sopenharmony_ci	PROC42(READ_PLUS,	enc_read_plus,		dec_read_plus),
771362306a36Sopenharmony_ci};
771462306a36Sopenharmony_ci
771562306a36Sopenharmony_cistatic unsigned int nfs_version4_counts[ARRAY_SIZE(nfs4_procedures)];
771662306a36Sopenharmony_ciconst struct rpc_version nfs_version4 = {
771762306a36Sopenharmony_ci	.number			= 4,
771862306a36Sopenharmony_ci	.nrprocs		= ARRAY_SIZE(nfs4_procedures),
771962306a36Sopenharmony_ci	.procs			= nfs4_procedures,
772062306a36Sopenharmony_ci	.counts			= nfs_version4_counts,
772162306a36Sopenharmony_ci};
7722