162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci#ifndef __LINUX_FS_NFS_NFS4_2XDR_H
662306a36Sopenharmony_ci#define __LINUX_FS_NFS_NFS4_2XDR_H
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "nfs42.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci/* Not limited by NFS itself, limited by the generic xattr code */
1162306a36Sopenharmony_ci#define nfs4_xattr_name_maxsz   XDR_QUADLEN(XATTR_NAME_MAX)
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_ci#define encode_fallocate_maxsz		(encode_stateid_maxsz + \
1462306a36Sopenharmony_ci					 2 /* offset */ + \
1562306a36Sopenharmony_ci					 2 /* length */)
1662306a36Sopenharmony_ci#define NFS42_WRITE_RES_SIZE		(1 /* wr_callback_id size */ +\
1762306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
1862306a36Sopenharmony_ci					 2 /* wr_count */ + \
1962306a36Sopenharmony_ci					 1 /* wr_committed */ + \
2062306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
2162306a36Sopenharmony_ci#define encode_allocate_maxsz		(op_encode_hdr_maxsz + \
2262306a36Sopenharmony_ci					 encode_fallocate_maxsz)
2362306a36Sopenharmony_ci#define decode_allocate_maxsz		(op_decode_hdr_maxsz)
2462306a36Sopenharmony_ci#define encode_copy_maxsz		(op_encode_hdr_maxsz +          \
2562306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
2662306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
2762306a36Sopenharmony_ci					 2 + 2 + 2 + 1 + 1 + 1 +\
2862306a36Sopenharmony_ci					 1 + /* One cnr_source_server */\
2962306a36Sopenharmony_ci					 1 + /* nl4_type */ \
3062306a36Sopenharmony_ci					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
3162306a36Sopenharmony_ci#define decode_copy_maxsz		(op_decode_hdr_maxsz + \
3262306a36Sopenharmony_ci					 NFS42_WRITE_RES_SIZE + \
3362306a36Sopenharmony_ci					 1 /* cr_consecutive */ + \
3462306a36Sopenharmony_ci					 1 /* cr_synchronous */)
3562306a36Sopenharmony_ci#define encode_offload_cancel_maxsz	(op_encode_hdr_maxsz + \
3662306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE))
3762306a36Sopenharmony_ci#define decode_offload_cancel_maxsz	(op_decode_hdr_maxsz)
3862306a36Sopenharmony_ci#define encode_copy_notify_maxsz	(op_encode_hdr_maxsz + \
3962306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
4062306a36Sopenharmony_ci					 1 + /* nl4_type */ \
4162306a36Sopenharmony_ci					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
4262306a36Sopenharmony_ci#define decode_copy_notify_maxsz	(op_decode_hdr_maxsz + \
4362306a36Sopenharmony_ci					 3 + /* cnr_lease_time */\
4462306a36Sopenharmony_ci					 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
4562306a36Sopenharmony_ci					 1 + /* Support 1 cnr_source_server */\
4662306a36Sopenharmony_ci					 1 + /* nl4_type */ \
4762306a36Sopenharmony_ci					 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
4862306a36Sopenharmony_ci#define encode_deallocate_maxsz		(op_encode_hdr_maxsz + \
4962306a36Sopenharmony_ci					 encode_fallocate_maxsz)
5062306a36Sopenharmony_ci#define decode_deallocate_maxsz		(op_decode_hdr_maxsz)
5162306a36Sopenharmony_ci#define encode_read_plus_maxsz		(op_encode_hdr_maxsz + \
5262306a36Sopenharmony_ci					 encode_stateid_maxsz + 3)
5362306a36Sopenharmony_ci#define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
5462306a36Sopenharmony_ci					(1 /* data_content4 */ + \
5562306a36Sopenharmony_ci					 2 /* data_info4.di_offset */ + \
5662306a36Sopenharmony_ci					 1 /* data_info4.di_length */)
5762306a36Sopenharmony_ci#define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
5862306a36Sopenharmony_ci					(1 /* data_content4 */ + \
5962306a36Sopenharmony_ci					 2 /* data_info4.di_offset */ + \
6062306a36Sopenharmony_ci					 2 /* data_info4.di_length */)
6162306a36Sopenharmony_ci#define READ_PLUS_SEGMENT_SIZE_DIFF	(NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
6262306a36Sopenharmony_ci					 NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
6362306a36Sopenharmony_ci#define decode_read_plus_maxsz		(op_decode_hdr_maxsz + \
6462306a36Sopenharmony_ci					 1 /* rpr_eof */ + \
6562306a36Sopenharmony_ci					 1 /* rpr_contents count */ + \
6662306a36Sopenharmony_ci					 NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
6762306a36Sopenharmony_ci#define encode_seek_maxsz		(op_encode_hdr_maxsz + \
6862306a36Sopenharmony_ci					 encode_stateid_maxsz + \
6962306a36Sopenharmony_ci					 2 /* offset */ + \
7062306a36Sopenharmony_ci					 1 /* whence */)
7162306a36Sopenharmony_ci#define decode_seek_maxsz		(op_decode_hdr_maxsz + \
7262306a36Sopenharmony_ci					 1 /* eof */ + \
7362306a36Sopenharmony_ci					 1 /* whence */ + \
7462306a36Sopenharmony_ci					 2 /* offset */ + \
7562306a36Sopenharmony_ci					 2 /* length */)
7662306a36Sopenharmony_ci#define encode_io_info_maxsz		4
7762306a36Sopenharmony_ci#define encode_layoutstats_maxsz	(op_decode_hdr_maxsz + \
7862306a36Sopenharmony_ci					2 /* offset */ + \
7962306a36Sopenharmony_ci					2 /* length */ + \
8062306a36Sopenharmony_ci					encode_stateid_maxsz + \
8162306a36Sopenharmony_ci					encode_io_info_maxsz + \
8262306a36Sopenharmony_ci					encode_io_info_maxsz + \
8362306a36Sopenharmony_ci					1 /* opaque devaddr4 length */ + \
8462306a36Sopenharmony_ci					XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
8562306a36Sopenharmony_ci#define decode_layoutstats_maxsz	(op_decode_hdr_maxsz)
8662306a36Sopenharmony_ci#define encode_device_error_maxsz	(XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
8762306a36Sopenharmony_ci					1 /* status */ + 1 /* opnum */)
8862306a36Sopenharmony_ci#define encode_layouterror_maxsz	(op_decode_hdr_maxsz + \
8962306a36Sopenharmony_ci					2 /* offset */ + \
9062306a36Sopenharmony_ci					2 /* length */ + \
9162306a36Sopenharmony_ci					encode_stateid_maxsz + \
9262306a36Sopenharmony_ci					1 /* Array size */ + \
9362306a36Sopenharmony_ci					encode_device_error_maxsz)
9462306a36Sopenharmony_ci#define decode_layouterror_maxsz	(op_decode_hdr_maxsz)
9562306a36Sopenharmony_ci#define encode_clone_maxsz		(encode_stateid_maxsz + \
9662306a36Sopenharmony_ci					encode_stateid_maxsz + \
9762306a36Sopenharmony_ci					2 /* src offset */ + \
9862306a36Sopenharmony_ci					2 /* dst offset */ + \
9962306a36Sopenharmony_ci					2 /* count */)
10062306a36Sopenharmony_ci#define decode_clone_maxsz		(op_decode_hdr_maxsz)
10162306a36Sopenharmony_ci#define encode_getxattr_maxsz		(op_encode_hdr_maxsz + 1 + \
10262306a36Sopenharmony_ci					 nfs4_xattr_name_maxsz)
10362306a36Sopenharmony_ci#define decode_getxattr_maxsz		(op_decode_hdr_maxsz + 1 + pagepad_maxsz)
10462306a36Sopenharmony_ci#define encode_setxattr_maxsz		(op_encode_hdr_maxsz + \
10562306a36Sopenharmony_ci					 1 + nfs4_xattr_name_maxsz + 1)
10662306a36Sopenharmony_ci#define decode_setxattr_maxsz		(op_decode_hdr_maxsz + decode_change_info_maxsz)
10762306a36Sopenharmony_ci#define encode_listxattrs_maxsz		(op_encode_hdr_maxsz + 2 + 1)
10862306a36Sopenharmony_ci#define decode_listxattrs_maxsz		(op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
10962306a36Sopenharmony_ci#define encode_removexattr_maxsz	(op_encode_hdr_maxsz + 1 + \
11062306a36Sopenharmony_ci					 nfs4_xattr_name_maxsz)
11162306a36Sopenharmony_ci#define decode_removexattr_maxsz	(op_decode_hdr_maxsz + \
11262306a36Sopenharmony_ci					 decode_change_info_maxsz)
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ci#define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
11562306a36Sopenharmony_ci					 encode_sequence_maxsz + \
11662306a36Sopenharmony_ci					 encode_putfh_maxsz + \
11762306a36Sopenharmony_ci					 encode_allocate_maxsz + \
11862306a36Sopenharmony_ci					 encode_getattr_maxsz)
11962306a36Sopenharmony_ci#define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
12062306a36Sopenharmony_ci					 decode_sequence_maxsz + \
12162306a36Sopenharmony_ci					 decode_putfh_maxsz + \
12262306a36Sopenharmony_ci					 decode_allocate_maxsz + \
12362306a36Sopenharmony_ci					 decode_getattr_maxsz)
12462306a36Sopenharmony_ci#define NFS4_enc_copy_sz		(compound_encode_hdr_maxsz + \
12562306a36Sopenharmony_ci					 encode_sequence_maxsz + \
12662306a36Sopenharmony_ci					 encode_putfh_maxsz + \
12762306a36Sopenharmony_ci					 encode_savefh_maxsz + \
12862306a36Sopenharmony_ci					 encode_putfh_maxsz + \
12962306a36Sopenharmony_ci					 encode_copy_maxsz + \
13062306a36Sopenharmony_ci					 encode_commit_maxsz)
13162306a36Sopenharmony_ci#define NFS4_dec_copy_sz		(compound_decode_hdr_maxsz + \
13262306a36Sopenharmony_ci					 decode_sequence_maxsz + \
13362306a36Sopenharmony_ci					 decode_putfh_maxsz + \
13462306a36Sopenharmony_ci					 decode_savefh_maxsz + \
13562306a36Sopenharmony_ci					 decode_putfh_maxsz + \
13662306a36Sopenharmony_ci					 decode_copy_maxsz + \
13762306a36Sopenharmony_ci					 decode_commit_maxsz)
13862306a36Sopenharmony_ci#define NFS4_enc_offload_cancel_sz	(compound_encode_hdr_maxsz + \
13962306a36Sopenharmony_ci					 encode_sequence_maxsz + \
14062306a36Sopenharmony_ci					 encode_putfh_maxsz + \
14162306a36Sopenharmony_ci					 encode_offload_cancel_maxsz)
14262306a36Sopenharmony_ci#define NFS4_dec_offload_cancel_sz	(compound_decode_hdr_maxsz + \
14362306a36Sopenharmony_ci					 decode_sequence_maxsz + \
14462306a36Sopenharmony_ci					 decode_putfh_maxsz + \
14562306a36Sopenharmony_ci					 decode_offload_cancel_maxsz)
14662306a36Sopenharmony_ci#define NFS4_enc_copy_notify_sz		(compound_encode_hdr_maxsz + \
14762306a36Sopenharmony_ci					 encode_putfh_maxsz + \
14862306a36Sopenharmony_ci					 encode_copy_notify_maxsz)
14962306a36Sopenharmony_ci#define NFS4_dec_copy_notify_sz		(compound_decode_hdr_maxsz + \
15062306a36Sopenharmony_ci					 decode_putfh_maxsz + \
15162306a36Sopenharmony_ci					 decode_copy_notify_maxsz)
15262306a36Sopenharmony_ci#define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
15362306a36Sopenharmony_ci					 encode_sequence_maxsz + \
15462306a36Sopenharmony_ci					 encode_putfh_maxsz + \
15562306a36Sopenharmony_ci					 encode_deallocate_maxsz + \
15662306a36Sopenharmony_ci					 encode_getattr_maxsz)
15762306a36Sopenharmony_ci#define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
15862306a36Sopenharmony_ci					 decode_sequence_maxsz + \
15962306a36Sopenharmony_ci					 decode_putfh_maxsz + \
16062306a36Sopenharmony_ci					 decode_deallocate_maxsz + \
16162306a36Sopenharmony_ci					 decode_getattr_maxsz)
16262306a36Sopenharmony_ci#define NFS4_enc_read_plus_sz		(compound_encode_hdr_maxsz + \
16362306a36Sopenharmony_ci					 encode_sequence_maxsz + \
16462306a36Sopenharmony_ci					 encode_putfh_maxsz + \
16562306a36Sopenharmony_ci					 encode_read_plus_maxsz)
16662306a36Sopenharmony_ci#define NFS4_dec_read_plus_sz		(compound_decode_hdr_maxsz + \
16762306a36Sopenharmony_ci					 decode_sequence_maxsz + \
16862306a36Sopenharmony_ci					 decode_putfh_maxsz + \
16962306a36Sopenharmony_ci					 decode_read_plus_maxsz)
17062306a36Sopenharmony_ci#define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
17162306a36Sopenharmony_ci					 encode_sequence_maxsz + \
17262306a36Sopenharmony_ci					 encode_putfh_maxsz + \
17362306a36Sopenharmony_ci					 encode_seek_maxsz)
17462306a36Sopenharmony_ci#define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
17562306a36Sopenharmony_ci					 decode_sequence_maxsz + \
17662306a36Sopenharmony_ci					 decode_putfh_maxsz + \
17762306a36Sopenharmony_ci					 decode_seek_maxsz)
17862306a36Sopenharmony_ci#define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
17962306a36Sopenharmony_ci					 encode_sequence_maxsz + \
18062306a36Sopenharmony_ci					 encode_putfh_maxsz + \
18162306a36Sopenharmony_ci					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
18262306a36Sopenharmony_ci#define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
18362306a36Sopenharmony_ci					 decode_sequence_maxsz + \
18462306a36Sopenharmony_ci					 decode_putfh_maxsz + \
18562306a36Sopenharmony_ci					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
18662306a36Sopenharmony_ci#define NFS4_enc_layouterror_sz		(compound_encode_hdr_maxsz + \
18762306a36Sopenharmony_ci					 encode_sequence_maxsz + \
18862306a36Sopenharmony_ci					 encode_putfh_maxsz + \
18962306a36Sopenharmony_ci					 NFS42_LAYOUTERROR_MAX * \
19062306a36Sopenharmony_ci					 encode_layouterror_maxsz)
19162306a36Sopenharmony_ci#define NFS4_dec_layouterror_sz		(compound_decode_hdr_maxsz + \
19262306a36Sopenharmony_ci					 decode_sequence_maxsz + \
19362306a36Sopenharmony_ci					 decode_putfh_maxsz + \
19462306a36Sopenharmony_ci					 NFS42_LAYOUTERROR_MAX * \
19562306a36Sopenharmony_ci					 decode_layouterror_maxsz)
19662306a36Sopenharmony_ci#define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
19762306a36Sopenharmony_ci					 encode_sequence_maxsz + \
19862306a36Sopenharmony_ci					 encode_putfh_maxsz + \
19962306a36Sopenharmony_ci					 encode_savefh_maxsz + \
20062306a36Sopenharmony_ci					 encode_putfh_maxsz + \
20162306a36Sopenharmony_ci					 encode_clone_maxsz + \
20262306a36Sopenharmony_ci					 encode_getattr_maxsz)
20362306a36Sopenharmony_ci#define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
20462306a36Sopenharmony_ci					 decode_sequence_maxsz + \
20562306a36Sopenharmony_ci					 decode_putfh_maxsz + \
20662306a36Sopenharmony_ci					 decode_savefh_maxsz + \
20762306a36Sopenharmony_ci					 decode_putfh_maxsz + \
20862306a36Sopenharmony_ci					 decode_clone_maxsz + \
20962306a36Sopenharmony_ci					 decode_getattr_maxsz)
21062306a36Sopenharmony_ci#define NFS4_enc_getxattr_sz		(compound_encode_hdr_maxsz + \
21162306a36Sopenharmony_ci					 encode_sequence_maxsz + \
21262306a36Sopenharmony_ci					 encode_putfh_maxsz + \
21362306a36Sopenharmony_ci					 encode_getxattr_maxsz)
21462306a36Sopenharmony_ci#define NFS4_dec_getxattr_sz		(compound_decode_hdr_maxsz + \
21562306a36Sopenharmony_ci					 decode_sequence_maxsz + \
21662306a36Sopenharmony_ci					 decode_putfh_maxsz + \
21762306a36Sopenharmony_ci					 decode_getxattr_maxsz)
21862306a36Sopenharmony_ci#define NFS4_enc_setxattr_sz		(compound_encode_hdr_maxsz + \
21962306a36Sopenharmony_ci					 encode_sequence_maxsz + \
22062306a36Sopenharmony_ci					 encode_putfh_maxsz + \
22162306a36Sopenharmony_ci					 encode_setxattr_maxsz + \
22262306a36Sopenharmony_ci					 encode_getattr_maxsz)
22362306a36Sopenharmony_ci#define NFS4_dec_setxattr_sz		(compound_decode_hdr_maxsz + \
22462306a36Sopenharmony_ci					 decode_sequence_maxsz + \
22562306a36Sopenharmony_ci					 decode_putfh_maxsz + \
22662306a36Sopenharmony_ci					 decode_setxattr_maxsz + \
22762306a36Sopenharmony_ci					 decode_getattr_maxsz)
22862306a36Sopenharmony_ci#define NFS4_enc_listxattrs_sz		(compound_encode_hdr_maxsz + \
22962306a36Sopenharmony_ci					 encode_sequence_maxsz + \
23062306a36Sopenharmony_ci					 encode_putfh_maxsz + \
23162306a36Sopenharmony_ci					 encode_listxattrs_maxsz)
23262306a36Sopenharmony_ci#define NFS4_dec_listxattrs_sz		(compound_decode_hdr_maxsz + \
23362306a36Sopenharmony_ci					 decode_sequence_maxsz + \
23462306a36Sopenharmony_ci					 decode_putfh_maxsz + \
23562306a36Sopenharmony_ci					 decode_listxattrs_maxsz)
23662306a36Sopenharmony_ci#define NFS4_enc_removexattr_sz		(compound_encode_hdr_maxsz + \
23762306a36Sopenharmony_ci					 encode_sequence_maxsz + \
23862306a36Sopenharmony_ci					 encode_putfh_maxsz + \
23962306a36Sopenharmony_ci					 encode_removexattr_maxsz)
24062306a36Sopenharmony_ci#define NFS4_dec_removexattr_sz		(compound_decode_hdr_maxsz + \
24162306a36Sopenharmony_ci					 decode_sequence_maxsz + \
24262306a36Sopenharmony_ci					 decode_putfh_maxsz + \
24362306a36Sopenharmony_ci					 decode_removexattr_maxsz)
24462306a36Sopenharmony_ci
24562306a36Sopenharmony_ci/*
24662306a36Sopenharmony_ci * These values specify the maximum amount of data that is not
24762306a36Sopenharmony_ci * associated with the extended attribute name or extended
24862306a36Sopenharmony_ci * attribute list in the SETXATTR, GETXATTR and LISTXATTR
24962306a36Sopenharmony_ci * respectively.
25062306a36Sopenharmony_ci */
25162306a36Sopenharmony_ciconst u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
25262306a36Sopenharmony_ci					compound_encode_hdr_maxsz +
25362306a36Sopenharmony_ci					encode_sequence_maxsz +
25462306a36Sopenharmony_ci					encode_putfh_maxsz + 1 +
25562306a36Sopenharmony_ci					nfs4_xattr_name_maxsz)
25662306a36Sopenharmony_ci					* XDR_UNIT);
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ciconst u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
25962306a36Sopenharmony_ci					compound_decode_hdr_maxsz +
26062306a36Sopenharmony_ci					decode_sequence_maxsz +
26162306a36Sopenharmony_ci					decode_putfh_maxsz + 1) * XDR_UNIT);
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ciconst u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
26462306a36Sopenharmony_ci					compound_decode_hdr_maxsz +
26562306a36Sopenharmony_ci					decode_sequence_maxsz +
26662306a36Sopenharmony_ci					decode_putfh_maxsz + 3) * XDR_UNIT);
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_cistatic void encode_fallocate(struct xdr_stream *xdr,
26962306a36Sopenharmony_ci			     const struct nfs42_falloc_args *args)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->falloc_stateid);
27262306a36Sopenharmony_ci	encode_uint64(xdr, args->falloc_offset);
27362306a36Sopenharmony_ci	encode_uint64(xdr, args->falloc_length);
27462306a36Sopenharmony_ci}
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_cistatic void encode_allocate(struct xdr_stream *xdr,
27762306a36Sopenharmony_ci			    const struct nfs42_falloc_args *args,
27862306a36Sopenharmony_ci			    struct compound_hdr *hdr)
27962306a36Sopenharmony_ci{
28062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
28162306a36Sopenharmony_ci	encode_fallocate(xdr, args);
28262306a36Sopenharmony_ci}
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_cistatic void encode_nl4_server(struct xdr_stream *xdr,
28562306a36Sopenharmony_ci			      const struct nl4_server *ns)
28662306a36Sopenharmony_ci{
28762306a36Sopenharmony_ci	encode_uint32(xdr, ns->nl4_type);
28862306a36Sopenharmony_ci	switch (ns->nl4_type) {
28962306a36Sopenharmony_ci	case NL4_NAME:
29062306a36Sopenharmony_ci	case NL4_URL:
29162306a36Sopenharmony_ci		encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
29262306a36Sopenharmony_ci		break;
29362306a36Sopenharmony_ci	case NL4_NETADDR:
29462306a36Sopenharmony_ci		encode_string(xdr, ns->u.nl4_addr.netid_len,
29562306a36Sopenharmony_ci			      ns->u.nl4_addr.netid);
29662306a36Sopenharmony_ci		encode_string(xdr, ns->u.nl4_addr.addr_len,
29762306a36Sopenharmony_ci			      ns->u.nl4_addr.addr);
29862306a36Sopenharmony_ci		break;
29962306a36Sopenharmony_ci	default:
30062306a36Sopenharmony_ci		WARN_ON_ONCE(1);
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci}
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_cistatic void encode_copy(struct xdr_stream *xdr,
30562306a36Sopenharmony_ci			const struct nfs42_copy_args *args,
30662306a36Sopenharmony_ci			struct compound_hdr *hdr)
30762306a36Sopenharmony_ci{
30862306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
30962306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->src_stateid);
31062306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->dst_stateid);
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci	encode_uint64(xdr, args->src_pos);
31362306a36Sopenharmony_ci	encode_uint64(xdr, args->dst_pos);
31462306a36Sopenharmony_ci	encode_uint64(xdr, args->count);
31562306a36Sopenharmony_ci
31662306a36Sopenharmony_ci	encode_uint32(xdr, 1); /* consecutive = true */
31762306a36Sopenharmony_ci	encode_uint32(xdr, args->sync);
31862306a36Sopenharmony_ci	if (args->cp_src == NULL) { /* intra-ssc */
31962306a36Sopenharmony_ci		encode_uint32(xdr, 0); /* no src server list */
32062306a36Sopenharmony_ci		return;
32162306a36Sopenharmony_ci	}
32262306a36Sopenharmony_ci	encode_uint32(xdr, 1); /* supporting 1 server */
32362306a36Sopenharmony_ci	encode_nl4_server(xdr, args->cp_src);
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic void encode_copy_commit(struct xdr_stream *xdr,
32762306a36Sopenharmony_ci			  const struct nfs42_copy_args *args,
32862306a36Sopenharmony_ci			  struct compound_hdr *hdr)
32962306a36Sopenharmony_ci{
33062306a36Sopenharmony_ci	__be32 *p;
33162306a36Sopenharmony_ci
33262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
33362306a36Sopenharmony_ci	p = reserve_space(xdr, 12);
33462306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->dst_pos);
33562306a36Sopenharmony_ci	*p = cpu_to_be32(args->count);
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic void encode_offload_cancel(struct xdr_stream *xdr,
33962306a36Sopenharmony_ci				  const struct nfs42_offload_status_args *args,
34062306a36Sopenharmony_ci				  struct compound_hdr *hdr)
34162306a36Sopenharmony_ci{
34262306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
34362306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->osa_stateid);
34462306a36Sopenharmony_ci}
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_cistatic void encode_copy_notify(struct xdr_stream *xdr,
34762306a36Sopenharmony_ci			       const struct nfs42_copy_notify_args *args,
34862306a36Sopenharmony_ci			       struct compound_hdr *hdr)
34962306a36Sopenharmony_ci{
35062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
35162306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->cna_src_stateid);
35262306a36Sopenharmony_ci	encode_nl4_server(xdr, &args->cna_dst);
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cistatic void encode_deallocate(struct xdr_stream *xdr,
35662306a36Sopenharmony_ci			      const struct nfs42_falloc_args *args,
35762306a36Sopenharmony_ci			      struct compound_hdr *hdr)
35862306a36Sopenharmony_ci{
35962306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
36062306a36Sopenharmony_ci	encode_fallocate(xdr, args);
36162306a36Sopenharmony_ci}
36262306a36Sopenharmony_ci
36362306a36Sopenharmony_cistatic void encode_read_plus(struct xdr_stream *xdr,
36462306a36Sopenharmony_ci			     const struct nfs_pgio_args *args,
36562306a36Sopenharmony_ci			     struct compound_hdr *hdr)
36662306a36Sopenharmony_ci{
36762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
36862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
36962306a36Sopenharmony_ci	encode_uint64(xdr, args->offset);
37062306a36Sopenharmony_ci	encode_uint32(xdr, args->count);
37162306a36Sopenharmony_ci}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_cistatic void encode_seek(struct xdr_stream *xdr,
37462306a36Sopenharmony_ci			const struct nfs42_seek_args *args,
37562306a36Sopenharmony_ci			struct compound_hdr *hdr)
37662306a36Sopenharmony_ci{
37762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
37862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->sa_stateid);
37962306a36Sopenharmony_ci	encode_uint64(xdr, args->sa_offset);
38062306a36Sopenharmony_ci	encode_uint32(xdr, args->sa_what);
38162306a36Sopenharmony_ci}
38262306a36Sopenharmony_ci
38362306a36Sopenharmony_cistatic void encode_layoutstats(struct xdr_stream *xdr,
38462306a36Sopenharmony_ci			       const struct nfs42_layoutstat_args *args,
38562306a36Sopenharmony_ci			       struct nfs42_layoutstat_devinfo *devinfo,
38662306a36Sopenharmony_ci			       struct compound_hdr *hdr)
38762306a36Sopenharmony_ci{
38862306a36Sopenharmony_ci	__be32 *p;
38962306a36Sopenharmony_ci
39062306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
39162306a36Sopenharmony_ci	p = reserve_space(xdr, 8 + 8);
39262306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->offset);
39362306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->length);
39462306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
39562306a36Sopenharmony_ci	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
39662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->read_count);
39762306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->read_bytes);
39862306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->write_count);
39962306a36Sopenharmony_ci	p = xdr_encode_hyper(p, devinfo->write_bytes);
40062306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
40162306a36Sopenharmony_ci			NFS4_DEVICEID4_SIZE);
40262306a36Sopenharmony_ci	/* Encode layoutupdate4 */
40362306a36Sopenharmony_ci	*p++ = cpu_to_be32(devinfo->layout_type);
40462306a36Sopenharmony_ci	if (devinfo->ld_private.ops)
40562306a36Sopenharmony_ci		devinfo->ld_private.ops->encode(xdr, args,
40662306a36Sopenharmony_ci				&devinfo->ld_private);
40762306a36Sopenharmony_ci	else
40862306a36Sopenharmony_ci		encode_uint32(xdr, 0);
40962306a36Sopenharmony_ci}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_cistatic void encode_clone(struct xdr_stream *xdr,
41262306a36Sopenharmony_ci			 const struct nfs42_clone_args *args,
41362306a36Sopenharmony_ci			 struct compound_hdr *hdr)
41462306a36Sopenharmony_ci{
41562306a36Sopenharmony_ci	__be32 *p;
41662306a36Sopenharmony_ci
41762306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
41862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->src_stateid);
41962306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->dst_stateid);
42062306a36Sopenharmony_ci	p = reserve_space(xdr, 3*8);
42162306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->src_offset);
42262306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->dst_offset);
42362306a36Sopenharmony_ci	xdr_encode_hyper(p, args->count);
42462306a36Sopenharmony_ci}
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_cistatic void encode_device_error(struct xdr_stream *xdr,
42762306a36Sopenharmony_ci				const struct nfs42_device_error *error)
42862306a36Sopenharmony_ci{
42962306a36Sopenharmony_ci	__be32 *p;
43062306a36Sopenharmony_ci
43162306a36Sopenharmony_ci	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
43262306a36Sopenharmony_ci	p = xdr_encode_opaque_fixed(p, error->dev_id.data,
43362306a36Sopenharmony_ci			NFS4_DEVICEID4_SIZE);
43462306a36Sopenharmony_ci	*p++ = cpu_to_be32(error->status);
43562306a36Sopenharmony_ci	*p = cpu_to_be32(error->opnum);
43662306a36Sopenharmony_ci}
43762306a36Sopenharmony_ci
43862306a36Sopenharmony_cistatic void encode_layouterror(struct xdr_stream *xdr,
43962306a36Sopenharmony_ci			       const struct nfs42_layout_error *args,
44062306a36Sopenharmony_ci			       struct compound_hdr *hdr)
44162306a36Sopenharmony_ci{
44262306a36Sopenharmony_ci	__be32 *p;
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
44562306a36Sopenharmony_ci	p = reserve_space(xdr, 8 + 8);
44662306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->offset);
44762306a36Sopenharmony_ci	p = xdr_encode_hyper(p, args->length);
44862306a36Sopenharmony_ci	encode_nfs4_stateid(xdr, &args->stateid);
44962306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
45062306a36Sopenharmony_ci	*p = cpu_to_be32(1);
45162306a36Sopenharmony_ci	encode_device_error(xdr, &args->errors[0]);
45262306a36Sopenharmony_ci}
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_cistatic void encode_setxattr(struct xdr_stream *xdr,
45562306a36Sopenharmony_ci			    const struct nfs42_setxattrargs *arg,
45662306a36Sopenharmony_ci			    struct compound_hdr *hdr)
45762306a36Sopenharmony_ci{
45862306a36Sopenharmony_ci	__be32 *p;
45962306a36Sopenharmony_ci
46062306a36Sopenharmony_ci	BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
46162306a36Sopenharmony_ci	BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
46262306a36Sopenharmony_ci
46362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
46462306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
46562306a36Sopenharmony_ci	*p = cpu_to_be32(arg->xattr_flags);
46662306a36Sopenharmony_ci	encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
46762306a36Sopenharmony_ci	p = reserve_space(xdr, 4);
46862306a36Sopenharmony_ci	*p = cpu_to_be32(arg->xattr_len);
46962306a36Sopenharmony_ci	if (arg->xattr_len)
47062306a36Sopenharmony_ci		xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
47162306a36Sopenharmony_ci}
47262306a36Sopenharmony_ci
47362306a36Sopenharmony_cistatic void encode_getxattr(struct xdr_stream *xdr, const char *name,
47462306a36Sopenharmony_ci			    struct compound_hdr *hdr)
47562306a36Sopenharmony_ci{
47662306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
47762306a36Sopenharmony_ci	encode_string(xdr, strlen(name), name);
47862306a36Sopenharmony_ci}
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_cistatic void encode_removexattr(struct xdr_stream *xdr, const char *name,
48162306a36Sopenharmony_ci			       struct compound_hdr *hdr)
48262306a36Sopenharmony_ci{
48362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
48462306a36Sopenharmony_ci	encode_string(xdr, strlen(name), name);
48562306a36Sopenharmony_ci}
48662306a36Sopenharmony_ci
48762306a36Sopenharmony_cistatic void encode_listxattrs(struct xdr_stream *xdr,
48862306a36Sopenharmony_ci			     const struct nfs42_listxattrsargs *arg,
48962306a36Sopenharmony_ci			     struct compound_hdr *hdr)
49062306a36Sopenharmony_ci{
49162306a36Sopenharmony_ci	__be32 *p;
49262306a36Sopenharmony_ci
49362306a36Sopenharmony_ci	encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	p = reserve_space(xdr, 12);
49662306a36Sopenharmony_ci	if (unlikely(!p))
49762306a36Sopenharmony_ci		return;
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_ci	p = xdr_encode_hyper(p, arg->cookie);
50062306a36Sopenharmony_ci	/*
50162306a36Sopenharmony_ci	 * RFC 8276 says to specify the full max length of the LISTXATTRS
50262306a36Sopenharmony_ci	 * XDR reply. Count is set to the XDR length of the names array
50362306a36Sopenharmony_ci	 * plus the EOF marker. So, add the cookie and the names count.
50462306a36Sopenharmony_ci	 */
50562306a36Sopenharmony_ci	*p = cpu_to_be32(arg->count + 8 + 4);
50662306a36Sopenharmony_ci}
50762306a36Sopenharmony_ci
50862306a36Sopenharmony_ci/*
50962306a36Sopenharmony_ci * Encode ALLOCATE request
51062306a36Sopenharmony_ci */
51162306a36Sopenharmony_cistatic void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
51262306a36Sopenharmony_ci				  struct xdr_stream *xdr,
51362306a36Sopenharmony_ci				  const void *data)
51462306a36Sopenharmony_ci{
51562306a36Sopenharmony_ci	const struct nfs42_falloc_args *args = data;
51662306a36Sopenharmony_ci	struct compound_hdr hdr = {
51762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
51862306a36Sopenharmony_ci	};
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
52162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
52262306a36Sopenharmony_ci	encode_putfh(xdr, args->falloc_fh, &hdr);
52362306a36Sopenharmony_ci	encode_allocate(xdr, args, &hdr);
52462306a36Sopenharmony_ci	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
52562306a36Sopenharmony_ci	encode_nops(&hdr);
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci/*
52962306a36Sopenharmony_ci * Encode COPY request
53062306a36Sopenharmony_ci */
53162306a36Sopenharmony_cistatic void nfs4_xdr_enc_copy(struct rpc_rqst *req,
53262306a36Sopenharmony_ci			      struct xdr_stream *xdr,
53362306a36Sopenharmony_ci			      const void *data)
53462306a36Sopenharmony_ci{
53562306a36Sopenharmony_ci	const struct nfs42_copy_args *args = data;
53662306a36Sopenharmony_ci	struct compound_hdr hdr = {
53762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
53862306a36Sopenharmony_ci	};
53962306a36Sopenharmony_ci
54062306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
54162306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
54262306a36Sopenharmony_ci	encode_putfh(xdr, args->src_fh, &hdr);
54362306a36Sopenharmony_ci	encode_savefh(xdr, &hdr);
54462306a36Sopenharmony_ci	encode_putfh(xdr, args->dst_fh, &hdr);
54562306a36Sopenharmony_ci	encode_copy(xdr, args, &hdr);
54662306a36Sopenharmony_ci	if (args->sync)
54762306a36Sopenharmony_ci		encode_copy_commit(xdr, args, &hdr);
54862306a36Sopenharmony_ci	encode_nops(&hdr);
54962306a36Sopenharmony_ci}
55062306a36Sopenharmony_ci
55162306a36Sopenharmony_ci/*
55262306a36Sopenharmony_ci * Encode OFFLOAD_CANEL request
55362306a36Sopenharmony_ci */
55462306a36Sopenharmony_cistatic void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
55562306a36Sopenharmony_ci					struct xdr_stream *xdr,
55662306a36Sopenharmony_ci					const void *data)
55762306a36Sopenharmony_ci{
55862306a36Sopenharmony_ci	const struct nfs42_offload_status_args *args = data;
55962306a36Sopenharmony_ci	struct compound_hdr hdr = {
56062306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
56162306a36Sopenharmony_ci	};
56262306a36Sopenharmony_ci
56362306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
56462306a36Sopenharmony_ci	encode_sequence(xdr, &args->osa_seq_args, &hdr);
56562306a36Sopenharmony_ci	encode_putfh(xdr, args->osa_src_fh, &hdr);
56662306a36Sopenharmony_ci	encode_offload_cancel(xdr, args, &hdr);
56762306a36Sopenharmony_ci	encode_nops(&hdr);
56862306a36Sopenharmony_ci}
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci/*
57162306a36Sopenharmony_ci * Encode COPY_NOTIFY request
57262306a36Sopenharmony_ci */
57362306a36Sopenharmony_cistatic void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
57462306a36Sopenharmony_ci				     struct xdr_stream *xdr,
57562306a36Sopenharmony_ci				     const void *data)
57662306a36Sopenharmony_ci{
57762306a36Sopenharmony_ci	const struct nfs42_copy_notify_args *args = data;
57862306a36Sopenharmony_ci	struct compound_hdr hdr = {
57962306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
58062306a36Sopenharmony_ci	};
58162306a36Sopenharmony_ci
58262306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
58362306a36Sopenharmony_ci	encode_sequence(xdr, &args->cna_seq_args, &hdr);
58462306a36Sopenharmony_ci	encode_putfh(xdr, args->cna_src_fh, &hdr);
58562306a36Sopenharmony_ci	encode_copy_notify(xdr, args, &hdr);
58662306a36Sopenharmony_ci	encode_nops(&hdr);
58762306a36Sopenharmony_ci}
58862306a36Sopenharmony_ci
58962306a36Sopenharmony_ci/*
59062306a36Sopenharmony_ci * Encode DEALLOCATE request
59162306a36Sopenharmony_ci */
59262306a36Sopenharmony_cistatic void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
59362306a36Sopenharmony_ci				    struct xdr_stream *xdr,
59462306a36Sopenharmony_ci				    const void *data)
59562306a36Sopenharmony_ci{
59662306a36Sopenharmony_ci	const struct nfs42_falloc_args *args = data;
59762306a36Sopenharmony_ci	struct compound_hdr hdr = {
59862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
59962306a36Sopenharmony_ci	};
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
60262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
60362306a36Sopenharmony_ci	encode_putfh(xdr, args->falloc_fh, &hdr);
60462306a36Sopenharmony_ci	encode_deallocate(xdr, args, &hdr);
60562306a36Sopenharmony_ci	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
60662306a36Sopenharmony_ci	encode_nops(&hdr);
60762306a36Sopenharmony_ci}
60862306a36Sopenharmony_ci
60962306a36Sopenharmony_ci/*
61062306a36Sopenharmony_ci * Encode READ_PLUS request
61162306a36Sopenharmony_ci */
61262306a36Sopenharmony_cistatic void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
61362306a36Sopenharmony_ci				   struct xdr_stream *xdr,
61462306a36Sopenharmony_ci				   const void *data)
61562306a36Sopenharmony_ci{
61662306a36Sopenharmony_ci	const struct nfs_pgio_args *args = data;
61762306a36Sopenharmony_ci	struct compound_hdr hdr = {
61862306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
61962306a36Sopenharmony_ci	};
62062306a36Sopenharmony_ci
62162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
62262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
62362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
62462306a36Sopenharmony_ci	encode_read_plus(xdr, args, &hdr);
62562306a36Sopenharmony_ci
62662306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
62762306a36Sopenharmony_ci				hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
62862306a36Sopenharmony_ci	encode_nops(&hdr);
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_ci/*
63262306a36Sopenharmony_ci * Encode SEEK request
63362306a36Sopenharmony_ci */
63462306a36Sopenharmony_cistatic void nfs4_xdr_enc_seek(struct rpc_rqst *req,
63562306a36Sopenharmony_ci			      struct xdr_stream *xdr,
63662306a36Sopenharmony_ci			      const void *data)
63762306a36Sopenharmony_ci{
63862306a36Sopenharmony_ci	const struct nfs42_seek_args *args = data;
63962306a36Sopenharmony_ci	struct compound_hdr hdr = {
64062306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
64162306a36Sopenharmony_ci	};
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
64462306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
64562306a36Sopenharmony_ci	encode_putfh(xdr, args->sa_fh, &hdr);
64662306a36Sopenharmony_ci	encode_seek(xdr, args, &hdr);
64762306a36Sopenharmony_ci	encode_nops(&hdr);
64862306a36Sopenharmony_ci}
64962306a36Sopenharmony_ci
65062306a36Sopenharmony_ci/*
65162306a36Sopenharmony_ci * Encode LAYOUTSTATS request
65262306a36Sopenharmony_ci */
65362306a36Sopenharmony_cistatic void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
65462306a36Sopenharmony_ci				     struct xdr_stream *xdr,
65562306a36Sopenharmony_ci				     const void *data)
65662306a36Sopenharmony_ci{
65762306a36Sopenharmony_ci	const struct nfs42_layoutstat_args *args = data;
65862306a36Sopenharmony_ci	int i;
65962306a36Sopenharmony_ci
66062306a36Sopenharmony_ci	struct compound_hdr hdr = {
66162306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
66262306a36Sopenharmony_ci	};
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
66562306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
66662306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
66762306a36Sopenharmony_ci	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
66862306a36Sopenharmony_ci	for (i = 0; i < args->num_dev; i++)
66962306a36Sopenharmony_ci		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
67062306a36Sopenharmony_ci	encode_nops(&hdr);
67162306a36Sopenharmony_ci}
67262306a36Sopenharmony_ci
67362306a36Sopenharmony_ci/*
67462306a36Sopenharmony_ci * Encode CLONE request
67562306a36Sopenharmony_ci */
67662306a36Sopenharmony_cistatic void nfs4_xdr_enc_clone(struct rpc_rqst *req,
67762306a36Sopenharmony_ci			       struct xdr_stream *xdr,
67862306a36Sopenharmony_ci			       const void *data)
67962306a36Sopenharmony_ci{
68062306a36Sopenharmony_ci	const struct nfs42_clone_args *args = data;
68162306a36Sopenharmony_ci	struct compound_hdr hdr = {
68262306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
68362306a36Sopenharmony_ci	};
68462306a36Sopenharmony_ci
68562306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
68662306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
68762306a36Sopenharmony_ci	encode_putfh(xdr, args->src_fh, &hdr);
68862306a36Sopenharmony_ci	encode_savefh(xdr, &hdr);
68962306a36Sopenharmony_ci	encode_putfh(xdr, args->dst_fh, &hdr);
69062306a36Sopenharmony_ci	encode_clone(xdr, args, &hdr);
69162306a36Sopenharmony_ci	encode_getfattr(xdr, args->dst_bitmask, &hdr);
69262306a36Sopenharmony_ci	encode_nops(&hdr);
69362306a36Sopenharmony_ci}
69462306a36Sopenharmony_ci
69562306a36Sopenharmony_ci/*
69662306a36Sopenharmony_ci * Encode LAYOUTERROR request
69762306a36Sopenharmony_ci */
69862306a36Sopenharmony_cistatic void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
69962306a36Sopenharmony_ci				     struct xdr_stream *xdr,
70062306a36Sopenharmony_ci				     const void *data)
70162306a36Sopenharmony_ci{
70262306a36Sopenharmony_ci	const struct nfs42_layouterror_args *args = data;
70362306a36Sopenharmony_ci	struct compound_hdr hdr = {
70462306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
70562306a36Sopenharmony_ci	};
70662306a36Sopenharmony_ci	int i;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
70962306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
71062306a36Sopenharmony_ci	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
71162306a36Sopenharmony_ci	for (i = 0; i < args->num_errors; i++)
71262306a36Sopenharmony_ci		encode_layouterror(xdr, &args->errors[i], &hdr);
71362306a36Sopenharmony_ci	encode_nops(&hdr);
71462306a36Sopenharmony_ci}
71562306a36Sopenharmony_ci
71662306a36Sopenharmony_ci/*
71762306a36Sopenharmony_ci * Encode SETXATTR request
71862306a36Sopenharmony_ci */
71962306a36Sopenharmony_cistatic void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
72062306a36Sopenharmony_ci				  const void *data)
72162306a36Sopenharmony_ci{
72262306a36Sopenharmony_ci	const struct nfs42_setxattrargs *args = data;
72362306a36Sopenharmony_ci	struct compound_hdr hdr = {
72462306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
72562306a36Sopenharmony_ci	};
72662306a36Sopenharmony_ci
72762306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
72862306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
72962306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
73062306a36Sopenharmony_ci	encode_setxattr(xdr, args, &hdr);
73162306a36Sopenharmony_ci	encode_getfattr(xdr, args->bitmask, &hdr);
73262306a36Sopenharmony_ci	encode_nops(&hdr);
73362306a36Sopenharmony_ci}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci/*
73662306a36Sopenharmony_ci * Encode GETXATTR request
73762306a36Sopenharmony_ci */
73862306a36Sopenharmony_cistatic void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
73962306a36Sopenharmony_ci				  const void *data)
74062306a36Sopenharmony_ci{
74162306a36Sopenharmony_ci	const struct nfs42_getxattrargs *args = data;
74262306a36Sopenharmony_ci	struct compound_hdr hdr = {
74362306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
74462306a36Sopenharmony_ci	};
74562306a36Sopenharmony_ci	uint32_t replen;
74662306a36Sopenharmony_ci
74762306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
74862306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
74962306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
75062306a36Sopenharmony_ci	replen = hdr.replen + op_decode_hdr_maxsz + 1;
75162306a36Sopenharmony_ci	encode_getxattr(xdr, args->xattr_name, &hdr);
75262306a36Sopenharmony_ci
75362306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len,
75462306a36Sopenharmony_ci				replen);
75562306a36Sopenharmony_ci
75662306a36Sopenharmony_ci	encode_nops(&hdr);
75762306a36Sopenharmony_ci}
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci/*
76062306a36Sopenharmony_ci * Encode LISTXATTR request
76162306a36Sopenharmony_ci */
76262306a36Sopenharmony_cistatic void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
76362306a36Sopenharmony_ci				    struct xdr_stream *xdr, const void *data)
76462306a36Sopenharmony_ci{
76562306a36Sopenharmony_ci	const struct nfs42_listxattrsargs *args = data;
76662306a36Sopenharmony_ci	struct compound_hdr hdr = {
76762306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
76862306a36Sopenharmony_ci	};
76962306a36Sopenharmony_ci	uint32_t replen;
77062306a36Sopenharmony_ci
77162306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
77262306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
77362306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
77462306a36Sopenharmony_ci	replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1;
77562306a36Sopenharmony_ci	encode_listxattrs(xdr, args, &hdr);
77662306a36Sopenharmony_ci
77762306a36Sopenharmony_ci	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen);
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	encode_nops(&hdr);
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci/*
78362306a36Sopenharmony_ci * Encode REMOVEXATTR request
78462306a36Sopenharmony_ci */
78562306a36Sopenharmony_cistatic void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
78662306a36Sopenharmony_ci				     struct xdr_stream *xdr, const void *data)
78762306a36Sopenharmony_ci{
78862306a36Sopenharmony_ci	const struct nfs42_removexattrargs *args = data;
78962306a36Sopenharmony_ci	struct compound_hdr hdr = {
79062306a36Sopenharmony_ci		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
79162306a36Sopenharmony_ci	};
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	encode_compound_hdr(xdr, req, &hdr);
79462306a36Sopenharmony_ci	encode_sequence(xdr, &args->seq_args, &hdr);
79562306a36Sopenharmony_ci	encode_putfh(xdr, args->fh, &hdr);
79662306a36Sopenharmony_ci	encode_removexattr(xdr, args->xattr_name, &hdr);
79762306a36Sopenharmony_ci	encode_nops(&hdr);
79862306a36Sopenharmony_ci}
79962306a36Sopenharmony_ci
80062306a36Sopenharmony_cistatic int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
80162306a36Sopenharmony_ci{
80262306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_ALLOCATE);
80362306a36Sopenharmony_ci}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_cistatic int decode_write_response(struct xdr_stream *xdr,
80662306a36Sopenharmony_ci				 struct nfs42_write_res *res)
80762306a36Sopenharmony_ci{
80862306a36Sopenharmony_ci	__be32 *p;
80962306a36Sopenharmony_ci	int status, count;
81062306a36Sopenharmony_ci
81162306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
81262306a36Sopenharmony_ci	if (unlikely(!p))
81362306a36Sopenharmony_ci		return -EIO;
81462306a36Sopenharmony_ci	count = be32_to_cpup(p);
81562306a36Sopenharmony_ci	if (count > 1)
81662306a36Sopenharmony_ci		return -EREMOTEIO;
81762306a36Sopenharmony_ci	else if (count == 1) {
81862306a36Sopenharmony_ci		status = decode_opaque_fixed(xdr, &res->stateid,
81962306a36Sopenharmony_ci				NFS4_STATEID_SIZE);
82062306a36Sopenharmony_ci		if (unlikely(status))
82162306a36Sopenharmony_ci			return -EIO;
82262306a36Sopenharmony_ci	}
82362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8 + 4);
82462306a36Sopenharmony_ci	if (unlikely(!p))
82562306a36Sopenharmony_ci		return -EIO;
82662306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->count);
82762306a36Sopenharmony_ci	res->verifier.committed = be32_to_cpup(p);
82862306a36Sopenharmony_ci	return decode_verifier(xdr, &res->verifier.verifier);
82962306a36Sopenharmony_ci}
83062306a36Sopenharmony_ci
83162306a36Sopenharmony_cistatic int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
83262306a36Sopenharmony_ci{
83362306a36Sopenharmony_ci	struct nfs42_netaddr *naddr;
83462306a36Sopenharmony_ci	uint32_t dummy;
83562306a36Sopenharmony_ci	char *dummy_str;
83662306a36Sopenharmony_ci	__be32 *p;
83762306a36Sopenharmony_ci	int status;
83862306a36Sopenharmony_ci
83962306a36Sopenharmony_ci	/* nl_type */
84062306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
84162306a36Sopenharmony_ci	if (unlikely(!p))
84262306a36Sopenharmony_ci		return -EIO;
84362306a36Sopenharmony_ci	ns->nl4_type = be32_to_cpup(p);
84462306a36Sopenharmony_ci	switch (ns->nl4_type) {
84562306a36Sopenharmony_ci	case NL4_NAME:
84662306a36Sopenharmony_ci	case NL4_URL:
84762306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
84862306a36Sopenharmony_ci		if (unlikely(status))
84962306a36Sopenharmony_ci			return status;
85062306a36Sopenharmony_ci		if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
85162306a36Sopenharmony_ci			return -EIO;
85262306a36Sopenharmony_ci		memcpy(&ns->u.nl4_str, dummy_str, dummy);
85362306a36Sopenharmony_ci		ns->u.nl4_str_sz = dummy;
85462306a36Sopenharmony_ci		break;
85562306a36Sopenharmony_ci	case NL4_NETADDR:
85662306a36Sopenharmony_ci		naddr = &ns->u.nl4_addr;
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci		/* netid string */
85962306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
86062306a36Sopenharmony_ci		if (unlikely(status))
86162306a36Sopenharmony_ci			return status;
86262306a36Sopenharmony_ci		if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
86362306a36Sopenharmony_ci			return -EIO;
86462306a36Sopenharmony_ci		naddr->netid_len = dummy;
86562306a36Sopenharmony_ci		memcpy(naddr->netid, dummy_str, naddr->netid_len);
86662306a36Sopenharmony_ci
86762306a36Sopenharmony_ci		/* uaddr string */
86862306a36Sopenharmony_ci		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
86962306a36Sopenharmony_ci		if (unlikely(status))
87062306a36Sopenharmony_ci			return status;
87162306a36Sopenharmony_ci		if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
87262306a36Sopenharmony_ci			return -EIO;
87362306a36Sopenharmony_ci		naddr->addr_len = dummy;
87462306a36Sopenharmony_ci		memcpy(naddr->addr, dummy_str, naddr->addr_len);
87562306a36Sopenharmony_ci		break;
87662306a36Sopenharmony_ci	default:
87762306a36Sopenharmony_ci		WARN_ON_ONCE(1);
87862306a36Sopenharmony_ci		return -EIO;
87962306a36Sopenharmony_ci	}
88062306a36Sopenharmony_ci	return 0;
88162306a36Sopenharmony_ci}
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_cistatic int decode_copy_requirements(struct xdr_stream *xdr,
88462306a36Sopenharmony_ci				    struct nfs42_copy_res *res) {
88562306a36Sopenharmony_ci	__be32 *p;
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4 + 4);
88862306a36Sopenharmony_ci	if (unlikely(!p))
88962306a36Sopenharmony_ci		return -EIO;
89062306a36Sopenharmony_ci
89162306a36Sopenharmony_ci	res->consecutive = be32_to_cpup(p++);
89262306a36Sopenharmony_ci	res->synchronous = be32_to_cpup(p++);
89362306a36Sopenharmony_ci	return 0;
89462306a36Sopenharmony_ci}
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_cistatic int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
89762306a36Sopenharmony_ci{
89862306a36Sopenharmony_ci	int status;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_COPY);
90162306a36Sopenharmony_ci	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
90262306a36Sopenharmony_ci		status = decode_copy_requirements(xdr, res);
90362306a36Sopenharmony_ci		if (status)
90462306a36Sopenharmony_ci			return status;
90562306a36Sopenharmony_ci		return NFS4ERR_OFFLOAD_NO_REQS;
90662306a36Sopenharmony_ci	} else if (status)
90762306a36Sopenharmony_ci		return status;
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	status = decode_write_response(xdr, &res->write_res);
91062306a36Sopenharmony_ci	if (status)
91162306a36Sopenharmony_ci		return status;
91262306a36Sopenharmony_ci
91362306a36Sopenharmony_ci	return decode_copy_requirements(xdr, res);
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic int decode_offload_cancel(struct xdr_stream *xdr,
91762306a36Sopenharmony_ci				 struct nfs42_offload_status_res *res)
91862306a36Sopenharmony_ci{
91962306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
92062306a36Sopenharmony_ci}
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_cistatic int decode_copy_notify(struct xdr_stream *xdr,
92362306a36Sopenharmony_ci			      struct nfs42_copy_notify_res *res)
92462306a36Sopenharmony_ci{
92562306a36Sopenharmony_ci	__be32 *p;
92662306a36Sopenharmony_ci	int status, count;
92762306a36Sopenharmony_ci
92862306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
92962306a36Sopenharmony_ci	if (status)
93062306a36Sopenharmony_ci		return status;
93162306a36Sopenharmony_ci	/* cnr_lease_time */
93262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 12);
93362306a36Sopenharmony_ci	if (unlikely(!p))
93462306a36Sopenharmony_ci		return -EIO;
93562306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
93662306a36Sopenharmony_ci	res->cnr_lease_time.nseconds = be32_to_cpup(p);
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
93962306a36Sopenharmony_ci	if (unlikely(status))
94062306a36Sopenharmony_ci		return -EIO;
94162306a36Sopenharmony_ci
94262306a36Sopenharmony_ci	/* number of source addresses */
94362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
94462306a36Sopenharmony_ci	if (unlikely(!p))
94562306a36Sopenharmony_ci		return -EIO;
94662306a36Sopenharmony_ci
94762306a36Sopenharmony_ci	count = be32_to_cpup(p);
94862306a36Sopenharmony_ci	if (count > 1)
94962306a36Sopenharmony_ci		pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
95062306a36Sopenharmony_ci			 __func__, count);
95162306a36Sopenharmony_ci
95262306a36Sopenharmony_ci	status = decode_nl4_server(xdr, &res->cnr_src);
95362306a36Sopenharmony_ci	if (unlikely(status))
95462306a36Sopenharmony_ci		return -EIO;
95562306a36Sopenharmony_ci	return 0;
95662306a36Sopenharmony_ci}
95762306a36Sopenharmony_ci
95862306a36Sopenharmony_cistatic int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
95962306a36Sopenharmony_ci{
96062306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_DEALLOCATE);
96162306a36Sopenharmony_ci}
96262306a36Sopenharmony_ci
96362306a36Sopenharmony_cistruct read_plus_segment {
96462306a36Sopenharmony_ci	enum data_content4 type;
96562306a36Sopenharmony_ci	uint64_t offset;
96662306a36Sopenharmony_ci	union {
96762306a36Sopenharmony_ci		struct {
96862306a36Sopenharmony_ci			uint64_t length;
96962306a36Sopenharmony_ci		} hole;
97062306a36Sopenharmony_ci
97162306a36Sopenharmony_ci		struct {
97262306a36Sopenharmony_ci			uint32_t length;
97362306a36Sopenharmony_ci			unsigned int from;
97462306a36Sopenharmony_ci		} data;
97562306a36Sopenharmony_ci	};
97662306a36Sopenharmony_ci};
97762306a36Sopenharmony_ci
97862306a36Sopenharmony_cistatic inline uint64_t read_plus_segment_length(struct read_plus_segment *seg)
97962306a36Sopenharmony_ci{
98062306a36Sopenharmony_ci	return seg->type == NFS4_CONTENT_DATA ? seg->data.length : seg->hole.length;
98162306a36Sopenharmony_ci}
98262306a36Sopenharmony_ci
98362306a36Sopenharmony_cistatic int decode_read_plus_segment(struct xdr_stream *xdr,
98462306a36Sopenharmony_ci				    struct read_plus_segment *seg)
98562306a36Sopenharmony_ci{
98662306a36Sopenharmony_ci	__be32 *p;
98762306a36Sopenharmony_ci
98862306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
98962306a36Sopenharmony_ci	if (!p)
99062306a36Sopenharmony_ci		return -EIO;
99162306a36Sopenharmony_ci	seg->type = be32_to_cpup(p++);
99262306a36Sopenharmony_ci
99362306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, seg->type == NFS4_CONTENT_DATA ? 12 : 16);
99462306a36Sopenharmony_ci	if (!p)
99562306a36Sopenharmony_ci		return -EIO;
99662306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &seg->offset);
99762306a36Sopenharmony_ci
99862306a36Sopenharmony_ci	if (seg->type == NFS4_CONTENT_DATA) {
99962306a36Sopenharmony_ci		struct xdr_buf buf;
100062306a36Sopenharmony_ci		uint32_t len = be32_to_cpup(p);
100162306a36Sopenharmony_ci
100262306a36Sopenharmony_ci		seg->data.length = len;
100362306a36Sopenharmony_ci		seg->data.from = xdr_stream_pos(xdr);
100462306a36Sopenharmony_ci
100562306a36Sopenharmony_ci		if (!xdr_stream_subsegment(xdr, &buf, xdr_align_size(len)))
100662306a36Sopenharmony_ci			return -EIO;
100762306a36Sopenharmony_ci	} else if (seg->type == NFS4_CONTENT_HOLE) {
100862306a36Sopenharmony_ci		xdr_decode_hyper(p, &seg->hole.length);
100962306a36Sopenharmony_ci	} else
101062306a36Sopenharmony_ci		return -EINVAL;
101162306a36Sopenharmony_ci	return 0;
101262306a36Sopenharmony_ci}
101362306a36Sopenharmony_ci
101462306a36Sopenharmony_cistatic int process_read_plus_segment(struct xdr_stream *xdr,
101562306a36Sopenharmony_ci				     struct nfs_pgio_args *args,
101662306a36Sopenharmony_ci				     struct nfs_pgio_res *res,
101762306a36Sopenharmony_ci				     struct read_plus_segment *seg)
101862306a36Sopenharmony_ci{
101962306a36Sopenharmony_ci	unsigned long offset = seg->offset;
102062306a36Sopenharmony_ci	unsigned long length = read_plus_segment_length(seg);
102162306a36Sopenharmony_ci	unsigned int bufpos;
102262306a36Sopenharmony_ci
102362306a36Sopenharmony_ci	if (offset + length < args->offset)
102462306a36Sopenharmony_ci		return 0;
102562306a36Sopenharmony_ci	else if (offset > args->offset + args->count) {
102662306a36Sopenharmony_ci		res->eof = 0;
102762306a36Sopenharmony_ci		return 0;
102862306a36Sopenharmony_ci	} else if (offset < args->offset) {
102962306a36Sopenharmony_ci		length -= (args->offset - offset);
103062306a36Sopenharmony_ci		offset = args->offset;
103162306a36Sopenharmony_ci	} else if (offset + length > args->offset + args->count) {
103262306a36Sopenharmony_ci		length = (args->offset + args->count) - offset;
103362306a36Sopenharmony_ci		res->eof = 0;
103462306a36Sopenharmony_ci	}
103562306a36Sopenharmony_ci
103662306a36Sopenharmony_ci	bufpos = xdr->buf->head[0].iov_len + (offset - args->offset);
103762306a36Sopenharmony_ci	if (seg->type == NFS4_CONTENT_HOLE)
103862306a36Sopenharmony_ci		return xdr_stream_zero(xdr, bufpos, length);
103962306a36Sopenharmony_ci	else
104062306a36Sopenharmony_ci		return xdr_stream_move_subsegment(xdr, seg->data.from, bufpos, length);
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_cistatic int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
104462306a36Sopenharmony_ci{
104562306a36Sopenharmony_ci	struct nfs_pgio_header *hdr =
104662306a36Sopenharmony_ci		container_of(res, struct nfs_pgio_header, res);
104762306a36Sopenharmony_ci	struct nfs_pgio_args *args = &hdr->args;
104862306a36Sopenharmony_ci	uint32_t segments;
104962306a36Sopenharmony_ci	struct read_plus_segment *segs;
105062306a36Sopenharmony_ci	int status, i;
105162306a36Sopenharmony_ci	__be32 *p;
105262306a36Sopenharmony_ci
105362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_READ_PLUS);
105462306a36Sopenharmony_ci	if (status)
105562306a36Sopenharmony_ci		return status;
105662306a36Sopenharmony_ci
105762306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4 + 4);
105862306a36Sopenharmony_ci	if (unlikely(!p))
105962306a36Sopenharmony_ci		return -EIO;
106062306a36Sopenharmony_ci
106162306a36Sopenharmony_ci	res->count = 0;
106262306a36Sopenharmony_ci	res->eof = be32_to_cpup(p++);
106362306a36Sopenharmony_ci	segments = be32_to_cpup(p++);
106462306a36Sopenharmony_ci	if (segments == 0)
106562306a36Sopenharmony_ci		return 0;
106662306a36Sopenharmony_ci
106762306a36Sopenharmony_ci	segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL);
106862306a36Sopenharmony_ci	if (!segs)
106962306a36Sopenharmony_ci		return -ENOMEM;
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci	for (i = 0; i < segments; i++) {
107262306a36Sopenharmony_ci		status = decode_read_plus_segment(xdr, &segs[i]);
107362306a36Sopenharmony_ci		if (status < 0)
107462306a36Sopenharmony_ci			goto out;
107562306a36Sopenharmony_ci	}
107662306a36Sopenharmony_ci
107762306a36Sopenharmony_ci	xdr_set_pagelen(xdr, xdr_align_size(args->count));
107862306a36Sopenharmony_ci	for (i = segments; i > 0; i--)
107962306a36Sopenharmony_ci		res->count += process_read_plus_segment(xdr, args, res, &segs[i-1]);
108062306a36Sopenharmony_ci	status = 0;
108162306a36Sopenharmony_ci
108262306a36Sopenharmony_ciout:
108362306a36Sopenharmony_ci	kfree(segs);
108462306a36Sopenharmony_ci	return status;
108562306a36Sopenharmony_ci}
108662306a36Sopenharmony_ci
108762306a36Sopenharmony_cistatic int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
108862306a36Sopenharmony_ci{
108962306a36Sopenharmony_ci	int status;
109062306a36Sopenharmony_ci	__be32 *p;
109162306a36Sopenharmony_ci
109262306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_SEEK);
109362306a36Sopenharmony_ci	if (status)
109462306a36Sopenharmony_ci		return status;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4 + 8);
109762306a36Sopenharmony_ci	if (unlikely(!p))
109862306a36Sopenharmony_ci		return -EIO;
109962306a36Sopenharmony_ci
110062306a36Sopenharmony_ci	res->sr_eof = be32_to_cpup(p++);
110162306a36Sopenharmony_ci	p = xdr_decode_hyper(p, &res->sr_offset);
110262306a36Sopenharmony_ci	return 0;
110362306a36Sopenharmony_ci}
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_cistatic int decode_layoutstats(struct xdr_stream *xdr)
110662306a36Sopenharmony_ci{
110762306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
110862306a36Sopenharmony_ci}
110962306a36Sopenharmony_ci
111062306a36Sopenharmony_cistatic int decode_clone(struct xdr_stream *xdr)
111162306a36Sopenharmony_ci{
111262306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_CLONE);
111362306a36Sopenharmony_ci}
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_cistatic int decode_layouterror(struct xdr_stream *xdr)
111662306a36Sopenharmony_ci{
111762306a36Sopenharmony_ci	return decode_op_hdr(xdr, OP_LAYOUTERROR);
111862306a36Sopenharmony_ci}
111962306a36Sopenharmony_ci
112062306a36Sopenharmony_cistatic int decode_setxattr(struct xdr_stream *xdr,
112162306a36Sopenharmony_ci			   struct nfs4_change_info *cinfo)
112262306a36Sopenharmony_ci{
112362306a36Sopenharmony_ci	int status;
112462306a36Sopenharmony_ci
112562306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_SETXATTR);
112662306a36Sopenharmony_ci	if (status)
112762306a36Sopenharmony_ci		goto out;
112862306a36Sopenharmony_ci	status = decode_change_info(xdr, cinfo);
112962306a36Sopenharmony_ciout:
113062306a36Sopenharmony_ci	return status;
113162306a36Sopenharmony_ci}
113262306a36Sopenharmony_ci
113362306a36Sopenharmony_cistatic int decode_getxattr(struct xdr_stream *xdr,
113462306a36Sopenharmony_ci			   struct nfs42_getxattrres *res,
113562306a36Sopenharmony_ci			   struct rpc_rqst *req)
113662306a36Sopenharmony_ci{
113762306a36Sopenharmony_ci	int status;
113862306a36Sopenharmony_ci	__be32 *p;
113962306a36Sopenharmony_ci	u32 len, rdlen;
114062306a36Sopenharmony_ci
114162306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_GETXATTR);
114262306a36Sopenharmony_ci	if (status)
114362306a36Sopenharmony_ci		return status;
114462306a36Sopenharmony_ci
114562306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
114662306a36Sopenharmony_ci	if (unlikely(!p))
114762306a36Sopenharmony_ci		return -EIO;
114862306a36Sopenharmony_ci
114962306a36Sopenharmony_ci	len = be32_to_cpup(p);
115062306a36Sopenharmony_ci
115162306a36Sopenharmony_ci	/*
115262306a36Sopenharmony_ci	 * Only check against the page length here. The actual
115362306a36Sopenharmony_ci	 * requested length may be smaller, but that is only
115462306a36Sopenharmony_ci	 * checked against after possibly caching a valid reply.
115562306a36Sopenharmony_ci	 */
115662306a36Sopenharmony_ci	if (len > req->rq_rcv_buf.page_len)
115762306a36Sopenharmony_ci		return -ERANGE;
115862306a36Sopenharmony_ci
115962306a36Sopenharmony_ci	res->xattr_len = len;
116062306a36Sopenharmony_ci
116162306a36Sopenharmony_ci	if (len > 0) {
116262306a36Sopenharmony_ci		rdlen = xdr_read_pages(xdr, len);
116362306a36Sopenharmony_ci		if (rdlen < len)
116462306a36Sopenharmony_ci			return -EIO;
116562306a36Sopenharmony_ci	}
116662306a36Sopenharmony_ci
116762306a36Sopenharmony_ci	return 0;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_cistatic int decode_removexattr(struct xdr_stream *xdr,
117162306a36Sopenharmony_ci			   struct nfs4_change_info *cinfo)
117262306a36Sopenharmony_ci{
117362306a36Sopenharmony_ci	int status;
117462306a36Sopenharmony_ci
117562306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_REMOVEXATTR);
117662306a36Sopenharmony_ci	if (status)
117762306a36Sopenharmony_ci		goto out;
117862306a36Sopenharmony_ci
117962306a36Sopenharmony_ci	status = decode_change_info(xdr, cinfo);
118062306a36Sopenharmony_ciout:
118162306a36Sopenharmony_ci	return status;
118262306a36Sopenharmony_ci}
118362306a36Sopenharmony_ci
118462306a36Sopenharmony_cistatic int decode_listxattrs(struct xdr_stream *xdr,
118562306a36Sopenharmony_ci			    struct nfs42_listxattrsres *res)
118662306a36Sopenharmony_ci{
118762306a36Sopenharmony_ci	int status;
118862306a36Sopenharmony_ci	__be32 *p;
118962306a36Sopenharmony_ci	u32 count, len, ulen;
119062306a36Sopenharmony_ci	size_t left, copied;
119162306a36Sopenharmony_ci	char *buf;
119262306a36Sopenharmony_ci
119362306a36Sopenharmony_ci	status = decode_op_hdr(xdr, OP_LISTXATTRS);
119462306a36Sopenharmony_ci	if (status) {
119562306a36Sopenharmony_ci		/*
119662306a36Sopenharmony_ci		 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
119762306a36Sopenharmony_ci		 * should be translated to ERANGE.
119862306a36Sopenharmony_ci		 */
119962306a36Sopenharmony_ci		if (status == -ETOOSMALL)
120062306a36Sopenharmony_ci			status = -ERANGE;
120162306a36Sopenharmony_ci		/*
120262306a36Sopenharmony_ci		 * Special case: for LISTXATTRS, NFS4ERR_NOXATTR
120362306a36Sopenharmony_ci		 * should be translated to success with zero-length reply.
120462306a36Sopenharmony_ci		 */
120562306a36Sopenharmony_ci		if (status == -ENODATA) {
120662306a36Sopenharmony_ci			res->eof = true;
120762306a36Sopenharmony_ci			status = 0;
120862306a36Sopenharmony_ci		}
120962306a36Sopenharmony_ci		goto out;
121062306a36Sopenharmony_ci	}
121162306a36Sopenharmony_ci
121262306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 8);
121362306a36Sopenharmony_ci	if (unlikely(!p))
121462306a36Sopenharmony_ci		return -EIO;
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	xdr_decode_hyper(p, &res->cookie);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
121962306a36Sopenharmony_ci	if (unlikely(!p))
122062306a36Sopenharmony_ci		return -EIO;
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci	left = res->xattr_len;
122362306a36Sopenharmony_ci	buf = res->xattr_buf;
122462306a36Sopenharmony_ci
122562306a36Sopenharmony_ci	count = be32_to_cpup(p);
122662306a36Sopenharmony_ci	copied = 0;
122762306a36Sopenharmony_ci
122862306a36Sopenharmony_ci	/*
122962306a36Sopenharmony_ci	 * We have asked for enough room to encode the maximum number
123062306a36Sopenharmony_ci	 * of possible attribute names, so everything should fit.
123162306a36Sopenharmony_ci	 *
123262306a36Sopenharmony_ci	 * But, don't rely on that assumption. Just decode entries
123362306a36Sopenharmony_ci	 * until they don't fit anymore, just in case the server did
123462306a36Sopenharmony_ci	 * something odd.
123562306a36Sopenharmony_ci	 */
123662306a36Sopenharmony_ci	while (count--) {
123762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, 4);
123862306a36Sopenharmony_ci		if (unlikely(!p))
123962306a36Sopenharmony_ci			return -EIO;
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci		len = be32_to_cpup(p);
124262306a36Sopenharmony_ci		if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
124362306a36Sopenharmony_ci			status = -ERANGE;
124462306a36Sopenharmony_ci			goto out;
124562306a36Sopenharmony_ci		}
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci		p = xdr_inline_decode(xdr, len);
124862306a36Sopenharmony_ci		if (unlikely(!p))
124962306a36Sopenharmony_ci			return -EIO;
125062306a36Sopenharmony_ci
125162306a36Sopenharmony_ci		ulen = len + XATTR_USER_PREFIX_LEN + 1;
125262306a36Sopenharmony_ci		if (buf) {
125362306a36Sopenharmony_ci			if (ulen > left) {
125462306a36Sopenharmony_ci				status = -ERANGE;
125562306a36Sopenharmony_ci				goto out;
125662306a36Sopenharmony_ci			}
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci			memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
125962306a36Sopenharmony_ci			memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
126062306a36Sopenharmony_ci
126162306a36Sopenharmony_ci			buf[ulen - 1] = 0;
126262306a36Sopenharmony_ci			buf += ulen;
126362306a36Sopenharmony_ci			left -= ulen;
126462306a36Sopenharmony_ci		}
126562306a36Sopenharmony_ci		copied += ulen;
126662306a36Sopenharmony_ci	}
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	p = xdr_inline_decode(xdr, 4);
126962306a36Sopenharmony_ci	if (unlikely(!p))
127062306a36Sopenharmony_ci		return -EIO;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	res->eof = be32_to_cpup(p);
127362306a36Sopenharmony_ci	res->copied = copied;
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ciout:
127662306a36Sopenharmony_ci	if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
127762306a36Sopenharmony_ci		status = -E2BIG;
127862306a36Sopenharmony_ci
127962306a36Sopenharmony_ci	return status;
128062306a36Sopenharmony_ci}
128162306a36Sopenharmony_ci
128262306a36Sopenharmony_ci/*
128362306a36Sopenharmony_ci * Decode ALLOCATE request
128462306a36Sopenharmony_ci */
128562306a36Sopenharmony_cistatic int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
128662306a36Sopenharmony_ci				 struct xdr_stream *xdr,
128762306a36Sopenharmony_ci				 void *data)
128862306a36Sopenharmony_ci{
128962306a36Sopenharmony_ci	struct nfs42_falloc_res *res = data;
129062306a36Sopenharmony_ci	struct compound_hdr hdr;
129162306a36Sopenharmony_ci	int status;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
129462306a36Sopenharmony_ci	if (status)
129562306a36Sopenharmony_ci		goto out;
129662306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
129762306a36Sopenharmony_ci	if (status)
129862306a36Sopenharmony_ci		goto out;
129962306a36Sopenharmony_ci	status = decode_putfh(xdr);
130062306a36Sopenharmony_ci	if (status)
130162306a36Sopenharmony_ci		goto out;
130262306a36Sopenharmony_ci	status = decode_allocate(xdr, res);
130362306a36Sopenharmony_ci	if (status)
130462306a36Sopenharmony_ci		goto out;
130562306a36Sopenharmony_ci	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
130662306a36Sopenharmony_ciout:
130762306a36Sopenharmony_ci	return status;
130862306a36Sopenharmony_ci}
130962306a36Sopenharmony_ci
131062306a36Sopenharmony_ci/*
131162306a36Sopenharmony_ci * Decode COPY response
131262306a36Sopenharmony_ci */
131362306a36Sopenharmony_cistatic int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
131462306a36Sopenharmony_ci			     struct xdr_stream *xdr,
131562306a36Sopenharmony_ci			     void *data)
131662306a36Sopenharmony_ci{
131762306a36Sopenharmony_ci	struct nfs42_copy_res *res = data;
131862306a36Sopenharmony_ci	struct compound_hdr hdr;
131962306a36Sopenharmony_ci	int status;
132062306a36Sopenharmony_ci
132162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
132262306a36Sopenharmony_ci	if (status)
132362306a36Sopenharmony_ci		goto out;
132462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
132562306a36Sopenharmony_ci	if (status)
132662306a36Sopenharmony_ci		goto out;
132762306a36Sopenharmony_ci	status = decode_putfh(xdr);
132862306a36Sopenharmony_ci	if (status)
132962306a36Sopenharmony_ci		goto out;
133062306a36Sopenharmony_ci	status = decode_savefh(xdr);
133162306a36Sopenharmony_ci	if (status)
133262306a36Sopenharmony_ci		goto out;
133362306a36Sopenharmony_ci	status = decode_putfh(xdr);
133462306a36Sopenharmony_ci	if (status)
133562306a36Sopenharmony_ci		goto out;
133662306a36Sopenharmony_ci	status = decode_copy(xdr, res);
133762306a36Sopenharmony_ci	if (status)
133862306a36Sopenharmony_ci		goto out;
133962306a36Sopenharmony_ci	if (res->commit_res.verf)
134062306a36Sopenharmony_ci		status = decode_commit(xdr, &res->commit_res);
134162306a36Sopenharmony_ciout:
134262306a36Sopenharmony_ci	return status;
134362306a36Sopenharmony_ci}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_ci/*
134662306a36Sopenharmony_ci * Decode OFFLOAD_CANCEL response
134762306a36Sopenharmony_ci */
134862306a36Sopenharmony_cistatic int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
134962306a36Sopenharmony_ci				       struct xdr_stream *xdr,
135062306a36Sopenharmony_ci				       void *data)
135162306a36Sopenharmony_ci{
135262306a36Sopenharmony_ci	struct nfs42_offload_status_res *res = data;
135362306a36Sopenharmony_ci	struct compound_hdr hdr;
135462306a36Sopenharmony_ci	int status;
135562306a36Sopenharmony_ci
135662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
135762306a36Sopenharmony_ci	if (status)
135862306a36Sopenharmony_ci		goto out;
135962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
136062306a36Sopenharmony_ci	if (status)
136162306a36Sopenharmony_ci		goto out;
136262306a36Sopenharmony_ci	status = decode_putfh(xdr);
136362306a36Sopenharmony_ci	if (status)
136462306a36Sopenharmony_ci		goto out;
136562306a36Sopenharmony_ci	status = decode_offload_cancel(xdr, res);
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ciout:
136862306a36Sopenharmony_ci	return status;
136962306a36Sopenharmony_ci}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci/*
137262306a36Sopenharmony_ci * Decode COPY_NOTIFY response
137362306a36Sopenharmony_ci */
137462306a36Sopenharmony_cistatic int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
137562306a36Sopenharmony_ci				    struct xdr_stream *xdr,
137662306a36Sopenharmony_ci				    void *data)
137762306a36Sopenharmony_ci{
137862306a36Sopenharmony_ci	struct nfs42_copy_notify_res *res = data;
137962306a36Sopenharmony_ci	struct compound_hdr hdr;
138062306a36Sopenharmony_ci	int status;
138162306a36Sopenharmony_ci
138262306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
138362306a36Sopenharmony_ci	if (status)
138462306a36Sopenharmony_ci		goto out;
138562306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
138662306a36Sopenharmony_ci	if (status)
138762306a36Sopenharmony_ci		goto out;
138862306a36Sopenharmony_ci	status = decode_putfh(xdr);
138962306a36Sopenharmony_ci	if (status)
139062306a36Sopenharmony_ci		goto out;
139162306a36Sopenharmony_ci	status = decode_copy_notify(xdr, res);
139262306a36Sopenharmony_ci
139362306a36Sopenharmony_ciout:
139462306a36Sopenharmony_ci	return status;
139562306a36Sopenharmony_ci}
139662306a36Sopenharmony_ci
139762306a36Sopenharmony_ci/*
139862306a36Sopenharmony_ci * Decode DEALLOCATE request
139962306a36Sopenharmony_ci */
140062306a36Sopenharmony_cistatic int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
140162306a36Sopenharmony_ci				   struct xdr_stream *xdr,
140262306a36Sopenharmony_ci				   void *data)
140362306a36Sopenharmony_ci{
140462306a36Sopenharmony_ci	struct nfs42_falloc_res *res = data;
140562306a36Sopenharmony_ci	struct compound_hdr hdr;
140662306a36Sopenharmony_ci	int status;
140762306a36Sopenharmony_ci
140862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
140962306a36Sopenharmony_ci	if (status)
141062306a36Sopenharmony_ci		goto out;
141162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
141262306a36Sopenharmony_ci	if (status)
141362306a36Sopenharmony_ci		goto out;
141462306a36Sopenharmony_ci	status = decode_putfh(xdr);
141562306a36Sopenharmony_ci	if (status)
141662306a36Sopenharmony_ci		goto out;
141762306a36Sopenharmony_ci	status = decode_deallocate(xdr, res);
141862306a36Sopenharmony_ci	if (status)
141962306a36Sopenharmony_ci		goto out;
142062306a36Sopenharmony_ci	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
142162306a36Sopenharmony_ciout:
142262306a36Sopenharmony_ci	return status;
142362306a36Sopenharmony_ci}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_ci/*
142662306a36Sopenharmony_ci * Decode READ_PLUS request
142762306a36Sopenharmony_ci */
142862306a36Sopenharmony_cistatic int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
142962306a36Sopenharmony_ci				  struct xdr_stream *xdr,
143062306a36Sopenharmony_ci				  void *data)
143162306a36Sopenharmony_ci{
143262306a36Sopenharmony_ci	struct nfs_pgio_res *res = data;
143362306a36Sopenharmony_ci	struct compound_hdr hdr;
143462306a36Sopenharmony_ci	int status;
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_ci	xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE);
143762306a36Sopenharmony_ci
143862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
143962306a36Sopenharmony_ci	if (status)
144062306a36Sopenharmony_ci		goto out;
144162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
144262306a36Sopenharmony_ci	if (status)
144362306a36Sopenharmony_ci		goto out;
144462306a36Sopenharmony_ci	status = decode_putfh(xdr);
144562306a36Sopenharmony_ci	if (status)
144662306a36Sopenharmony_ci		goto out;
144762306a36Sopenharmony_ci	status = decode_read_plus(xdr, res);
144862306a36Sopenharmony_ci	if (!status)
144962306a36Sopenharmony_ci		status = res->count;
145062306a36Sopenharmony_ciout:
145162306a36Sopenharmony_ci	return status;
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_ci/*
145562306a36Sopenharmony_ci * Decode SEEK request
145662306a36Sopenharmony_ci */
145762306a36Sopenharmony_cistatic int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
145862306a36Sopenharmony_ci			     struct xdr_stream *xdr,
145962306a36Sopenharmony_ci			     void *data)
146062306a36Sopenharmony_ci{
146162306a36Sopenharmony_ci	struct nfs42_seek_res *res = data;
146262306a36Sopenharmony_ci	struct compound_hdr hdr;
146362306a36Sopenharmony_ci	int status;
146462306a36Sopenharmony_ci
146562306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
146662306a36Sopenharmony_ci	if (status)
146762306a36Sopenharmony_ci		goto out;
146862306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
146962306a36Sopenharmony_ci	if (status)
147062306a36Sopenharmony_ci		goto out;
147162306a36Sopenharmony_ci	status = decode_putfh(xdr);
147262306a36Sopenharmony_ci	if (status)
147362306a36Sopenharmony_ci		goto out;
147462306a36Sopenharmony_ci	status = decode_seek(xdr, res);
147562306a36Sopenharmony_ciout:
147662306a36Sopenharmony_ci	return status;
147762306a36Sopenharmony_ci}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci/*
148062306a36Sopenharmony_ci * Decode LAYOUTSTATS request
148162306a36Sopenharmony_ci */
148262306a36Sopenharmony_cistatic int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
148362306a36Sopenharmony_ci				    struct xdr_stream *xdr,
148462306a36Sopenharmony_ci				    void *data)
148562306a36Sopenharmony_ci{
148662306a36Sopenharmony_ci	struct nfs42_layoutstat_res *res = data;
148762306a36Sopenharmony_ci	struct compound_hdr hdr;
148862306a36Sopenharmony_ci	int status, i;
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
149162306a36Sopenharmony_ci	if (status)
149262306a36Sopenharmony_ci		goto out;
149362306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
149462306a36Sopenharmony_ci	if (status)
149562306a36Sopenharmony_ci		goto out;
149662306a36Sopenharmony_ci	status = decode_putfh(xdr);
149762306a36Sopenharmony_ci	if (status)
149862306a36Sopenharmony_ci		goto out;
149962306a36Sopenharmony_ci	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
150062306a36Sopenharmony_ci	for (i = 0; i < res->num_dev; i++) {
150162306a36Sopenharmony_ci		status = decode_layoutstats(xdr);
150262306a36Sopenharmony_ci		if (status)
150362306a36Sopenharmony_ci			goto out;
150462306a36Sopenharmony_ci	}
150562306a36Sopenharmony_ciout:
150662306a36Sopenharmony_ci	res->rpc_status = status;
150762306a36Sopenharmony_ci	return status;
150862306a36Sopenharmony_ci}
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ci/*
151162306a36Sopenharmony_ci * Decode CLONE request
151262306a36Sopenharmony_ci */
151362306a36Sopenharmony_cistatic int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
151462306a36Sopenharmony_ci			      struct xdr_stream *xdr,
151562306a36Sopenharmony_ci			      void *data)
151662306a36Sopenharmony_ci{
151762306a36Sopenharmony_ci	struct nfs42_clone_res *res = data;
151862306a36Sopenharmony_ci	struct compound_hdr hdr;
151962306a36Sopenharmony_ci	int status;
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
152262306a36Sopenharmony_ci	if (status)
152362306a36Sopenharmony_ci		goto out;
152462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
152562306a36Sopenharmony_ci	if (status)
152662306a36Sopenharmony_ci		goto out;
152762306a36Sopenharmony_ci	status = decode_putfh(xdr);
152862306a36Sopenharmony_ci	if (status)
152962306a36Sopenharmony_ci		goto out;
153062306a36Sopenharmony_ci	status = decode_savefh(xdr);
153162306a36Sopenharmony_ci	if (status)
153262306a36Sopenharmony_ci		goto out;
153362306a36Sopenharmony_ci	status = decode_putfh(xdr);
153462306a36Sopenharmony_ci	if (status)
153562306a36Sopenharmony_ci		goto out;
153662306a36Sopenharmony_ci	status = decode_clone(xdr);
153762306a36Sopenharmony_ci	if (status)
153862306a36Sopenharmony_ci		goto out;
153962306a36Sopenharmony_ci	decode_getfattr(xdr, res->dst_fattr, res->server);
154062306a36Sopenharmony_ciout:
154162306a36Sopenharmony_ci	res->rpc_status = status;
154262306a36Sopenharmony_ci	return status;
154362306a36Sopenharmony_ci}
154462306a36Sopenharmony_ci
154562306a36Sopenharmony_ci/*
154662306a36Sopenharmony_ci * Decode LAYOUTERROR request
154762306a36Sopenharmony_ci */
154862306a36Sopenharmony_cistatic int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
154962306a36Sopenharmony_ci				    struct xdr_stream *xdr,
155062306a36Sopenharmony_ci				    void *data)
155162306a36Sopenharmony_ci{
155262306a36Sopenharmony_ci	struct nfs42_layouterror_res *res = data;
155362306a36Sopenharmony_ci	struct compound_hdr hdr;
155462306a36Sopenharmony_ci	int status, i;
155562306a36Sopenharmony_ci
155662306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
155762306a36Sopenharmony_ci	if (status)
155862306a36Sopenharmony_ci		goto out;
155962306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
156062306a36Sopenharmony_ci	if (status)
156162306a36Sopenharmony_ci		goto out;
156262306a36Sopenharmony_ci	status = decode_putfh(xdr);
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	for (i = 0; i < res->num_errors && status == 0; i++)
156562306a36Sopenharmony_ci		status = decode_layouterror(xdr);
156662306a36Sopenharmony_ciout:
156762306a36Sopenharmony_ci	res->rpc_status = status;
156862306a36Sopenharmony_ci	return status;
156962306a36Sopenharmony_ci}
157062306a36Sopenharmony_ci
157162306a36Sopenharmony_ci/*
157262306a36Sopenharmony_ci * Decode SETXATTR request
157362306a36Sopenharmony_ci */
157462306a36Sopenharmony_cistatic int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
157562306a36Sopenharmony_ci				 void *data)
157662306a36Sopenharmony_ci{
157762306a36Sopenharmony_ci	struct nfs42_setxattrres *res = data;
157862306a36Sopenharmony_ci	struct compound_hdr hdr;
157962306a36Sopenharmony_ci	int status;
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
158262306a36Sopenharmony_ci	if (status)
158362306a36Sopenharmony_ci		goto out;
158462306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, req);
158562306a36Sopenharmony_ci	if (status)
158662306a36Sopenharmony_ci		goto out;
158762306a36Sopenharmony_ci	status = decode_putfh(xdr);
158862306a36Sopenharmony_ci	if (status)
158962306a36Sopenharmony_ci		goto out;
159062306a36Sopenharmony_ci	status = decode_setxattr(xdr, &res->cinfo);
159162306a36Sopenharmony_ci	if (status)
159262306a36Sopenharmony_ci		goto out;
159362306a36Sopenharmony_ci	status = decode_getfattr(xdr, res->fattr, res->server);
159462306a36Sopenharmony_ciout:
159562306a36Sopenharmony_ci	return status;
159662306a36Sopenharmony_ci}
159762306a36Sopenharmony_ci
159862306a36Sopenharmony_ci/*
159962306a36Sopenharmony_ci * Decode GETXATTR request
160062306a36Sopenharmony_ci */
160162306a36Sopenharmony_cistatic int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
160262306a36Sopenharmony_ci				 struct xdr_stream *xdr, void *data)
160362306a36Sopenharmony_ci{
160462306a36Sopenharmony_ci	struct nfs42_getxattrres *res = data;
160562306a36Sopenharmony_ci	struct compound_hdr hdr;
160662306a36Sopenharmony_ci	int status;
160762306a36Sopenharmony_ci
160862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
160962306a36Sopenharmony_ci	if (status)
161062306a36Sopenharmony_ci		goto out;
161162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
161262306a36Sopenharmony_ci	if (status)
161362306a36Sopenharmony_ci		goto out;
161462306a36Sopenharmony_ci	status = decode_putfh(xdr);
161562306a36Sopenharmony_ci	if (status)
161662306a36Sopenharmony_ci		goto out;
161762306a36Sopenharmony_ci	status = decode_getxattr(xdr, res, rqstp);
161862306a36Sopenharmony_ciout:
161962306a36Sopenharmony_ci	return status;
162062306a36Sopenharmony_ci}
162162306a36Sopenharmony_ci
162262306a36Sopenharmony_ci/*
162362306a36Sopenharmony_ci * Decode LISTXATTR request
162462306a36Sopenharmony_ci */
162562306a36Sopenharmony_cistatic int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
162662306a36Sopenharmony_ci				   struct xdr_stream *xdr, void *data)
162762306a36Sopenharmony_ci{
162862306a36Sopenharmony_ci	struct nfs42_listxattrsres *res = data;
162962306a36Sopenharmony_ci	struct compound_hdr hdr;
163062306a36Sopenharmony_ci	int status;
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	xdr_set_scratch_page(xdr, res->scratch);
163362306a36Sopenharmony_ci
163462306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
163562306a36Sopenharmony_ci	if (status)
163662306a36Sopenharmony_ci		goto out;
163762306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, rqstp);
163862306a36Sopenharmony_ci	if (status)
163962306a36Sopenharmony_ci		goto out;
164062306a36Sopenharmony_ci	status = decode_putfh(xdr);
164162306a36Sopenharmony_ci	if (status)
164262306a36Sopenharmony_ci		goto out;
164362306a36Sopenharmony_ci	status = decode_listxattrs(xdr, res);
164462306a36Sopenharmony_ciout:
164562306a36Sopenharmony_ci	return status;
164662306a36Sopenharmony_ci}
164762306a36Sopenharmony_ci
164862306a36Sopenharmony_ci/*
164962306a36Sopenharmony_ci * Decode REMOVEXATTR request
165062306a36Sopenharmony_ci */
165162306a36Sopenharmony_cistatic int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
165262306a36Sopenharmony_ci				    struct xdr_stream *xdr, void *data)
165362306a36Sopenharmony_ci{
165462306a36Sopenharmony_ci	struct nfs42_removexattrres *res = data;
165562306a36Sopenharmony_ci	struct compound_hdr hdr;
165662306a36Sopenharmony_ci	int status;
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci	status = decode_compound_hdr(xdr, &hdr);
165962306a36Sopenharmony_ci	if (status)
166062306a36Sopenharmony_ci		goto out;
166162306a36Sopenharmony_ci	status = decode_sequence(xdr, &res->seq_res, req);
166262306a36Sopenharmony_ci	if (status)
166362306a36Sopenharmony_ci		goto out;
166462306a36Sopenharmony_ci	status = decode_putfh(xdr);
166562306a36Sopenharmony_ci	if (status)
166662306a36Sopenharmony_ci		goto out;
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci	status = decode_removexattr(xdr, &res->cinfo);
166962306a36Sopenharmony_ciout:
167062306a36Sopenharmony_ci	return status;
167162306a36Sopenharmony_ci}
167262306a36Sopenharmony_ci#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
1673