blob: c37473721230df28f405bec137725da654cf94fe [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * fs/nfs/nfs4xdr.c
3 *
4 * Client-side XDR for NFSv4.
5 *
6 * Copyright (c) 2002 The Regents of the University of Michigan.
7 * All rights reserved.
8 *
9 * Kendrick Smith <kmsmith@umich.edu>
10 * Andy Adamson <andros@umich.edu>
Andy Adamson6c0195a2008-12-23 16:06:15 -050011 *
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
14 * are met:
15 *
16 * 1. Redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer.
18 * 2. Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution.
21 * 3. Neither the name of the University nor the names of its
22 * contributors may be used to endorse or promote products derived
23 * from this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
26 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
27 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28 * DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
32 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
34 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
35 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#include <linux/param.h>
39#include <linux/time.h>
40#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070041#include <linux/errno.h>
42#include <linux/string.h>
43#include <linux/in.h>
44#include <linux/pagemap.h>
45#include <linux/proc_fs.h>
46#include <linux/kdev_t.h>
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -050047#include <linux/module.h>
48#include <linux/utsname.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070049#include <linux/sunrpc/clnt.h>
Alexandros Batsakis2449ea22009-12-05 13:36:55 -050050#include <linux/sunrpc/msg_prot.h>
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +000051#include <linux/sunrpc/gss_api.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070052#include <linux/nfs.h>
53#include <linux/nfs4.h>
54#include <linux/nfs_fs.h>
Chuck Leverf0920752012-05-21 22:45:41 -040055
Trond Myklebust4ce79712005-06-22 17:16:21 +000056#include "nfs4_fs.h"
Alexandros Batsakis4882ef72009-12-05 13:30:21 -050057#include "internal.h"
Anna Schumaker40c64c22015-04-15 13:00:05 -040058#include "nfs4idmap.h"
Trond Myklebust76e697b2012-11-26 14:20:49 -050059#include "nfs4session.h"
Andy Adamsonb1f69b72010-10-20 00:18:03 -040060#include "pnfs.h"
Chuck Leverf0920752012-05-21 22:45:41 -040061#include "netns.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63#define NFSDBG_FACILITY NFSDBG_XDR
64
65/* Mapping from NFS error code to "errno" error code. */
66#define errno_NFSERR_IO EIO
67
David Howells0a8ea432006-08-22 20:06:08 -040068static int nfs4_stat_to_errno(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -070069
70/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
71#ifdef DEBUG
72#define NFS4_MAXTAGLEN 20
73#else
74#define NFS4_MAXTAGLEN 0
75#endif
76
Andy Adamson6c0195a2008-12-23 16:06:15 -050077/* lock,open owner id:
Trond Myklebust9f958ab2007-07-02 13:58:33 -040078 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070079 */
Trond Myklebust95b72eb2012-04-20 19:24:51 -040080#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2)
Trond Myklebustd035c362010-12-21 10:45:27 -050081#define lock_owner_id_maxsz (1 + 1 + 4)
Trond Myklebust9104a552007-07-17 21:52:42 -040082#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -070083#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
84#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
85#define op_encode_hdr_maxsz (1)
86#define op_decode_hdr_maxsz (2)
Trond Myklebust9104a552007-07-17 21:52:42 -040087#define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
88#define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
89#define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
90#define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -070091#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
92 (NFS4_FHSIZE >> 2))
93#define decode_putfh_maxsz (op_decode_hdr_maxsz)
94#define encode_putrootfh_maxsz (op_encode_hdr_maxsz)
95#define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
96#define encode_getfh_maxsz (op_encode_hdr_maxsz)
97#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
98 ((3+NFS4_FHSIZE) >> 2))
Andy Adamsone5012d12011-07-11 17:17:42 -040099#define nfs4_fattr_bitmap_maxsz 4
J. Bruce Fields96928202005-06-22 17:16:22 +0000100#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
102#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
Trond Myklebustbd625ba2007-07-08 18:38:23 -0400103#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
104#define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
David Quigleyaa9c2662013-05-22 12:50:44 -0400105#ifdef CONFIG_NFS_V4_SECURITY_LABEL
106/* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
107#define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
David Quigleyaa9c2662013-05-22 12:50:44 -0400108#else
109#define nfs4_label_maxsz 0
David Quigleyaa9c2662013-05-22 12:50:44 -0400110#endif
Andy Adamson88034c32012-05-23 05:02:34 -0400111/* We support only one layout type per file system */
112#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
J. Bruce Fields96928202005-06-22 17:16:22 +0000113/* This is based on getfattr, which uses the most attributes: */
114#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
Andy Adamson88034c32012-05-23 05:02:34 -0400115 3 + 3 + 3 + nfs4_owner_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400116 nfs4_group_maxsz + nfs4_label_maxsz + \
117 decode_mdsthreshold_maxsz))
J. Bruce Fields96928202005-06-22 17:16:22 +0000118#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
119 nfs4_fattr_value_maxsz)
120#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400121#define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \
122 1 + 2 + 1 + \
123 nfs4_owner_maxsz + \
124 nfs4_group_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400125 nfs4_label_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400126 4 + 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700127#define encode_savefh_maxsz (op_encode_hdr_maxsz)
128#define decode_savefh_maxsz (op_decode_hdr_maxsz)
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400129#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
130#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
Fred Isaman2f42b5d2008-03-13 15:26:30 +0200131#define encode_fsinfo_maxsz (encode_getattr_maxsz)
Fred Isamandae100c2011-07-30 20:52:37 -0400132/* The 5 accounts for the PNFS attributes, and assumes that at most three
133 * layout types will be returned.
134 */
135#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \
136 nfs4_fattr_bitmap_maxsz + 4 + 8 + 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
138#define decode_renew_maxsz (op_decode_hdr_maxsz)
139#define encode_setclientid_maxsz \
140 (op_encode_hdr_maxsz + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500141 XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
Jeff Laytonb8fb2f52015-06-09 19:43:58 -0400142 /* client name */ \
143 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500144 1 /* sc_prog */ + \
Chuck Lever6dd34362014-11-08 20:15:18 -0500145 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
146 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500147 1) /* sc_cb_ident */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148#define decode_setclientid_maxsz \
149 (op_decode_hdr_maxsz + \
Chuck Lever6dd34362014-11-08 20:15:18 -0500150 2 /* clientid */ + \
151 XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
152 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
153 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700154#define encode_setclientid_confirm_maxsz \
155 (op_encode_hdr_maxsz + \
156 3 + (NFS4_VERIFIER_SIZE >> 2))
157#define decode_setclientid_confirm_maxsz \
158 (op_decode_hdr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400159#define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
160#define decode_lookup_maxsz (op_decode_hdr_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400161#define encode_share_access_maxsz \
162 (2)
Alexandros Batsakis4882ef72009-12-05 13:30:21 -0500163#define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400164#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
165#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
166#define encode_open_maxsz (op_encode_hdr_maxsz + \
167 2 + encode_share_access_maxsz + 2 + \
168 open_owner_id_maxsz + \
169 encode_opentype_maxsz + \
170 encode_claim_null_maxsz)
171#define decode_ace_maxsz (3 + nfs4_owner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400172#define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400173 decode_ace_maxsz)
174#define decode_change_info_maxsz (5)
175#define decode_open_maxsz (op_decode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400176 decode_stateid_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400177 decode_change_info_maxsz + 1 + \
178 nfs4_fattr_bitmap_maxsz + \
179 decode_delegation_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400180#define encode_open_confirm_maxsz \
181 (op_encode_hdr_maxsz + \
182 encode_stateid_maxsz + 1)
183#define decode_open_confirm_maxsz \
184 (op_decode_hdr_maxsz + \
185 decode_stateid_maxsz)
186#define encode_open_downgrade_maxsz \
187 (op_encode_hdr_maxsz + \
188 encode_stateid_maxsz + 1 + \
189 encode_share_access_maxsz)
190#define decode_open_downgrade_maxsz \
191 (op_decode_hdr_maxsz + \
192 decode_stateid_maxsz)
193#define encode_close_maxsz (op_encode_hdr_maxsz + \
194 1 + encode_stateid_maxsz)
195#define decode_close_maxsz (op_decode_hdr_maxsz + \
196 decode_stateid_maxsz)
197#define encode_setattr_maxsz (op_encode_hdr_maxsz + \
198 encode_stateid_maxsz + \
199 encode_attrs_maxsz)
200#define decode_setattr_maxsz (op_decode_hdr_maxsz + \
201 nfs4_fattr_bitmap_maxsz)
202#define encode_read_maxsz (op_encode_hdr_maxsz + \
203 encode_stateid_maxsz + 3)
204#define decode_read_maxsz (op_decode_hdr_maxsz + 2)
205#define encode_readdir_maxsz (op_encode_hdr_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400206 2 + encode_verifier_maxsz + 5 + \
207 nfs4_label_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400208#define decode_readdir_maxsz (op_decode_hdr_maxsz + \
Chuck Levera7697f62014-03-12 12:51:17 -0400209 decode_verifier_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400210#define encode_readlink_maxsz (op_encode_hdr_maxsz)
211#define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
212#define encode_write_maxsz (op_encode_hdr_maxsz + \
213 encode_stateid_maxsz + 4)
214#define decode_write_maxsz (op_decode_hdr_maxsz + \
215 2 + decode_verifier_maxsz)
216#define encode_commit_maxsz (op_encode_hdr_maxsz + 3)
217#define decode_commit_maxsz (op_decode_hdr_maxsz + \
218 decode_verifier_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700219#define encode_remove_maxsz (op_encode_hdr_maxsz + \
220 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400221#define decode_remove_maxsz (op_decode_hdr_maxsz + \
222 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700223#define encode_rename_maxsz (op_encode_hdr_maxsz + \
224 2 * nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400225#define decode_rename_maxsz (op_decode_hdr_maxsz + \
226 decode_change_info_maxsz + \
227 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700228#define encode_link_maxsz (op_encode_hdr_maxsz + \
229 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400230#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400231#define encode_lockowner_maxsz (7)
Trond Myklebust9104a552007-07-17 21:52:42 -0400232#define encode_lock_maxsz (op_encode_hdr_maxsz + \
233 7 + \
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400234 1 + encode_stateid_maxsz + 1 + \
235 encode_lockowner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400236#define decode_lock_denied_maxsz \
237 (8 + decode_lockowner_maxsz)
238#define decode_lock_maxsz (op_decode_hdr_maxsz + \
239 decode_lock_denied_maxsz)
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400240#define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \
241 encode_lockowner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400242#define decode_lockt_maxsz (op_decode_hdr_maxsz + \
243 decode_lock_denied_maxsz)
244#define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
245 encode_stateid_maxsz + \
246 4)
247#define decode_locku_maxsz (op_decode_hdr_maxsz + \
248 decode_stateid_maxsz)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -0400249#define encode_release_lockowner_maxsz \
250 (op_encode_hdr_maxsz + \
251 encode_lockowner_maxsz)
252#define decode_release_lockowner_maxsz \
253 (op_decode_hdr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400254#define encode_access_maxsz (op_encode_hdr_maxsz + 1)
255#define decode_access_maxsz (op_decode_hdr_maxsz + 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700256#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
257 1 + nfs4_name_maxsz + \
Chuck Lever94a6d752006-08-22 20:06:23 -0400258 1 + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000259 nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700260#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
261#define encode_create_maxsz (op_encode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400262 1 + 2 + nfs4_name_maxsz + \
263 encode_attrs_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400264#define decode_create_maxsz (op_decode_hdr_maxsz + \
265 decode_change_info_maxsz + \
266 nfs4_fattr_bitmap_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400267#define encode_statfs_maxsz (encode_getattr_maxsz)
268#define decode_statfs_maxsz (decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700269#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
270#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400271#define encode_getacl_maxsz (encode_getattr_maxsz)
272#define decode_getacl_maxsz (op_decode_hdr_maxsz + \
273 nfs4_fattr_bitmap_maxsz + 1)
274#define encode_setacl_maxsz (op_encode_hdr_maxsz + \
275 encode_stateid_maxsz + 3)
276#define decode_setacl_maxsz (decode_setattr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400277#define encode_fs_locations_maxsz \
278 (encode_getattr_maxsz)
279#define decode_fs_locations_maxsz \
280 (0)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +0000281#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
Bryan Schumaker1650add2011-06-02 15:07:35 -0400282#define decode_secinfo_maxsz (op_decode_hdr_maxsz + 1 + ((NFS_MAX_SECFLAVORS * (16 + GSS_OID_MAX_LEN)) / 4))
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400283
284#if defined(CONFIG_NFS_V4_1)
Andy Adamsonfc931582009-04-01 09:22:31 -0400285#define NFS4_MAX_MACHINE_NAME_LEN (64)
Jim Reesd751f742012-11-16 18:12:06 -0500286#define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
287 sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
Andy Adamsonfc931582009-04-01 09:22:31 -0400288
Benny Halevy99fe60d2009-04-01 09:22:29 -0400289#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
290 encode_verifier_maxsz + \
291 1 /* co_ownerid.len */ + \
Jeff Laytonb8fb2f52015-06-09 19:43:58 -0400292 /* eia_clientowner */ \
293 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
Benny Halevy99fe60d2009-04-01 09:22:29 -0400294 1 /* flags */ + \
295 1 /* spa_how */ + \
Weston Andros Adamson2031cd12013-08-13 16:37:32 -0400296 /* max is SP4_MACH_CRED (for now) */ + \
297 1 + NFS4_OP_MAP_NUM_WORDS + \
298 1 + NFS4_OP_MAP_NUM_WORDS + \
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -0500299 1 /* implementation id array of size 1 */ + \
300 1 /* nii_domain */ + \
301 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
302 1 /* nii_name */ + \
Jim Reesd751f742012-11-16 18:12:06 -0500303 XDR_QUADLEN(IMPL_NAME_LIMIT) + \
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -0500304 3 /* nii_date */)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400305#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
306 2 /* eir_clientid */ + \
307 1 /* eir_sequenceid */ + \
308 1 /* eir_flags */ + \
309 1 /* spr_how */ + \
Weston Andros Adamson2031cd12013-08-13 16:37:32 -0400310 /* max is SP4_MACH_CRED (for now) */ + \
311 1 + NFS4_OP_MAP_NUM_WORDS + \
312 1 + NFS4_OP_MAP_NUM_WORDS + \
Benny Halevy99fe60d2009-04-01 09:22:29 -0400313 2 /* eir_server_owner.so_minor_id */ + \
314 /* eir_server_owner.so_major_id<> */ \
315 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
316 /* eir_server_scope<> */ \
317 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
318 1 /* eir_server_impl_id array length */ + \
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -0500319 1 /* nii_domain */ + \
320 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
321 1 /* nii_name */ + \
322 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
323 3 /* nii_date */)
Andy Adamsonfc931582009-04-01 09:22:31 -0400324#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
325#define decode_channel_attrs_maxsz (6 + \
326 1 /* ca_rdma_ird.len */ + \
327 1 /* ca_rdma_ird */)
328#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
329 2 /* csa_clientid */ + \
330 1 /* csa_sequence */ + \
331 1 /* csa_flags */ + \
332 encode_channel_attrs_maxsz + \
333 encode_channel_attrs_maxsz + \
334 1 /* csa_cb_program */ + \
335 1 /* csa_sec_parms.len (1) */ + \
336 1 /* cb_secflavor (AUTH_SYS) */ + \
337 1 /* stamp */ + \
338 1 /* machinename.len */ + \
339 XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
340 1 /* uid */ + \
341 1 /* gid */ + \
342 1 /* gids.len (0) */)
343#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
344 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
345 1 /* csr_sequence */ + \
346 1 /* csr_flags */ + \
347 decode_channel_attrs_maxsz + \
348 decode_channel_attrs_maxsz)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -0400349#define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \
350 /* bctsa_sessid */ \
351 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
352 1 /* bctsa_dir */ + \
353 1 /* bctsa_use_conn_in_rdma_mode */)
354#define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \
355 /* bctsr_sessid */ \
356 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
357 1 /* bctsr_dir */ + \
358 1 /* bctsr_use_conn_in_rdma_mode */)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400359#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
360#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
Trond Myklebust66245532012-05-25 17:18:09 -0400361#define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2)
362#define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400363#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
364 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
365#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
366 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
Ricardo Labiaga180197532009-12-05 16:08:40 -0500367#define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4)
368#define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4)
Christoph Hellwig84c9dee2014-09-10 17:37:28 -0700369#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \
370 XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
371 1 /* layout type */ + \
372 1 /* maxcount */ + \
373 1 /* bitmap size */ + \
374 1 /* notification bitmap length */ + \
375 1 /* notification bitmap, word 0 */)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400376#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
377 1 /* layout type */ + \
378 1 /* opaque devaddr4 length */ + \
379 /* devaddr4 payload is read into page */ \
380 1 /* notification bitmap length */ + \
Christoph Hellwig84c9dee2014-09-10 17:37:28 -0700381 1 /* notification bitmap, word 0 */)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400382#define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \
383 encode_stateid_maxsz)
384#define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \
385 decode_stateid_maxsz + \
386 XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
Andy Adamson863a3c62011-03-23 13:27:54 +0000387#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \
388 2 /* offset */ + \
389 2 /* length */ + \
390 1 /* reclaim */ + \
391 encode_stateid_maxsz + \
392 1 /* new offset (true) */ + \
393 2 /* last byte written */ + \
394 1 /* nt_timechanged (false) */ + \
395 1 /* layoutupdate4 layout type */ + \
Christoph Hellwig5f919c92014-08-21 11:09:25 -0500396 1 /* layoutupdate4 opaqueue len */)
397 /* the actual content of layoutupdate4 should
398 be allocated by drivers and spliced in
399 using xdr_write_pages */
Andy Adamson863a3c62011-03-23 13:27:54 +0000400#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
Benny Halevycbe82602011-05-22 19:52:37 +0300401#define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \
402 encode_stateid_maxsz + \
Trond Myklebust6669cb82015-08-27 20:43:20 -0400403 1 + \
404 XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
Benny Halevycbe82602011-05-22 19:52:37 +0300405#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
406 1 + decode_stateid_maxsz)
Bryan Schumakerfca78d62011-06-02 14:59:07 -0400407#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
408#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
Bryan Schumaker7d974792011-06-02 14:59:08 -0400409#define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \
410 XDR_QUADLEN(NFS4_STATEID_SIZE))
411#define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1)
Bryan Schumaker9aeda352011-06-02 14:59:09 -0400412#define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \
413 XDR_QUADLEN(NFS4_STATEID_SIZE))
Andy Adamson9f79fb42013-09-10 12:56:29 -0400414#define decode_free_stateid_maxsz (op_decode_hdr_maxsz)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400415#else /* CONFIG_NFS_V4_1 */
416#define encode_sequence_maxsz 0
417#define decode_sequence_maxsz 0
418#endif /* CONFIG_NFS_V4_1 */
419
Linus Torvalds1da177e2005-04-16 15:20:36 -0700420#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
421#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
422#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400423 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400425 encode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700426#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400427 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400429 decode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700430#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400431 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700432 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400433 encode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700434#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400435 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700436 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400437 decode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700438#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400439 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700440 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400441 encode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700442#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400443 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700444 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400445 decode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700446#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400447 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700448 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400449 encode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400450 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400452 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700453 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400454 decode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400455 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400457 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 encode_putfh_maxsz + \
Trond Myklebust85827152012-04-29 10:44:42 -0400459 encode_commit_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700460#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400461 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700462 decode_putfh_maxsz + \
Trond Myklebust85827152012-04-29 10:44:42 -0400463 decode_commit_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400465 encode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400466 encode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400467 encode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400468 encode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400469 encode_getfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400470 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700471#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400472 decode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400473 decode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400474 decode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400475 decode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400476 decode_getfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400477 decode_getattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400478#define NFS4_enc_open_confirm_sz \
479 (compound_encode_hdr_maxsz + \
480 encode_putfh_maxsz + \
481 encode_open_confirm_maxsz)
482#define NFS4_dec_open_confirm_sz \
483 (compound_decode_hdr_maxsz + \
484 decode_putfh_maxsz + \
485 decode_open_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700486#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400487 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 encode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400489 encode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400490 encode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400491 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400493 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 decode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400495 decode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400496 decode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400497 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498#define NFS4_enc_open_downgrade_sz \
499 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400500 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400501 encode_putfh_maxsz + \
Trond Myklebust3947b742016-10-27 18:27:02 -0400502 encode_open_downgrade_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700503#define NFS4_dec_open_downgrade_sz \
504 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400505 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400506 decode_putfh_maxsz + \
Trond Myklebust3947b742016-10-27 18:27:02 -0400507 decode_open_downgrade_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400508#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400509 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400510 encode_putfh_maxsz + \
511 encode_close_maxsz + \
512 encode_getattr_maxsz)
513#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400514 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400515 decode_putfh_maxsz + \
516 decode_close_maxsz + \
517 decode_getattr_maxsz)
518#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400519 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400520 encode_putfh_maxsz + \
521 encode_setattr_maxsz + \
522 encode_getattr_maxsz)
523#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400524 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400525 decode_putfh_maxsz + \
526 decode_setattr_maxsz + \
527 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700528#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400529 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700530 encode_putfh_maxsz + \
531 encode_fsinfo_maxsz)
532#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400533 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700534 decode_putfh_maxsz + \
535 decode_fsinfo_maxsz)
536#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
537 encode_renew_maxsz)
538#define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \
539 decode_renew_maxsz)
540#define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \
541 encode_setclientid_maxsz)
542#define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \
543 decode_setclientid_maxsz)
544#define NFS4_enc_setclientid_confirm_sz \
545 (compound_encode_hdr_maxsz + \
Chuck Lever83ca7f52013-03-16 15:55:53 -0400546 encode_setclientid_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700547#define NFS4_dec_setclientid_confirm_sz \
548 (compound_decode_hdr_maxsz + \
Chuck Lever83ca7f52013-03-16 15:55:53 -0400549 decode_setclientid_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700550#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400551 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400553 encode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400555 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700556 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400557 decode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400559 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400561 encode_lockt_maxsz)
562#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400563 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400564 decode_putfh_maxsz + \
565 decode_lockt_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400567 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700568 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400569 encode_locku_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700570#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400571 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400573 decode_locku_maxsz)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -0400574#define NFS4_enc_release_lockowner_sz \
575 (compound_encode_hdr_maxsz + \
576 encode_lockowner_maxsz)
577#define NFS4_dec_release_lockowner_sz \
578 (compound_decode_hdr_maxsz + \
579 decode_lockowner_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700580#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400581 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700582 encode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400583 encode_access_maxsz + \
584 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400586 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 decode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400588 decode_access_maxsz + \
589 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400591 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 encode_putfh_maxsz + \
Chuck Lever44c99932013-10-17 14:13:30 -0400593 encode_getattr_maxsz + \
594 encode_renew_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400596 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 decode_putfh_maxsz + \
Chuck Lever44c99932013-10-17 14:13:30 -0400598 decode_getattr_maxsz + \
599 decode_renew_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400601 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 encode_putfh_maxsz + \
603 encode_lookup_maxsz + \
604 encode_getattr_maxsz + \
605 encode_getfh_maxsz)
606#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400607 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700608 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400609 decode_lookup_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700610 decode_getattr_maxsz + \
611 decode_getfh_maxsz)
612#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400613 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 encode_putrootfh_maxsz + \
615 encode_getattr_maxsz + \
616 encode_getfh_maxsz)
617#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400618 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 decode_putrootfh_maxsz + \
620 decode_getattr_maxsz + \
621 decode_getfh_maxsz)
622#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400623 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 encode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400625 encode_remove_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700626#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400627 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700628 decode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400629 decode_remove_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700630#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400631 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700632 encode_putfh_maxsz + \
633 encode_savefh_maxsz + \
634 encode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400635 encode_rename_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700636#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400637 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700638 decode_putfh_maxsz + \
639 decode_savefh_maxsz + \
640 decode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400641 decode_rename_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700642#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400643 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700644 encode_putfh_maxsz + \
645 encode_savefh_maxsz + \
646 encode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400647 encode_link_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400648 encode_restorefh_maxsz + \
Trond Myklebusta9f69912012-04-27 13:48:17 -0400649 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700650#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400651 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700652 decode_putfh_maxsz + \
653 decode_savefh_maxsz + \
654 decode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400655 decode_link_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400656 decode_restorefh_maxsz + \
657 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700658#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400659 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700660 encode_putfh_maxsz + \
661 encode_symlink_maxsz + \
662 encode_getattr_maxsz + \
663 encode_getfh_maxsz)
664#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400665 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700666 decode_putfh_maxsz + \
667 decode_symlink_maxsz + \
668 decode_getattr_maxsz + \
669 decode_getfh_maxsz)
670#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400671 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700672 encode_putfh_maxsz + \
673 encode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400674 encode_getfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400675 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700676#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400677 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700678 decode_putfh_maxsz + \
679 decode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400680 decode_getfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400681 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700682#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400683 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700684 encode_putfh_maxsz + \
685 encode_getattr_maxsz)
686#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400687 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700688 decode_putfh_maxsz + \
689 decode_getattr_maxsz)
690#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400691 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700692 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400693 encode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400695 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700696 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400697 decode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700698#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400699 encode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800700 encode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 encode_getattr_maxsz)
702#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400703 decode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800704 decode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700705 decode_getattr_maxsz)
706#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400707 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700708 encode_putfh_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100709 encode_delegreturn_maxsz + \
710 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400712 decode_sequence_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100713 decode_delegreturn_maxsz + \
714 decode_getattr_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000715#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400716 encode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000717 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400718 encode_getacl_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000719#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400720 decode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000721 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400722 decode_getacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000723#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400724 encode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000725 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400726 encode_setacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000727#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400728 decode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000729 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400730 decode_setacl_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400731#define NFS4_enc_fs_locations_sz \
732 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400733 encode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400734 encode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400735 encode_lookup_maxsz + \
Chuck Leverb03d7352013-10-17 14:12:50 -0400736 encode_fs_locations_maxsz + \
737 encode_renew_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400738#define NFS4_dec_fs_locations_sz \
739 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400740 decode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400741 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400742 decode_lookup_maxsz + \
Chuck Leverb03d7352013-10-17 14:12:50 -0400743 decode_fs_locations_maxsz + \
744 decode_renew_maxsz)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +0000745#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \
746 encode_sequence_maxsz + \
747 encode_putfh_maxsz + \
748 encode_secinfo_maxsz)
749#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \
750 decode_sequence_maxsz + \
751 decode_putfh_maxsz + \
752 decode_secinfo_maxsz)
Chuck Lever44c99932013-10-17 14:13:30 -0400753#define NFS4_enc_fsid_present_sz \
754 (compound_encode_hdr_maxsz + \
755 encode_sequence_maxsz + \
756 encode_putfh_maxsz + \
757 encode_getfh_maxsz + \
758 encode_renew_maxsz)
759#define NFS4_dec_fsid_present_sz \
760 (compound_decode_hdr_maxsz + \
761 decode_sequence_maxsz + \
762 decode_putfh_maxsz + \
763 decode_getfh_maxsz + \
764 decode_renew_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400765#if defined(CONFIG_NFS_V4_1)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -0400766#define NFS4_enc_bind_conn_to_session_sz \
767 (compound_encode_hdr_maxsz + \
768 encode_bind_conn_to_session_maxsz)
769#define NFS4_dec_bind_conn_to_session_sz \
770 (compound_decode_hdr_maxsz + \
771 decode_bind_conn_to_session_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400772#define NFS4_enc_exchange_id_sz \
773 (compound_encode_hdr_maxsz + \
774 encode_exchange_id_maxsz)
775#define NFS4_dec_exchange_id_sz \
776 (compound_decode_hdr_maxsz + \
777 decode_exchange_id_maxsz)
Andy Adamsonfc931582009-04-01 09:22:31 -0400778#define NFS4_enc_create_session_sz \
779 (compound_encode_hdr_maxsz + \
780 encode_create_session_maxsz)
781#define NFS4_dec_create_session_sz \
782 (compound_decode_hdr_maxsz + \
783 decode_create_session_maxsz)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400784#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
785 encode_destroy_session_maxsz)
786#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
787 decode_destroy_session_maxsz)
Trond Myklebust66245532012-05-25 17:18:09 -0400788#define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \
789 encode_destroy_clientid_maxsz)
790#define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \
791 decode_destroy_clientid_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400792#define NFS4_enc_sequence_sz \
793 (compound_decode_hdr_maxsz + \
794 encode_sequence_maxsz)
795#define NFS4_dec_sequence_sz \
796 (compound_decode_hdr_maxsz + \
797 decode_sequence_maxsz)
Andy Adamson2050f0c2009-04-01 09:22:30 -0400798#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
799 encode_sequence_maxsz + \
800 encode_putrootfh_maxsz + \
801 encode_fsinfo_maxsz)
802#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
803 decode_sequence_maxsz + \
804 decode_putrootfh_maxsz + \
805 decode_fsinfo_maxsz)
Ricardo Labiaga180197532009-12-05 16:08:40 -0500806#define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \
807 encode_sequence_maxsz + \
808 encode_reclaim_complete_maxsz)
809#define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \
810 decode_sequence_maxsz + \
811 decode_reclaim_complete_maxsz)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400812#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \
813 encode_sequence_maxsz +\
814 encode_getdeviceinfo_maxsz)
815#define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \
816 decode_sequence_maxsz + \
817 decode_getdeviceinfo_maxsz)
818#define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \
819 encode_sequence_maxsz + \
820 encode_putfh_maxsz + \
821 encode_layoutget_maxsz)
822#define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \
823 decode_sequence_maxsz + \
824 decode_putfh_maxsz + \
825 decode_layoutget_maxsz)
Andy Adamson863a3c62011-03-23 13:27:54 +0000826#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \
827 encode_sequence_maxsz +\
828 encode_putfh_maxsz + \
829 encode_layoutcommit_maxsz + \
830 encode_getattr_maxsz)
831#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \
832 decode_sequence_maxsz + \
833 decode_putfh_maxsz + \
834 decode_layoutcommit_maxsz + \
835 decode_getattr_maxsz)
Benny Halevycbe82602011-05-22 19:52:37 +0300836#define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \
837 encode_sequence_maxsz + \
838 encode_putfh_maxsz + \
839 encode_layoutreturn_maxsz)
840#define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \
841 decode_sequence_maxsz + \
842 decode_putfh_maxsz + \
843 decode_layoutreturn_maxsz)
Bryan Schumakerfca78d62011-06-02 14:59:07 -0400844#define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \
845 encode_sequence_maxsz + \
846 encode_putrootfh_maxsz +\
847 encode_secinfo_no_name_maxsz)
848#define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \
849 decode_sequence_maxsz + \
850 decode_putrootfh_maxsz + \
851 decode_secinfo_no_name_maxsz)
Bryan Schumaker7d974792011-06-02 14:59:08 -0400852#define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \
853 encode_sequence_maxsz + \
854 encode_test_stateid_maxsz)
855#define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \
856 decode_sequence_maxsz + \
857 decode_test_stateid_maxsz)
Bryan Schumaker9aeda352011-06-02 14:59:09 -0400858#define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \
859 encode_sequence_maxsz + \
860 encode_free_stateid_maxsz)
861#define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \
862 decode_sequence_maxsz + \
863 decode_free_stateid_maxsz)
Alexandros Batsakis2449ea22009-12-05 13:36:55 -0500864
865const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
866 compound_encode_hdr_maxsz +
867 encode_sequence_maxsz +
868 encode_putfh_maxsz +
869 encode_getattr_maxsz) *
870 XDR_UNIT);
871
872const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
873 compound_decode_hdr_maxsz +
874 decode_sequence_maxsz +
875 decode_putfh_maxsz) *
876 XDR_UNIT);
Andy Adamsonf1c097b2013-06-25 19:02:53 -0400877
878const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH +
879 compound_decode_hdr_maxsz +
880 decode_sequence_maxsz) *
881 XDR_UNIT);
882EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead);
Benny Halevy99fe60d2009-04-01 09:22:29 -0400883#endif /* CONFIG_NFS_V4_1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700884
Trond Myklebustbca79472009-03-11 14:10:26 -0400885static const umode_t nfs_type2fmt[] = {
886 [NF4BAD] = 0,
887 [NF4REG] = S_IFREG,
888 [NF4DIR] = S_IFDIR,
889 [NF4BLK] = S_IFBLK,
890 [NF4CHR] = S_IFCHR,
891 [NF4LNK] = S_IFLNK,
892 [NF4SOCK] = S_IFSOCK,
893 [NF4FIFO] = S_IFIFO,
894 [NF4ATTRDIR] = 0,
895 [NF4NAMEDATTR] = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896};
897
898struct compound_hdr {
899 int32_t status;
900 uint32_t nops;
Andy Adamsond0179312008-12-23 16:06:17 -0500901 __be32 * nops_p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700902 uint32_t taglen;
903 char * tag;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400904 uint32_t replen; /* expected reply words */
Benny Halevy66cc0422009-04-01 09:22:10 -0400905 u32 minorversion;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906};
907
Benny Halevy13c65ce2009-08-14 17:19:25 +0300908static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
909{
910 __be32 *p = xdr_reserve_space(xdr, nbytes);
911 BUG_ON(!p);
912 return p;
913}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914
Trond Myklebustcb17e552012-03-04 18:13:56 -0500915static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
916{
917 __be32 *p;
918
919 p = xdr_reserve_space(xdr, len);
920 xdr_encode_opaque_fixed(p, buf, len);
921}
922
Linus Torvalds1da177e2005-04-16 15:20:36 -0700923static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
924{
Al Viro8687b632006-10-19 23:28:48 -0700925 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700926
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -0500927 p = reserve_space(xdr, 4 + len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700928 xdr_encode_opaque(p, str, len);
929}
930
Trond Myklebust4ade9822012-03-04 18:13:57 -0500931static void encode_uint32(struct xdr_stream *xdr, u32 n)
932{
933 __be32 *p;
934
935 p = reserve_space(xdr, 4);
936 *p = cpu_to_be32(n);
937}
938
Trond Myklebustff2eb682012-03-05 11:40:12 -0500939static void encode_uint64(struct xdr_stream *xdr, u64 n)
940{
941 __be32 *p;
942
943 p = reserve_space(xdr, 8);
944 xdr_encode_hyper(p, n);
945}
946
Trond Myklebust4ade9822012-03-04 18:13:57 -0500947static void encode_nfs4_seqid(struct xdr_stream *xdr,
948 const struct nfs_seqid *seqid)
949{
Trond Myklebusta6796412015-01-23 19:04:44 -0500950 if (seqid != NULL)
951 encode_uint32(xdr, seqid->sequence->counter);
952 else
953 encode_uint32(xdr, 0);
Trond Myklebust4ade9822012-03-04 18:13:57 -0500954}
955
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400956static void encode_compound_hdr(struct xdr_stream *xdr,
957 struct rpc_rqst *req,
958 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700959{
Al Viro8687b632006-10-19 23:28:48 -0700960 __be32 *p;
Trond Myklebusta17c2152010-07-31 14:29:08 -0400961 struct rpc_auth *auth = req->rq_cred->cr_auth;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400962
963 /* initialize running count of expected bytes in reply.
964 * NOTE: the replied tag SHOULD be the same is the one sent,
965 * but this is not required as a MUST for the server to do so. */
966 hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967
Trond Myklebust7fc38842012-10-15 11:51:21 -0400968 WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -0500969 encode_string(xdr, hdr->taglen, hdr->tag);
970 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300971 *p++ = cpu_to_be32(hdr->minorversion);
Andy Adamsond0179312008-12-23 16:06:17 -0500972 hdr->nops_p = p;
Benny Halevy34558512009-08-14 17:19:30 +0300973 *p = cpu_to_be32(hdr->nops);
Andy Adamsond0179312008-12-23 16:06:17 -0500974}
975
Trond Myklebustab19b482012-03-04 18:13:57 -0500976static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op,
977 uint32_t replen,
978 struct compound_hdr *hdr)
979{
980 encode_uint32(xdr, op);
981 hdr->nops++;
982 hdr->replen += replen;
983}
984
Andy Adamsond0179312008-12-23 16:06:17 -0500985static void encode_nops(struct compound_hdr *hdr)
986{
Trond Myklebust7fc38842012-10-15 11:51:21 -0400987 WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
Andy Adamsond0179312008-12-23 16:06:17 -0500988 *hdr->nops_p = htonl(hdr->nops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700989}
990
Trond Myklebustea9d23f2012-03-04 18:13:56 -0500991static void encode_nfs4_stateid(struct xdr_stream *xdr, const nfs4_stateid *stateid)
992{
Trond Myklebust2d2f24a2012-03-04 18:13:57 -0500993 encode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
Trond Myklebustea9d23f2012-03-04 18:13:56 -0500994}
995
Linus Torvalds1da177e2005-04-16 15:20:36 -0700996static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
997{
Trond Myklebustcb17e552012-03-04 18:13:56 -0500998 encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700999}
1000
David Quigleyaa9c2662013-05-22 12:50:44 -04001001static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1002 const struct nfs4_label *label,
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001003 const struct nfs_server *server,
1004 bool excl_check)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005{
1006 char owner_name[IDMAP_NAMESZ];
1007 char owner_group[IDMAP_NAMESZ];
1008 int owner_namelen = 0;
1009 int owner_grouplen = 0;
Al Viro8687b632006-10-19 23:28:48 -07001010 __be32 *p;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001011 unsigned i;
1012 uint32_t len = 0;
1013 uint32_t bmval_len;
1014 uint32_t bmval[3] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001015
1016 /*
1017 * We reserve enough space to write the entire attribute buffer at once.
1018 * In the worst-case, this would be
David Quigleya09df2c2013-05-22 12:50:41 -04001019 * 16(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
1020 * = 40 bytes, plus any contribution from variable-length fields
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001021 * such as owner/group.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001022 */
Trond Myklebustd7067b22013-07-17 17:09:01 -04001023 if (iap->ia_valid & ATTR_SIZE) {
1024 bmval[0] |= FATTR4_WORD0_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001025 len += 8;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001026 }
1027 if (iap->ia_valid & ATTR_MODE) {
1028 bmval[1] |= FATTR4_WORD1_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 len += 4;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001030 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001031 if (iap->ia_valid & ATTR_UID) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08001032 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001033 if (owner_namelen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04001034 dprintk("nfs: couldn't resolve uid %d to string\n",
Eric W. Biedermane5782072013-02-01 14:22:02 -08001035 from_kuid(&init_user_ns, iap->ia_uid));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001036 /* XXX */
1037 strcpy(owner_name, "nobody");
1038 owner_namelen = sizeof("nobody") - 1;
1039 /* goto out; */
1040 }
Trond Myklebustd7067b22013-07-17 17:09:01 -04001041 bmval[1] |= FATTR4_WORD1_OWNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
1043 }
1044 if (iap->ia_valid & ATTR_GID) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08001045 owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001046 if (owner_grouplen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04001047 dprintk("nfs: couldn't resolve gid %d to string\n",
Eric W. Biedermane5782072013-02-01 14:22:02 -08001048 from_kgid(&init_user_ns, iap->ia_gid));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001049 strcpy(owner_group, "nobody");
1050 owner_grouplen = sizeof("nobody") - 1;
1051 /* goto out; */
1052 }
Trond Myklebustd7067b22013-07-17 17:09:01 -04001053 bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
1055 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001056 if (iap->ia_valid & ATTR_ATIME_SET) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001057 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1058 len += 16;
1059 } else if (iap->ia_valid & ATTR_ATIME) {
1060 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1061 len += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062 }
1063 if (iap->ia_valid & ATTR_MTIME_SET) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001064 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1065 len += 16;
1066 } else if (iap->ia_valid & ATTR_MTIME) {
1067 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1068 len += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001069 }
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001070
1071 if (excl_check) {
1072 const u32 *excl_bmval = server->exclcreat_bitmask;
1073 bmval[0] &= excl_bmval[0];
1074 bmval[1] &= excl_bmval[1];
1075 bmval[2] &= excl_bmval[2];
1076
1077 if (!(excl_bmval[2] & FATTR4_WORD2_SECURITY_LABEL))
1078 label = NULL;
1079 }
1080
David Quigleyaa9c2662013-05-22 12:50:44 -04001081 if (label) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001082 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
1083 bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
1084 }
1085
1086 if (bmval[2] != 0)
1087 bmval_len = 3;
1088 else if (bmval[1] != 0)
1089 bmval_len = 2;
1090 else
1091 bmval_len = 1;
1092
1093 p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len);
1094
1095 *p++ = cpu_to_be32(bmval_len);
1096 for (i = 0; i < bmval_len; i++)
1097 *p++ = cpu_to_be32(bmval[i]);
1098 *p++ = cpu_to_be32(len);
1099
1100 if (bmval[0] & FATTR4_WORD0_SIZE)
1101 p = xdr_encode_hyper(p, iap->ia_size);
1102 if (bmval[1] & FATTR4_WORD1_MODE)
1103 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1104 if (bmval[1] & FATTR4_WORD1_OWNER)
1105 p = xdr_encode_opaque(p, owner_name, owner_namelen);
1106 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP)
1107 p = xdr_encode_opaque(p, owner_group, owner_grouplen);
1108 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1109 if (iap->ia_valid & ATTR_ATIME_SET) {
1110 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1111 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
1112 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
1113 } else
1114 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1115 }
1116 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1117 if (iap->ia_valid & ATTR_MTIME_SET) {
1118 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1119 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
1120 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1121 } else
1122 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1123 }
1124 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
David Quigleyaa9c2662013-05-22 12:50:44 -04001125 *p++ = cpu_to_be32(label->lfs);
1126 *p++ = cpu_to_be32(label->pi);
1127 *p++ = cpu_to_be32(label->len);
1128 p = xdr_encode_opaque_fixed(p, label->label, label->len);
1129 }
Andy Adamson6c0195a2008-12-23 16:06:15 -05001130
Linus Torvalds1da177e2005-04-16 15:20:36 -07001131/* out: */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001132}
1133
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001134static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001136 encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr);
1137 encode_uint32(xdr, access);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001138}
1139
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001140static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001141{
Trond Myklebustab19b482012-03-04 18:13:57 -05001142 encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001143 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust566fcec2015-01-23 15:32:46 -05001144 encode_nfs4_stateid(xdr, &arg->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001145}
1146
Fred Isaman0b7c0152012-04-20 14:47:39 -04001147static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001148{
Al Viro8687b632006-10-19 23:28:48 -07001149 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001150
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001151 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
1152 p = reserve_space(xdr, 12);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001153 p = xdr_encode_hyper(p, args->offset);
Benny Halevy34558512009-08-14 17:19:30 +03001154 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001155}
1156
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001157static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158{
Al Viro8687b632006-10-19 23:28:48 -07001159 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001160
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001161 encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr);
1162 encode_uint32(xdr, create->ftype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163
1164 switch (create->ftype) {
1165 case NF4LNK:
Benny Halevy13c65ce2009-08-14 17:19:25 +03001166 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001167 *p = cpu_to_be32(create->u.symlink.len);
Chuck Lever2fcc2132015-08-03 13:04:26 -04001168 xdr_write_pages(xdr, create->u.symlink.pages, 0,
1169 create->u.symlink.len);
1170 xdr->buf->flags |= XDRBUF_WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001171 break;
1172
1173 case NF4BLK: case NF4CHR:
Benny Halevy13c65ce2009-08-14 17:19:25 +03001174 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001175 *p++ = cpu_to_be32(create->u.device.specdata1);
Benny Halevy34558512009-08-14 17:19:30 +03001176 *p = cpu_to_be32(create->u.device.specdata2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 break;
1178
1179 default:
1180 break;
1181 }
1182
Benny Halevy811652b2009-08-14 17:19:34 +03001183 encode_string(xdr, create->name->len, create->name->name);
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001184 encode_attrs(xdr, create->attrs, create->label, create->server, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185}
1186
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001187static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001188{
Andy Adamson05d564f2008-12-23 16:06:15 -05001189 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001190
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001191 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
1192 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001193 *p++ = cpu_to_be32(1);
Benny Halevy34558512009-08-14 17:19:30 +03001194 *p = cpu_to_be32(bitmap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001195}
1196
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001197static void encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001198{
Andy Adamson05d564f2008-12-23 16:06:15 -05001199 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001200
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001201 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
1202 p = reserve_space(xdr, 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001203 *p++ = cpu_to_be32(2);
1204 *p++ = cpu_to_be32(bm0);
Benny Halevy34558512009-08-14 17:19:30 +03001205 *p = cpu_to_be32(bm1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206}
1207
Fred Isamandae100c2011-07-30 20:52:37 -04001208static void
1209encode_getattr_three(struct xdr_stream *xdr,
1210 uint32_t bm0, uint32_t bm1, uint32_t bm2,
1211 struct compound_hdr *hdr)
1212{
1213 __be32 *p;
1214
Trond Myklebustab19b482012-03-04 18:13:57 -05001215 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
Fred Isamandae100c2011-07-30 20:52:37 -04001216 if (bm2) {
1217 p = reserve_space(xdr, 16);
1218 *p++ = cpu_to_be32(3);
1219 *p++ = cpu_to_be32(bm0);
1220 *p++ = cpu_to_be32(bm1);
1221 *p = cpu_to_be32(bm2);
1222 } else if (bm1) {
1223 p = reserve_space(xdr, 12);
1224 *p++ = cpu_to_be32(2);
1225 *p++ = cpu_to_be32(bm0);
1226 *p = cpu_to_be32(bm1);
1227 } else {
1228 p = reserve_space(xdr, 8);
1229 *p++ = cpu_to_be32(1);
1230 *p = cpu_to_be32(bm0);
1231 }
Fred Isamandae100c2011-07-30 20:52:37 -04001232}
1233
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001234static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001235{
David Quigleya09df2c2013-05-22 12:50:41 -04001236 encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
1237 bitmask[1] & nfs4_fattr_bitmap[1],
1238 bitmask[2] & nfs4_fattr_bitmap[2],
1239 hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001240}
1241
Andy Adamson88034c32012-05-23 05:02:34 -04001242static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
Trond Myklebust1549210f2012-06-05 09:16:47 -04001243 const u32 *open_bitmap,
Andy Adamson88034c32012-05-23 05:02:34 -04001244 struct compound_hdr *hdr)
1245{
1246 encode_getattr_three(xdr,
Trond Myklebust1549210f2012-06-05 09:16:47 -04001247 bitmask[0] & open_bitmap[0],
1248 bitmask[1] & open_bitmap[1],
1249 bitmask[2] & open_bitmap[2],
Andy Adamson88034c32012-05-23 05:02:34 -04001250 hdr);
1251}
1252
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001253static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001254{
Fred Isamandae100c2011-07-30 20:52:37 -04001255 encode_getattr_three(xdr,
1256 bitmask[0] & nfs4_fsinfo_bitmap[0],
1257 bitmask[1] & nfs4_fsinfo_bitmap[1],
1258 bitmask[2] & nfs4_fsinfo_bitmap[2],
1259 hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001260}
1261
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001262static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Manoj Naik830b8e32006-06-09 09:34:25 -04001263{
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001264 encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0],
1265 bitmask[1] & nfs4_fs_locations_bitmap[1], hdr);
Manoj Naik830b8e32006-06-09 09:34:25 -04001266}
1267
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001268static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001269{
Trond Myklebustab19b482012-03-04 18:13:57 -05001270 encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001271}
1272
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001273static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001274{
Trond Myklebustab19b482012-03-04 18:13:57 -05001275 encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001276 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001277}
1278
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001279static inline int nfs4_lock_type(struct file_lock *fl, int block)
1280{
Jeff Laytonf44106e2012-07-23 15:49:56 -04001281 if (fl->fl_type == F_RDLCK)
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001282 return block ? NFS4_READW_LT : NFS4_READ_LT;
1283 return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
1284}
1285
1286static inline uint64_t nfs4_lock_length(struct file_lock *fl)
1287{
1288 if (fl->fl_end == OFFSET_MAX)
1289 return ~(uint64_t)0;
1290 return fl->fl_end - fl->fl_start + 1;
1291}
1292
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001293static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
1294{
1295 __be32 *p;
1296
Trond Myklebustd035c362010-12-21 10:45:27 -05001297 p = reserve_space(xdr, 32);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001298 p = xdr_encode_hyper(p, lowner->clientid);
Trond Myklebustd035c362010-12-21 10:45:27 -05001299 *p++ = cpu_to_be32(20);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001300 p = xdr_encode_opaque_fixed(p, "lock id:", 8);
Trond Myklebustd035c362010-12-21 10:45:27 -05001301 *p++ = cpu_to_be32(lowner->s_dev);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001302 xdr_encode_hyper(p, lowner->id);
1303}
1304
Linus Torvalds1da177e2005-04-16 15:20:36 -07001305/*
1306 * opcode,type,reclaim,offset,length,new_lock_owner = 32
1307 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
1308 */
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001309static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001310{
Al Viro8687b632006-10-19 23:28:48 -07001311 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001313 encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr);
1314 p = reserve_space(xdr, 28);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001315 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
1316 *p++ = cpu_to_be32(args->reclaim);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001317 p = xdr_encode_hyper(p, args->fl->fl_start);
1318 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Benny Halevy34558512009-08-14 17:19:30 +03001319 *p = cpu_to_be32(args->new_lock_owner);
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001320 if (args->new_lock_owner){
Trond Myklebust4ade9822012-03-04 18:13:57 -05001321 encode_nfs4_seqid(xdr, args->open_seqid);
Trond Myklebust425c1d42015-01-24 14:57:53 -05001322 encode_nfs4_stateid(xdr, &args->open_stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001323 encode_nfs4_seqid(xdr, args->lock_seqid);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001324 encode_lockowner(xdr, &args->lock_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325 }
1326 else {
Trond Myklebust425c1d42015-01-24 14:57:53 -05001327 encode_nfs4_stateid(xdr, &args->lock_stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001328 encode_nfs4_seqid(xdr, args->lock_seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001329 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001330}
1331
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001332static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001333{
Al Viro8687b632006-10-19 23:28:48 -07001334 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001335
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001336 encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr);
1337 p = reserve_space(xdr, 20);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001338 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
Benny Halevyb95be5a2009-08-14 17:19:01 +03001339 p = xdr_encode_hyper(p, args->fl->fl_start);
1340 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001341 encode_lockowner(xdr, &args->lock_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001342}
1343
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001344static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345{
Al Viro8687b632006-10-19 23:28:48 -07001346 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001347
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001348 encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr);
1349 encode_uint32(xdr, nfs4_lock_type(args->fl, 0));
Trond Myklebust4ade9822012-03-04 18:13:57 -05001350 encode_nfs4_seqid(xdr, args->seqid);
Trond Myklebust425c1d42015-01-24 14:57:53 -05001351 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001352 p = reserve_space(xdr, 16);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001353 p = xdr_encode_hyper(p, args->fl->fl_start);
Benny Halevy34558512009-08-14 17:19:30 +03001354 xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001355}
1356
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001357static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
1358{
Trond Myklebustab19b482012-03-04 18:13:57 -05001359 encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001360 encode_lockowner(xdr, lowner);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001361}
1362
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001363static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001364{
Trond Myklebustab19b482012-03-04 18:13:57 -05001365 encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001366 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001367}
1368
Trond Myklebust6ae37332015-01-30 14:21:14 -05001369static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001370{
Al Viro8687b632006-10-19 23:28:48 -07001371 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001372
Benny Halevy13c65ce2009-08-14 17:19:25 +03001373 p = reserve_space(xdr, 8);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001374 *p++ = cpu_to_be32(share_access);
Benny Halevy34558512009-08-14 17:19:30 +03001375 *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001376}
1377
1378static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1379{
Al Viro8687b632006-10-19 23:28:48 -07001380 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001381 /*
1382 * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
1383 * owner 4 = 32
1384 */
Trond Myklebust4ade9822012-03-04 18:13:57 -05001385 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001386 encode_share_access(xdr, arg->share_access);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001387 p = reserve_space(xdr, 36);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001388 p = xdr_encode_hyper(p, arg->clientid);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001389 *p++ = cpu_to_be32(24);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001390 p = xdr_encode_opaque_fixed(p, "open id:", 8);
Trond Myklebustd035c362010-12-21 10:45:27 -05001391 *p++ = cpu_to_be32(arg->server->s_dev);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001392 *p++ = cpu_to_be32(arg->id.uniquifier);
1393 xdr_encode_hyper(p, arg->id.create_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394}
1395
1396static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1397{
Al Viro8687b632006-10-19 23:28:48 -07001398 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399
Benny Halevy13c65ce2009-08-14 17:19:25 +03001400 p = reserve_space(xdr, 4);
Trond Myklebust549b19c2013-04-16 18:42:34 -04001401 switch(arg->createmode) {
1402 case NFS4_CREATE_UNCHECKED:
Benny Halevy34558512009-08-14 17:19:30 +03001403 *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001404 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
Andy Adamson05d564f2008-12-23 16:06:15 -05001405 break;
Trond Myklebust549b19c2013-04-16 18:42:34 -04001406 case NFS4_CREATE_GUARDED:
1407 *p = cpu_to_be32(NFS4_CREATE_GUARDED);
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001408 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false);
Trond Myklebust549b19c2013-04-16 18:42:34 -04001409 break;
1410 case NFS4_CREATE_EXCLUSIVE:
1411 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
1412 encode_nfs4_verifier(xdr, &arg->u.verifier);
1413 break;
1414 case NFS4_CREATE_EXCLUSIVE4_1:
1415 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
1416 encode_nfs4_verifier(xdr, &arg->u.verifier);
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001417 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001418 }
1419}
1420
1421static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1422{
Al Viro8687b632006-10-19 23:28:48 -07001423 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001424
Benny Halevy13c65ce2009-08-14 17:19:25 +03001425 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001426 switch (arg->open_flags & O_CREAT) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001427 case 0:
Benny Halevy34558512009-08-14 17:19:30 +03001428 *p = cpu_to_be32(NFS4_OPEN_NOCREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001429 break;
1430 default:
Benny Halevy34558512009-08-14 17:19:30 +03001431 *p = cpu_to_be32(NFS4_OPEN_CREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001432 encode_createmode(xdr, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001433 }
1434}
1435
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001436static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437{
Al Viro8687b632006-10-19 23:28:48 -07001438 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001439
Benny Halevy13c65ce2009-08-14 17:19:25 +03001440 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001442 case 0:
Benny Halevy34558512009-08-14 17:19:30 +03001443 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001444 break;
1445 case FMODE_READ:
Benny Halevy34558512009-08-14 17:19:30 +03001446 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
Andy Adamson05d564f2008-12-23 16:06:15 -05001447 break;
1448 case FMODE_WRITE|FMODE_READ:
Benny Halevy34558512009-08-14 17:19:30 +03001449 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001450 break;
1451 default:
1452 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453 }
1454}
1455
1456static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
1457{
Al Viro8687b632006-10-19 23:28:48 -07001458 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001459
Benny Halevy13c65ce2009-08-14 17:19:25 +03001460 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001461 *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462 encode_string(xdr, name->len, name->name);
1463}
1464
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001465static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001466{
Al Viro8687b632006-10-19 23:28:48 -07001467 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001468
Benny Halevy13c65ce2009-08-14 17:19:25 +03001469 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001470 *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 encode_delegation_type(xdr, type);
1472}
1473
1474static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
1475{
Al Viro8687b632006-10-19 23:28:48 -07001476 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001477
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001478 p = reserve_space(xdr, 4);
1479 *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
1480 encode_nfs4_stateid(xdr, stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 encode_string(xdr, name->len, name->name);
1482}
1483
Trond Myklebustd9fc6612013-03-15 15:39:06 -04001484static inline void encode_claim_fh(struct xdr_stream *xdr)
1485{
1486 __be32 *p;
1487
1488 p = reserve_space(xdr, 4);
1489 *p = cpu_to_be32(NFS4_OPEN_CLAIM_FH);
1490}
1491
1492static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid)
1493{
1494 __be32 *p;
1495
1496 p = reserve_space(xdr, 4);
1497 *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH);
1498 encode_nfs4_stateid(xdr, stateid);
1499}
1500
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001501static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001502{
Trond Myklebustab19b482012-03-04 18:13:57 -05001503 encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001504 encode_openhdr(xdr, arg);
1505 encode_opentype(xdr, arg);
1506 switch (arg->claim) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001507 case NFS4_OPEN_CLAIM_NULL:
1508 encode_claim_null(xdr, arg->name);
1509 break;
1510 case NFS4_OPEN_CLAIM_PREVIOUS:
1511 encode_claim_previous(xdr, arg->u.delegation_type);
1512 break;
1513 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
1514 encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
1515 break;
Trond Myklebustd9fc6612013-03-15 15:39:06 -04001516 case NFS4_OPEN_CLAIM_FH:
1517 encode_claim_fh(xdr);
1518 break;
1519 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
1520 encode_claim_delegate_cur_fh(xdr, &arg->u.delegation);
1521 break;
Andy Adamson05d564f2008-12-23 16:06:15 -05001522 default:
1523 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001525}
1526
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001527static void encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001528{
Trond Myklebustab19b482012-03-04 18:13:57 -05001529 encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001530 encode_nfs4_stateid(xdr, arg->stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001531 encode_nfs4_seqid(xdr, arg->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001532}
1533
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001534static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001535{
Trond Myklebustab19b482012-03-04 18:13:57 -05001536 encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
Trond Myklebust566fcec2015-01-23 15:32:46 -05001537 encode_nfs4_stateid(xdr, &arg->stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001538 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001539 encode_share_access(xdr, arg->share_access);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001540}
1541
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001542static void
Andy Adamsond0179312008-12-23 16:06:17 -05001543encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544{
Trond Myklebustab19b482012-03-04 18:13:57 -05001545 encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001546 encode_string(xdr, fh->size, fh->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001547}
1548
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001549static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001550{
Trond Myklebustab19b482012-03-04 18:13:57 -05001551 encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552}
1553
Anna Schumaker3c6b8992014-05-06 09:12:24 -04001554static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
1555 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001556{
Al Viro8687b632006-10-19 23:28:48 -07001557 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001558
Trond Myklebustab19b482012-03-04 18:13:57 -05001559 encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
Trond Myklebust9b206142013-03-17 15:52:00 -04001560 encode_nfs4_stateid(xdr, &args->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001561
Benny Halevy13c65ce2009-08-14 17:19:25 +03001562 p = reserve_space(xdr, 12);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001563 p = xdr_encode_hyper(p, args->offset);
Benny Halevy34558512009-08-14 17:19:30 +03001564 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001565}
1566
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001567static void encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001568{
David Quigleyaa9c2662013-05-22 12:50:44 -04001569 uint32_t attrs[3] = {
Trond Myklebust28331a42011-04-27 13:47:52 -04001570 FATTR4_WORD0_RDATTR_ERROR,
1571 FATTR4_WORD1_MOUNTED_ON_FILEID,
1572 };
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001573 uint32_t dircount = readdir->count >> 1;
Chuck Levercd937102012-03-02 17:14:31 -05001574 __be32 *p, verf[2];
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001575 uint32_t attrlen = 0;
1576 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001578 if (readdir->plus) {
1579 attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
Trond Myklebust28331a42011-04-27 13:47:52 -04001580 FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001581 attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
1582 FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
1583 FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
1584 FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001585 attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001586 dircount >>= 1;
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001587 }
Trond Myklebust28331a42011-04-27 13:47:52 -04001588 /* Use mounted_on_fileid only if the server supports it */
1589 if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
1590 attrs[0] |= FATTR4_WORD0_FILEID;
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001591 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
1592 attrs[i] &= readdir->bitmask[i];
1593 if (attrs[i] != 0)
1594 attrlen = i+1;
1595 }
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001596
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001597 encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001598 encode_uint64(xdr, readdir->cookie);
Chuck Levercd937102012-03-02 17:14:31 -05001599 encode_nfs4_verifier(xdr, &readdir->verifier);
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001600 p = reserve_space(xdr, 12 + (attrlen << 2));
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001601 *p++ = cpu_to_be32(dircount);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001602 *p++ = cpu_to_be32(readdir->count);
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001603 *p++ = cpu_to_be32(attrlen);
1604 for (i = 0; i < attrlen; i++)
1605 *p++ = cpu_to_be32(attrs[i]);
Chuck Levercd937102012-03-02 17:14:31 -05001606 memcpy(verf, readdir->verifier.data, sizeof(verf));
David Quigleyaa9c2662013-05-22 12:50:44 -04001607
1608 dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n",
Fred Isaman44109242008-04-02 15:21:15 +03001609 __func__,
Trond Myklebusteadf4592005-06-22 17:16:39 +00001610 (unsigned long long)readdir->cookie,
Chuck Levercd937102012-03-02 17:14:31 -05001611 verf[0], verf[1],
Trond Myklebusteadf4592005-06-22 17:16:39 +00001612 attrs[0] & readdir->bitmask[0],
David Quigleyaa9c2662013-05-22 12:50:44 -04001613 attrs[1] & readdir->bitmask[1],
1614 attrs[2] & readdir->bitmask[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001615}
1616
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001617static void encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001618{
Trond Myklebustab19b482012-03-04 18:13:57 -05001619 encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001620}
1621
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001622static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001623{
Trond Myklebustab19b482012-03-04 18:13:57 -05001624 encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001625 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001626}
1627
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001628static void encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001629{
Trond Myklebustab19b482012-03-04 18:13:57 -05001630 encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr);
Benny Halevy811652b2009-08-14 17:19:34 +03001631 encode_string(xdr, oldname->len, oldname->name);
1632 encode_string(xdr, newname->len, newname->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001633}
1634
Chuck Leverbb4dae52012-03-01 17:01:48 -05001635static void encode_renew(struct xdr_stream *xdr, clientid4 clid,
1636 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001637{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001638 encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001639 encode_uint64(xdr, clid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001640}
1641
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001642static void
Andy Adamsond0179312008-12-23 16:06:17 -05001643encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001644{
Trond Myklebustab19b482012-03-04 18:13:57 -05001645 encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001646}
1647
Chuck Lever9f06c712010-12-14 14:59:18 +00001648static void
Andy Adamsond0179312008-12-23 16:06:17 -05001649encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001650{
Al Viro8687b632006-10-19 23:28:48 -07001651 __be32 *p;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001652
Trond Myklebustab19b482012-03-04 18:13:57 -05001653 encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001654 encode_nfs4_stateid(xdr, &zero_stateid);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001655 p = reserve_space(xdr, 2*4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001656 *p++ = cpu_to_be32(1);
Benny Halevy34558512009-08-14 17:19:30 +03001657 *p = cpu_to_be32(FATTR4_WORD0_ACL);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001658 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001659 *p = cpu_to_be32(arg->acl_len);
Andreas Gruenbacher8fbcf232015-11-03 18:25:34 +01001660 xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001661}
1662
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001663static void
Andy Adamsond0179312008-12-23 16:06:17 -05001664encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001665{
Trond Myklebustab19b482012-03-04 18:13:57 -05001666 encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001667}
1668
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001669static void encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001670{
Trond Myklebustab19b482012-03-04 18:13:57 -05001671 encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001672 encode_nfs4_stateid(xdr, &arg->stateid);
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001673 encode_attrs(xdr, arg->iap, arg->label, server, false);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001674}
1675
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001676static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677{
Al Viro8687b632006-10-19 23:28:48 -07001678 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001679
Trond Myklebust70019512012-03-04 20:49:32 -05001680 encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr);
Chuck Levercd937102012-03-02 17:14:31 -05001681 encode_nfs4_verifier(xdr, setclientid->sc_verifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001682
Jeff Layton3a6bb732015-06-09 19:43:57 -04001683 encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id),
1684 setclientid->sc_clnt->cl_owner_id);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001685 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001686 *p = cpu_to_be32(setclientid->sc_prog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001687 encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
1688 encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001689 p = reserve_space(xdr, 4);
Jeff Layton3a6bb732015-06-09 19:43:57 -04001690 *p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001691}
1692
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04001693static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_setclientid_res *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001694{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001695 encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM,
1696 decode_setclientid_confirm_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001697 encode_uint64(xdr, arg->clientid);
Chuck Levercd937102012-03-02 17:14:31 -05001698 encode_nfs4_verifier(xdr, &arg->confirm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001699}
1700
Anna Schumaker3c6b8992014-05-06 09:12:24 -04001701static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
1702 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001703{
Al Viro8687b632006-10-19 23:28:48 -07001704 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001705
Trond Myklebustab19b482012-03-04 18:13:57 -05001706 encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
Trond Myklebust9b206142013-03-17 15:52:00 -04001707 encode_nfs4_stateid(xdr, &args->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001708
Benny Halevy13c65ce2009-08-14 17:19:25 +03001709 p = reserve_space(xdr, 16);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001710 p = xdr_encode_hyper(p, args->offset);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001711 *p++ = cpu_to_be32(args->stable);
Benny Halevy34558512009-08-14 17:19:30 +03001712 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713
1714 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001715}
1716
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001717static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718{
Trond Myklebustab19b482012-03-04 18:13:57 -05001719 encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001720 encode_nfs4_stateid(xdr, stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001721}
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001722
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00001723static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
1724{
Trond Myklebustab19b482012-03-04 18:13:57 -05001725 encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001726 encode_string(xdr, name->len, name->name);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00001727}
1728
Benny Halevy99fe60d2009-04-01 09:22:29 -04001729#if defined(CONFIG_NFS_V4_1)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001730/* NFSv4.1 operations */
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001731static void encode_bind_conn_to_session(struct xdr_stream *xdr,
Trond Myklebust71a097c2015-02-18 09:27:18 -08001732 struct nfs41_bind_conn_to_session_args *args,
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001733 struct compound_hdr *hdr)
1734{
1735 __be32 *p;
1736
1737 encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
1738 decode_bind_conn_to_session_maxsz, hdr);
Trond Myklebust71a097c2015-02-18 09:27:18 -08001739 encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001740 p = xdr_reserve_space(xdr, 8);
Trond Myklebust71a097c2015-02-18 09:27:18 -08001741 *p++ = cpu_to_be32(args->dir);
1742 *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001743}
1744
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001745static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
1746{
1747 unsigned int i;
1748 encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS);
1749 for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++)
1750 encode_uint32(xdr, op_map->u.words[i]);
1751}
1752
Benny Halevy99fe60d2009-04-01 09:22:29 -04001753static void encode_exchange_id(struct xdr_stream *xdr,
1754 struct nfs41_exchange_id_args *args,
1755 struct compound_hdr *hdr)
1756{
1757 __be32 *p;
Jim Reesd751f742012-11-16 18:12:06 -05001758 char impl_name[IMPL_NAME_LIMIT];
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001759 int len = 0;
Benny Halevy99fe60d2009-04-01 09:22:29 -04001760
Trond Myklebust70019512012-03-04 20:49:32 -05001761 encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
Chuck Levercd937102012-03-02 17:14:31 -05001762 encode_nfs4_verifier(xdr, args->verifier);
Benny Halevy99fe60d2009-04-01 09:22:29 -04001763
Jeff Layton3a6bb732015-06-09 19:43:57 -04001764 encode_string(xdr, strlen(args->client->cl_owner_id),
1765 args->client->cl_owner_id);
Benny Halevy99fe60d2009-04-01 09:22:29 -04001766
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001767 encode_uint32(xdr, args->flags);
1768 encode_uint32(xdr, args->state_protect.how);
1769
1770 switch (args->state_protect.how) {
1771 case SP4_NONE:
1772 break;
1773 case SP4_MACH_CRED:
1774 encode_op_map(xdr, &args->state_protect.enforce);
1775 encode_op_map(xdr, &args->state_protect.allow);
1776 break;
1777 default:
1778 WARN_ON_ONCE(1);
1779 break;
1780 }
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001781
1782 if (send_implementation_id &&
1783 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
1784 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
Jim Reesd751f742012-11-16 18:12:06 -05001785 <= sizeof(impl_name) + 1)
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001786 len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
1787 utsname()->sysname, utsname()->release,
1788 utsname()->version, utsname()->machine);
1789
1790 if (len > 0) {
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001791 encode_uint32(xdr, 1); /* implementation id array length=1 */
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001792
1793 encode_string(xdr,
1794 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1,
1795 CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN);
1796 encode_string(xdr, len, impl_name);
1797 /* just send zeros for nii_date - the date is in nii_name */
1798 p = reserve_space(xdr, 12);
1799 p = xdr_encode_hyper(p, 0);
1800 *p = cpu_to_be32(0);
1801 } else
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001802 encode_uint32(xdr, 0); /* implementation id array length=0 */
Benny Halevy99fe60d2009-04-01 09:22:29 -04001803}
Andy Adamsonfc931582009-04-01 09:22:31 -04001804
1805static void encode_create_session(struct xdr_stream *xdr,
1806 struct nfs41_create_session_args *args,
1807 struct compound_hdr *hdr)
1808{
1809 __be32 *p;
Andy Adamsonfc931582009-04-01 09:22:31 -04001810 struct nfs_client *clp = args->client;
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001811 struct rpc_clnt *clnt = clp->cl_rpcclient;
Chuck Leverf0920752012-05-21 22:45:41 -04001812 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
Mike Sager8e0d46e2009-12-17 12:06:26 -05001813 u32 max_resp_sz_cached;
1814
1815 /*
1816 * Assumes OPEN is the biggest non-idempotent compound.
1817 * 2 is the verifier.
1818 */
1819 max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
1820 RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
Andy Adamsonfc931582009-04-01 09:22:31 -04001821
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001822 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001823 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
Trond Myklebust79969dd2015-02-18 11:30:18 -08001824 p = xdr_encode_hyper(p, args->clientid);
1825 *p++ = cpu_to_be32(args->seqid); /*Sequence id */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001826 *p++ = cpu_to_be32(args->flags); /*flags */
Andy Adamsonfc931582009-04-01 09:22:31 -04001827
Andy Adamsonfc931582009-04-01 09:22:31 -04001828 /* Fore Channel */
Benny Halevyc9c30dd2011-06-11 17:08:39 -04001829 *p++ = cpu_to_be32(0); /* header padding size */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001830 *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
1831 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
Mike Sager8e0d46e2009-12-17 12:06:26 -05001832 *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001833 *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */
1834 *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */
1835 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001836
1837 /* Back Channel */
Benny Halevyc9c30dd2011-06-11 17:08:39 -04001838 *p++ = cpu_to_be32(0); /* header padding size */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001839 *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
1840 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
1841 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1842 *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */
1843 *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */
1844 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001845
Benny Halevye75bc1c2009-08-14 17:18:54 +03001846 *p++ = cpu_to_be32(args->cb_program); /* cb_program */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001847 *p++ = cpu_to_be32(1);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001848 *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */
Andy Adamsonfc931582009-04-01 09:22:31 -04001849
1850 /* authsys_parms rfc1831 */
Deepa Dinamani2f86e092016-10-01 16:46:26 -07001851 *p++ = cpu_to_be32(ktime_to_ns(nn->boot_time)); /* stamp */
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001852 p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001853 *p++ = cpu_to_be32(0); /* UID */
1854 *p++ = cpu_to_be32(0); /* GID */
Benny Halevy34558512009-08-14 17:19:30 +03001855 *p = cpu_to_be32(0); /* No more gids */
Andy Adamsonfc931582009-04-01 09:22:31 -04001856}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001857
1858static void encode_destroy_session(struct xdr_stream *xdr,
1859 struct nfs4_session *session,
1860 struct compound_hdr *hdr)
1861{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001862 encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr);
1863 encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001864}
Ricardo Labiaga180197532009-12-05 16:08:40 -05001865
Trond Myklebust66245532012-05-25 17:18:09 -04001866static void encode_destroy_clientid(struct xdr_stream *xdr,
1867 uint64_t clientid,
1868 struct compound_hdr *hdr)
1869{
1870 encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr);
1871 encode_uint64(xdr, clientid);
1872}
1873
Ricardo Labiaga180197532009-12-05 16:08:40 -05001874static void encode_reclaim_complete(struct xdr_stream *xdr,
1875 struct nfs41_reclaim_complete_args *args,
1876 struct compound_hdr *hdr)
1877{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001878 encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr);
1879 encode_uint32(xdr, args->one_fs);
Ricardo Labiaga180197532009-12-05 16:08:40 -05001880}
Benny Halevy99fe60d2009-04-01 09:22:29 -04001881#endif /* CONFIG_NFS_V4_1 */
1882
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001883static void encode_sequence(struct xdr_stream *xdr,
1884 const struct nfs4_sequence_args *args,
1885 struct compound_hdr *hdr)
1886{
1887#if defined(CONFIG_NFS_V4_1)
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001888 struct nfs4_session *session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001889 struct nfs4_slot_table *tp;
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001890 struct nfs4_slot *slot = args->sa_slot;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001891 __be32 *p;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001892
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001893 tp = slot->table;
1894 session = tp->session;
Chuck Lever3bd23842013-08-09 12:49:19 -04001895 if (!session)
1896 return;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001897
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001898 encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001899
1900 /*
1901 * Sessionid + seqid + slotid + max slotid + cache_this
1902 */
1903 dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1904 "max_slotid=%d cache_this=%d\n",
1905 __func__,
1906 ((u32 *)session->sess_id.data)[0],
1907 ((u32 *)session->sess_id.data)[1],
1908 ((u32 *)session->sess_id.data)[2],
1909 ((u32 *)session->sess_id.data)[3],
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001910 slot->seq_nr, slot->slot_nr,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001911 tp->highest_used_slotid, args->sa_cache_this);
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001912 p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001913 p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001914 *p++ = cpu_to_be32(slot->seq_nr);
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001915 *p++ = cpu_to_be32(slot->slot_nr);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001916 *p++ = cpu_to_be32(tp->highest_used_slotid);
Benny Halevy34558512009-08-14 17:19:30 +03001917 *p = cpu_to_be32(args->sa_cache_this);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001918#endif /* CONFIG_NFS_V4_1 */
1919}
1920
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001921#ifdef CONFIG_NFS_V4_1
1922static void
1923encode_getdeviceinfo(struct xdr_stream *xdr,
1924 const struct nfs4_getdeviceinfo_args *args,
1925 struct compound_hdr *hdr)
1926{
1927 __be32 *p;
1928
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001929 encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr);
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07001930 p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001931 p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
1932 NFS4_DEVICEID4_SIZE);
1933 *p++ = cpu_to_be32(args->pdev->layout_type);
Andy Adamsonf1c097b2013-06-25 19:02:53 -04001934 *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07001935
1936 p = reserve_space(xdr, 4 + 4);
1937 *p++ = cpu_to_be32(1); /* bitmap length */
Trond Myklebust4e590802015-03-09 14:01:25 -04001938 *p++ = cpu_to_be32(args->notify_types);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001939}
1940
1941static void
1942encode_layoutget(struct xdr_stream *xdr,
1943 const struct nfs4_layoutget_args *args,
1944 struct compound_hdr *hdr)
1945{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001946 __be32 *p;
1947
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001948 encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr);
1949 p = reserve_space(xdr, 36);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001950 *p++ = cpu_to_be32(0); /* Signal layout available */
1951 *p++ = cpu_to_be32(args->type);
1952 *p++ = cpu_to_be32(args->range.iomode);
1953 p = xdr_encode_hyper(p, args->range.offset);
1954 p = xdr_encode_hyper(p, args->range.length);
1955 p = xdr_encode_hyper(p, args->minlength);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001956 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001957 encode_uint32(xdr, args->maxcount);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001958
1959 dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
1960 __func__,
1961 args->type,
1962 args->range.iomode,
1963 (unsigned long)args->range.offset,
1964 (unsigned long)args->range.length,
1965 args->maxcount);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001966}
Andy Adamson863a3c62011-03-23 13:27:54 +00001967
1968static int
1969encode_layoutcommit(struct xdr_stream *xdr,
Benny Halevyac7db722011-05-22 19:53:48 +03001970 struct inode *inode,
Christoph Hellwig5f919c92014-08-21 11:09:25 -05001971 struct nfs4_layoutcommit_args *args,
Andy Adamson863a3c62011-03-23 13:27:54 +00001972 struct compound_hdr *hdr)
1973{
1974 __be32 *p;
1975
1976 dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,
1977 NFS_SERVER(args->inode)->pnfs_curr_ld->id);
1978
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001979 encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr);
1980 p = reserve_space(xdr, 20);
Andy Adamson863a3c62011-03-23 13:27:54 +00001981 /* Only whole file layouts */
1982 p = xdr_encode_hyper(p, 0); /* offset */
Peng Tao3557c6c2011-07-30 20:52:34 -04001983 p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001984 *p = cpu_to_be32(0); /* reclaim */
1985 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebust2e18d4d2016-06-26 18:54:58 -04001986 if (args->lastbytewritten != U64_MAX) {
1987 p = reserve_space(xdr, 20);
1988 *p++ = cpu_to_be32(1); /* newoffset = TRUE */
1989 p = xdr_encode_hyper(p, args->lastbytewritten);
1990 } else {
1991 p = reserve_space(xdr, 12);
1992 *p++ = cpu_to_be32(0); /* newoffset = FALSE */
1993 }
Andy Adamson863a3c62011-03-23 13:27:54 +00001994 *p++ = cpu_to_be32(0); /* Never send time_modify_changed */
1995 *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
Benny Halevyac7db722011-05-22 19:53:48 +03001996
Christoph Hellwig5f919c92014-08-21 11:09:25 -05001997 if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) {
Benny Halevyac7db722011-05-22 19:53:48 +03001998 NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit(
1999 NFS_I(inode)->layout, xdr, args);
Christoph Hellwig5f919c92014-08-21 11:09:25 -05002000 } else {
2001 encode_uint32(xdr, args->layoutupdate_len);
2002 if (args->layoutupdate_pages) {
2003 xdr_write_pages(xdr, args->layoutupdate_pages, 0,
2004 args->layoutupdate_len);
2005 }
2006 }
Andy Adamson863a3c62011-03-23 13:27:54 +00002007
Andy Adamson863a3c62011-03-23 13:27:54 +00002008 return 0;
2009}
Benny Halevycbe82602011-05-22 19:52:37 +03002010
2011static void
2012encode_layoutreturn(struct xdr_stream *xdr,
2013 const struct nfs4_layoutreturn_args *args,
2014 struct compound_hdr *hdr)
2015{
2016 __be32 *p;
2017
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002018 encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr);
2019 p = reserve_space(xdr, 16);
Benny Halevycbe82602011-05-22 19:52:37 +03002020 *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */
2021 *p++ = cpu_to_be32(args->layout_type);
Peng Tao15eb67c2014-11-17 09:30:36 +08002022 *p++ = cpu_to_be32(args->range.iomode);
Benny Halevycbe82602011-05-22 19:52:37 +03002023 *p = cpu_to_be32(RETURN_FILE);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002024 p = reserve_space(xdr, 16);
Peng Tao15eb67c2014-11-17 09:30:36 +08002025 p = xdr_encode_hyper(p, args->range.offset);
2026 p = xdr_encode_hyper(p, args->range.length);
Benny Halevycbe82602011-05-22 19:52:37 +03002027 spin_lock(&args->inode->i_lock);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002028 encode_nfs4_stateid(xdr, &args->stateid);
Benny Halevycbe82602011-05-22 19:52:37 +03002029 spin_unlock(&args->inode->i_lock);
Andy Adamson04a55542011-05-22 19:53:10 +03002030 if (NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn) {
2031 NFS_SERVER(args->inode)->pnfs_curr_ld->encode_layoutreturn(
2032 NFS_I(args->inode)->layout, xdr, args);
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002033 } else
2034 encode_uint32(xdr, 0);
Benny Halevycbe82602011-05-22 19:52:37 +03002035}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002036
2037static int
2038encode_secinfo_no_name(struct xdr_stream *xdr,
2039 const struct nfs41_secinfo_no_name_args *args,
2040 struct compound_hdr *hdr)
2041{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002042 encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr);
2043 encode_uint32(xdr, args->style);
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002044 return 0;
2045}
Bryan Schumaker7d974792011-06-02 14:59:08 -04002046
2047static void encode_test_stateid(struct xdr_stream *xdr,
2048 struct nfs41_test_stateid_args *args,
2049 struct compound_hdr *hdr)
2050{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002051 encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr);
2052 encode_uint32(xdr, 1);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002053 encode_nfs4_stateid(xdr, args->stateid);
Bryan Schumaker7d974792011-06-02 14:59:08 -04002054}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04002055
2056static void encode_free_stateid(struct xdr_stream *xdr,
2057 struct nfs41_free_stateid_args *args,
2058 struct compound_hdr *hdr)
2059{
Trond Myklebustab19b482012-03-04 18:13:57 -05002060 encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr);
Trond Myklebust7c1d5fa2013-05-03 14:40:01 -04002061 encode_nfs4_stateid(xdr, &args->stateid);
Bryan Schumaker9aeda352011-06-02 14:59:09 -04002062}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002063#endif /* CONFIG_NFS_V4_1 */
2064
Linus Torvalds1da177e2005-04-16 15:20:36 -07002065/*
2066 * END OF "GENERIC" ENCODE ROUTINES.
2067 */
2068
Benny Halevy66cc0422009-04-01 09:22:10 -04002069static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
2070{
2071#if defined(CONFIG_NFS_V4_1)
Chuck Lever3bd23842013-08-09 12:49:19 -04002072 struct nfs4_session *session = args->sa_slot->table->session;
2073 if (session)
2074 return session->clp->cl_mvops->minor_version;
Benny Halevy66cc0422009-04-01 09:22:10 -04002075#endif /* CONFIG_NFS_V4_1 */
2076 return 0;
2077}
2078
Linus Torvalds1da177e2005-04-16 15:20:36 -07002079/*
2080 * Encode an ACCESS request
2081 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002082static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr,
2083 const struct nfs4_accessargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002084{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002085 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002086 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002087 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002088
Chuck Lever9f06c712010-12-14 14:59:18 +00002089 encode_compound_hdr(xdr, req, &hdr);
2090 encode_sequence(xdr, &args->seq_args, &hdr);
2091 encode_putfh(xdr, args->fh, &hdr);
2092 encode_access(xdr, args->access, &hdr);
2093 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002094 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095}
2096
2097/*
2098 * Encode LOOKUP request
2099 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002100static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
2101 const struct nfs4_lookup_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002102{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002103 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002104 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002105 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002106
Chuck Lever9f06c712010-12-14 14:59:18 +00002107 encode_compound_hdr(xdr, req, &hdr);
2108 encode_sequence(xdr, &args->seq_args, &hdr);
2109 encode_putfh(xdr, args->dir_fh, &hdr);
2110 encode_lookup(xdr, args->name, &hdr);
2111 encode_getfh(xdr, &hdr);
2112 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002113 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002114}
2115
2116/*
2117 * Encode LOOKUP_ROOT request
2118 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002119static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req,
2120 struct xdr_stream *xdr,
2121 const struct nfs4_lookup_root_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002122{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002124 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002125 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002126
Chuck Lever9f06c712010-12-14 14:59:18 +00002127 encode_compound_hdr(xdr, req, &hdr);
2128 encode_sequence(xdr, &args->seq_args, &hdr);
2129 encode_putrootfh(xdr, &hdr);
2130 encode_getfh(xdr, &hdr);
2131 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002132 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133}
2134
2135/*
2136 * Encode REMOVE request
2137 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002138static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr,
2139 const struct nfs_removeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002140{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002141 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002142 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002143 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002144
Chuck Lever9f06c712010-12-14 14:59:18 +00002145 encode_compound_hdr(xdr, req, &hdr);
2146 encode_sequence(xdr, &args->seq_args, &hdr);
2147 encode_putfh(xdr, args->fh, &hdr);
2148 encode_remove(xdr, &args->name, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002149 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150}
2151
2152/*
2153 * Encode RENAME request
2154 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002155static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr,
2156 const struct nfs_renameargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002157{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002158 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002159 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002160 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161
Chuck Lever9f06c712010-12-14 14:59:18 +00002162 encode_compound_hdr(xdr, req, &hdr);
2163 encode_sequence(xdr, &args->seq_args, &hdr);
2164 encode_putfh(xdr, args->old_dir, &hdr);
2165 encode_savefh(xdr, &hdr);
2166 encode_putfh(xdr, args->new_dir, &hdr);
2167 encode_rename(xdr, args->old_name, args->new_name, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002168 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169}
2170
2171/*
2172 * Encode LINK request
2173 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002174static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr,
2175 const struct nfs4_link_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002176{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002177 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002178 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002179 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002180
Chuck Lever9f06c712010-12-14 14:59:18 +00002181 encode_compound_hdr(xdr, req, &hdr);
2182 encode_sequence(xdr, &args->seq_args, &hdr);
2183 encode_putfh(xdr, args->fh, &hdr);
2184 encode_savefh(xdr, &hdr);
2185 encode_putfh(xdr, args->dir_fh, &hdr);
2186 encode_link(xdr, args->name, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002187 encode_restorefh(xdr, &hdr);
2188 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002189 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002190}
2191
2192/*
2193 * Encode CREATE request
2194 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002195static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
2196 const struct nfs4_create_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002198 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002199 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002200 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201
Chuck Lever9f06c712010-12-14 14:59:18 +00002202 encode_compound_hdr(xdr, req, &hdr);
2203 encode_sequence(xdr, &args->seq_args, &hdr);
2204 encode_putfh(xdr, args->dir_fh, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002205 encode_create(xdr, args, &hdr);
2206 encode_getfh(xdr, &hdr);
2207 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002208 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002209}
2210
2211/*
2212 * Encode SYMLINK request
2213 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002214static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr,
2215 const struct nfs4_create_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002216{
Chuck Lever9f06c712010-12-14 14:59:18 +00002217 nfs4_xdr_enc_create(req, xdr, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218}
2219
2220/*
2221 * Encode GETATTR request
2222 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002223static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr,
2224 const struct nfs4_getattr_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002225{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002226 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002227 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002229
Chuck Lever9f06c712010-12-14 14:59:18 +00002230 encode_compound_hdr(xdr, req, &hdr);
2231 encode_sequence(xdr, &args->seq_args, &hdr);
2232 encode_putfh(xdr, args->fh, &hdr);
2233 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002234 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002235}
2236
2237/*
2238 * Encode a CLOSE request
2239 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002240static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr,
2241 struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002242{
Andy Adamson05d564f2008-12-23 16:06:15 -05002243 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002244 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05002245 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246
Chuck Lever9f06c712010-12-14 14:59:18 +00002247 encode_compound_hdr(xdr, req, &hdr);
2248 encode_sequence(xdr, &args->seq_args, &hdr);
2249 encode_putfh(xdr, args->fh, &hdr);
2250 encode_close(xdr, args, &hdr);
2251 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002252 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253}
2254
2255/*
2256 * Encode an OPEN request
2257 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002258static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
2259 struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002260{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002262 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002264
Chuck Lever9f06c712010-12-14 14:59:18 +00002265 encode_compound_hdr(xdr, req, &hdr);
2266 encode_sequence(xdr, &args->seq_args, &hdr);
2267 encode_putfh(xdr, args->fh, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002268 encode_open(xdr, args, &hdr);
2269 encode_getfh(xdr, &hdr);
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07002270 if (args->access)
2271 encode_access(xdr, args->access, &hdr);
Trond Myklebust1549210f2012-06-05 09:16:47 -04002272 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002273 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274}
2275
2276/*
2277 * Encode an OPEN_CONFIRM request
2278 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002279static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req,
2280 struct xdr_stream *xdr,
2281 struct nfs_open_confirmargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002282{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002283 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002284 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002285 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002286
Chuck Lever9f06c712010-12-14 14:59:18 +00002287 encode_compound_hdr(xdr, req, &hdr);
2288 encode_putfh(xdr, args->fh, &hdr);
2289 encode_open_confirm(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002290 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291}
2292
2293/*
2294 * Encode an OPEN request with no attributes.
2295 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002296static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
2297 struct xdr_stream *xdr,
2298 struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002300 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002301 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002302 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002303
Chuck Lever9f06c712010-12-14 14:59:18 +00002304 encode_compound_hdr(xdr, req, &hdr);
2305 encode_sequence(xdr, &args->seq_args, &hdr);
2306 encode_putfh(xdr, args->fh, &hdr);
2307 encode_open(xdr, args, &hdr);
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07002308 if (args->access)
2309 encode_access(xdr, args->access, &hdr);
Andy Adamsone23008e2012-10-02 21:07:32 -04002310 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002311 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002312}
2313
2314/*
2315 * Encode an OPEN_DOWNGRADE request
2316 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002317static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req,
2318 struct xdr_stream *xdr,
2319 struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002320{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002321 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002322 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002323 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002324
Chuck Lever9f06c712010-12-14 14:59:18 +00002325 encode_compound_hdr(xdr, req, &hdr);
2326 encode_sequence(xdr, &args->seq_args, &hdr);
2327 encode_putfh(xdr, args->fh, &hdr);
2328 encode_open_downgrade(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002329 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330}
2331
2332/*
2333 * Encode a LOCK request
2334 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002335static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr,
2336 struct nfs_lock_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002337{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002338 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002339 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002340 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002341
Chuck Lever9f06c712010-12-14 14:59:18 +00002342 encode_compound_hdr(xdr, req, &hdr);
2343 encode_sequence(xdr, &args->seq_args, &hdr);
2344 encode_putfh(xdr, args->fh, &hdr);
2345 encode_lock(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002346 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002347}
2348
2349/*
2350 * Encode a LOCKT request
2351 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002352static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr,
2353 struct nfs_lockt_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002356 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002357 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002358
Chuck Lever9f06c712010-12-14 14:59:18 +00002359 encode_compound_hdr(xdr, req, &hdr);
2360 encode_sequence(xdr, &args->seq_args, &hdr);
2361 encode_putfh(xdr, args->fh, &hdr);
2362 encode_lockt(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002363 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002364}
2365
2366/*
2367 * Encode a LOCKU request
2368 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002369static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr,
2370 struct nfs_locku_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002373 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002374 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002375
Chuck Lever9f06c712010-12-14 14:59:18 +00002376 encode_compound_hdr(xdr, req, &hdr);
2377 encode_sequence(xdr, &args->seq_args, &hdr);
2378 encode_putfh(xdr, args->fh, &hdr);
2379 encode_locku(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002380 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002381}
2382
Chuck Lever9f06c712010-12-14 14:59:18 +00002383static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req,
2384 struct xdr_stream *xdr,
2385 struct nfs_release_lockowner_args *args)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002386{
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002387 struct compound_hdr hdr = {
2388 .minorversion = 0,
2389 };
2390
Chuck Lever9f06c712010-12-14 14:59:18 +00002391 encode_compound_hdr(xdr, req, &hdr);
2392 encode_release_lockowner(xdr, &args->lock_owner, &hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002393 encode_nops(&hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002394}
2395
Linus Torvalds1da177e2005-04-16 15:20:36 -07002396/*
2397 * Encode a READLINK request
2398 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002399static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr,
2400 const struct nfs4_readlink *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002401{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002403 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002404 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405
Chuck Lever9f06c712010-12-14 14:59:18 +00002406 encode_compound_hdr(xdr, req, &hdr);
2407 encode_sequence(xdr, &args->seq_args, &hdr);
2408 encode_putfh(xdr, args->fh, &hdr);
2409 encode_readlink(xdr, args, req, &hdr);
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002410
Benny Halevy28f56692009-04-01 09:22:09 -04002411 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002412 args->pgbase, args->pglen);
Andy Adamsond0179312008-12-23 16:06:17 -05002413 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002414}
2415
2416/*
2417 * Encode a READDIR request
2418 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002419static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr,
2420 const struct nfs4_readdir_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002421{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002422 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002423 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002424 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002425
Chuck Lever9f06c712010-12-14 14:59:18 +00002426 encode_compound_hdr(xdr, req, &hdr);
2427 encode_sequence(xdr, &args->seq_args, &hdr);
2428 encode_putfh(xdr, args->fh, &hdr);
2429 encode_readdir(xdr, args, req, &hdr);
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002430
Benny Halevy28f56692009-04-01 09:22:09 -04002431 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002432 args->pgbase, args->count);
2433 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
Benny Halevy28f56692009-04-01 09:22:09 -04002434 __func__, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002435 args->pgbase, args->count);
Andy Adamsond0179312008-12-23 16:06:17 -05002436 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002437}
2438
2439/*
2440 * Encode a READ request
2441 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002442static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr,
Anna Schumaker3c6b8992014-05-06 09:12:24 -04002443 struct nfs_pgio_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002444{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002446 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002447 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002448
Chuck Lever9f06c712010-12-14 14:59:18 +00002449 encode_compound_hdr(xdr, req, &hdr);
2450 encode_sequence(xdr, &args->seq_args, &hdr);
2451 encode_putfh(xdr, args->fh, &hdr);
2452 encode_read(xdr, args, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453
Benny Halevy28f56692009-04-01 09:22:09 -04002454 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 args->pages, args->pgbase, args->count);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002456 req->rq_rcv_buf.flags |= XDRBUF_READ;
Andy Adamsond0179312008-12-23 16:06:17 -05002457 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002458}
2459
2460/*
2461 * Encode an SETATTR request
2462 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002463static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr,
2464 struct nfs_setattrargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002465{
Andy Adamson05d564f2008-12-23 16:06:15 -05002466 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002467 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05002468 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002469
Chuck Lever9f06c712010-12-14 14:59:18 +00002470 encode_compound_hdr(xdr, req, &hdr);
2471 encode_sequence(xdr, &args->seq_args, &hdr);
2472 encode_putfh(xdr, args->fh, &hdr);
2473 encode_setattr(xdr, args, args->server, &hdr);
2474 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002475 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476}
2477
2478/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00002479 * Encode a GETACL request
2480 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002481static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
2482 struct nfs_getaclargs *args)
J. Bruce Fields029d1052005-06-22 17:16:22 +00002483{
J. Bruce Fields029d1052005-06-22 17:16:22 +00002484 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002485 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
J. Bruce Fields029d1052005-06-22 17:16:22 +00002486 };
Benny Halevy28f56692009-04-01 09:22:09 -04002487 uint32_t replen;
J. Bruce Fields029d1052005-06-22 17:16:22 +00002488
Chuck Lever9f06c712010-12-14 14:59:18 +00002489 encode_compound_hdr(xdr, req, &hdr);
2490 encode_sequence(xdr, &args->seq_args, &hdr);
2491 encode_putfh(xdr, args->fh, &hdr);
Andy Adamsonbf118a32011-12-07 11:55:27 -05002492 replen = hdr.replen + op_decode_hdr_maxsz + 1;
Chuck Lever9f06c712010-12-14 14:59:18 +00002493 encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002494
Benny Halevy28f56692009-04-01 09:22:09 -04002495 xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
Andreas Gruenbacher8fbcf232015-11-03 18:25:34 +01002496 args->acl_pages, 0, args->acl_len);
Andy Adamsonbf118a32011-12-07 11:55:27 -05002497
Andy Adamsond0179312008-12-23 16:06:17 -05002498 encode_nops(&hdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00002499}
2500
2501/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002502 * Encode a WRITE request
2503 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002504static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
Anna Schumaker3c6b8992014-05-06 09:12:24 -04002505 struct nfs_pgio_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002508 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002509 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002510
Chuck Lever9f06c712010-12-14 14:59:18 +00002511 encode_compound_hdr(xdr, req, &hdr);
2512 encode_sequence(xdr, &args->seq_args, &hdr);
2513 encode_putfh(xdr, args->fh, &hdr);
2514 encode_write(xdr, args, &hdr);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002515 req->rq_snd_buf.flags |= XDRBUF_WRITE;
Fred Isaman7ffd1062011-03-03 15:13:46 +00002516 if (args->bitmask)
2517 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002518 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002519}
2520
2521/*
2522 * a COMMIT request
2523 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002524static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr,
Fred Isaman0b7c0152012-04-20 14:47:39 -04002525 struct nfs_commitargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002527 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002528 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002530
Chuck Lever9f06c712010-12-14 14:59:18 +00002531 encode_compound_hdr(xdr, req, &hdr);
2532 encode_sequence(xdr, &args->seq_args, &hdr);
2533 encode_putfh(xdr, args->fh, &hdr);
2534 encode_commit(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002535 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002536}
2537
2538/*
2539 * FSINFO request
2540 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002541static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
2542 struct nfs4_fsinfo_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002543{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002544 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002545 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002546 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002547
Chuck Lever9f06c712010-12-14 14:59:18 +00002548 encode_compound_hdr(xdr, req, &hdr);
2549 encode_sequence(xdr, &args->seq_args, &hdr);
2550 encode_putfh(xdr, args->fh, &hdr);
2551 encode_fsinfo(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002552 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002553}
2554
2555/*
2556 * a PATHCONF request
2557 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002558static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
2559 const struct nfs4_pathconf_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002562 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002563 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002564
Chuck Lever9f06c712010-12-14 14:59:18 +00002565 encode_compound_hdr(xdr, req, &hdr);
2566 encode_sequence(xdr, &args->seq_args, &hdr);
2567 encode_putfh(xdr, args->fh, &hdr);
2568 encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002569 &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002570 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571}
2572
2573/*
2574 * a STATFS request
2575 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002576static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
2577 const struct nfs4_statfs_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002579 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002580 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002581 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002582
Chuck Lever9f06c712010-12-14 14:59:18 +00002583 encode_compound_hdr(xdr, req, &hdr);
2584 encode_sequence(xdr, &args->seq_args, &hdr);
2585 encode_putfh(xdr, args->fh, &hdr);
2586 encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002587 args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002588 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002589}
2590
2591/*
2592 * GETATTR_BITMAP request
2593 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002594static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req,
2595 struct xdr_stream *xdr,
2596 struct nfs4_server_caps_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002597{
Kinglong Mee8c612822015-08-26 21:12:58 +08002598 const u32 *bitmask = args->bitmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002599 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002600 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002601 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602
Chuck Lever9f06c712010-12-14 14:59:18 +00002603 encode_compound_hdr(xdr, req, &hdr);
2604 encode_sequence(xdr, &args->seq_args, &hdr);
2605 encode_putfh(xdr, args->fhandle, &hdr);
Kinglong Mee8c612822015-08-26 21:12:58 +08002606 encode_getattr_three(xdr, bitmask[0], bitmask[1], bitmask[2], &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002607 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002608}
2609
2610/*
2611 * a RENEW request
2612 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002613static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr,
2614 struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002615{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002616 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002617 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002618 };
2619
Chuck Lever9f06c712010-12-14 14:59:18 +00002620 encode_compound_hdr(xdr, req, &hdr);
Chuck Leverbb4dae52012-03-01 17:01:48 -05002621 encode_renew(xdr, clp->cl_clientid, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002622 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002623}
2624
2625/*
2626 * a SETCLIENTID request
2627 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002628static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req,
2629 struct xdr_stream *xdr,
2630 struct nfs4_setclientid *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002633 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002634 };
2635
Chuck Lever9f06c712010-12-14 14:59:18 +00002636 encode_compound_hdr(xdr, req, &hdr);
2637 encode_setclientid(xdr, sc, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002638 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639}
2640
2641/*
2642 * a SETCLIENTID_CONFIRM request
2643 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002644static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
2645 struct xdr_stream *xdr,
2646 struct nfs4_setclientid_res *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002648 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002649 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002650 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002651
Chuck Lever9f06c712010-12-14 14:59:18 +00002652 encode_compound_hdr(xdr, req, &hdr);
2653 encode_setclientid_confirm(xdr, arg, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002654 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002655}
2656
2657/*
2658 * DELEGRETURN request
2659 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002660static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req,
2661 struct xdr_stream *xdr,
2662 const struct nfs4_delegreturnargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002664 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002665 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002667
Chuck Lever9f06c712010-12-14 14:59:18 +00002668 encode_compound_hdr(xdr, req, &hdr);
2669 encode_sequence(xdr, &args->seq_args, &hdr);
2670 encode_putfh(xdr, args->fhandle, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002671 encode_getfattr(xdr, args->bitmask, &hdr);
Trond Myklebuste144cbc2012-04-28 16:05:03 -04002672 encode_delegreturn(xdr, args->stateid, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002673 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002674}
2675
2676/*
Trond Myklebust683b57b2006-06-09 09:34:22 -04002677 * Encode FS_LOCATIONS request
2678 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002679static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
2680 struct xdr_stream *xdr,
2681 struct nfs4_fs_locations_arg *args)
Trond Myklebust683b57b2006-06-09 09:34:22 -04002682{
Trond Myklebust683b57b2006-06-09 09:34:22 -04002683 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002684 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Trond Myklebust683b57b2006-06-09 09:34:22 -04002685 };
Benny Halevy28f56692009-04-01 09:22:09 -04002686 uint32_t replen;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002687
Chuck Lever9f06c712010-12-14 14:59:18 +00002688 encode_compound_hdr(xdr, req, &hdr);
2689 encode_sequence(xdr, &args->seq_args, &hdr);
Chuck Leverb03d7352013-10-17 14:12:50 -04002690 if (args->migration) {
2691 encode_putfh(xdr, args->fh, &hdr);
2692 replen = hdr.replen;
2693 encode_fs_locations(xdr, args->bitmask, &hdr);
2694 if (args->renew)
2695 encode_renew(xdr, args->clientid, &hdr);
2696 } else {
2697 encode_putfh(xdr, args->dir_fh, &hdr);
2698 encode_lookup(xdr, args->name, &hdr);
2699 replen = hdr.replen;
2700 encode_fs_locations(xdr, args->bitmask, &hdr);
2701 }
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002702
Chuck Leverb03d7352013-10-17 14:12:50 -04002703 /* Set up reply kvec to capture returned fs_locations array. */
Benny Halevy28f56692009-04-01 09:22:09 -04002704 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
Trond Myklebust683b57b2006-06-09 09:34:22 -04002705 0, PAGE_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05002706 encode_nops(&hdr);
Trond Myklebust683b57b2006-06-09 09:34:22 -04002707}
2708
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00002709/*
2710 * Encode SECINFO request
2711 */
2712static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req,
2713 struct xdr_stream *xdr,
2714 struct nfs4_secinfo_arg *args)
2715{
2716 struct compound_hdr hdr = {
2717 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2718 };
2719
2720 encode_compound_hdr(xdr, req, &hdr);
2721 encode_sequence(xdr, &args->seq_args, &hdr);
2722 encode_putfh(xdr, args->dir_fh, &hdr);
2723 encode_secinfo(xdr, args->name, &hdr);
2724 encode_nops(&hdr);
2725}
2726
Chuck Lever44c99932013-10-17 14:13:30 -04002727/*
2728 * Encode FSID_PRESENT request
2729 */
2730static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
2731 struct xdr_stream *xdr,
2732 struct nfs4_fsid_present_arg *args)
2733{
2734 struct compound_hdr hdr = {
2735 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2736 };
2737
2738 encode_compound_hdr(xdr, req, &hdr);
2739 encode_sequence(xdr, &args->seq_args, &hdr);
2740 encode_putfh(xdr, args->fh, &hdr);
2741 encode_getfh(xdr, &hdr);
2742 if (args->renew)
2743 encode_renew(xdr, args->clientid, &hdr);
2744 encode_nops(&hdr);
2745}
2746
Benny Halevy99fe60d2009-04-01 09:22:29 -04002747#if defined(CONFIG_NFS_V4_1)
2748/*
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002749 * BIND_CONN_TO_SESSION request
2750 */
2751static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
2752 struct xdr_stream *xdr,
Trond Myklebust71a097c2015-02-18 09:27:18 -08002753 struct nfs41_bind_conn_to_session_args *args)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002754{
2755 struct compound_hdr hdr = {
Trond Myklebust71a097c2015-02-18 09:27:18 -08002756 .minorversion = args->client->cl_mvops->minor_version,
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002757 };
2758
2759 encode_compound_hdr(xdr, req, &hdr);
Trond Myklebust71a097c2015-02-18 09:27:18 -08002760 encode_bind_conn_to_session(xdr, args, &hdr);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002761 encode_nops(&hdr);
2762}
2763
2764/*
Benny Halevy99fe60d2009-04-01 09:22:29 -04002765 * EXCHANGE_ID request
2766 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002767static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req,
2768 struct xdr_stream *xdr,
2769 struct nfs41_exchange_id_args *args)
Benny Halevy99fe60d2009-04-01 09:22:29 -04002770{
Benny Halevy99fe60d2009-04-01 09:22:29 -04002771 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002772 .minorversion = args->client->cl_mvops->minor_version,
Benny Halevy99fe60d2009-04-01 09:22:29 -04002773 };
2774
Chuck Lever9f06c712010-12-14 14:59:18 +00002775 encode_compound_hdr(xdr, req, &hdr);
2776 encode_exchange_id(xdr, args, &hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04002777 encode_nops(&hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04002778}
Andy Adamson2050f0c2009-04-01 09:22:30 -04002779
2780/*
Andy Adamsonfc931582009-04-01 09:22:31 -04002781 * a CREATE_SESSION request
2782 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002783static void nfs4_xdr_enc_create_session(struct rpc_rqst *req,
2784 struct xdr_stream *xdr,
2785 struct nfs41_create_session_args *args)
Andy Adamsonfc931582009-04-01 09:22:31 -04002786{
Andy Adamsonfc931582009-04-01 09:22:31 -04002787 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002788 .minorversion = args->client->cl_mvops->minor_version,
Andy Adamsonfc931582009-04-01 09:22:31 -04002789 };
2790
Chuck Lever9f06c712010-12-14 14:59:18 +00002791 encode_compound_hdr(xdr, req, &hdr);
2792 encode_create_session(xdr, args, &hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04002793 encode_nops(&hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04002794}
2795
2796/*
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002797 * a DESTROY_SESSION request
2798 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002799static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req,
2800 struct xdr_stream *xdr,
2801 struct nfs4_session *session)
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002802{
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002803 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002804 .minorversion = session->clp->cl_mvops->minor_version,
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002805 };
2806
Chuck Lever9f06c712010-12-14 14:59:18 +00002807 encode_compound_hdr(xdr, req, &hdr);
2808 encode_destroy_session(xdr, session, &hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002809 encode_nops(&hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002810}
2811
2812/*
Trond Myklebust66245532012-05-25 17:18:09 -04002813 * a DESTROY_CLIENTID request
2814 */
2815static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req,
2816 struct xdr_stream *xdr,
2817 struct nfs_client *clp)
2818{
2819 struct compound_hdr hdr = {
2820 .minorversion = clp->cl_mvops->minor_version,
2821 };
2822
2823 encode_compound_hdr(xdr, req, &hdr);
2824 encode_destroy_clientid(xdr, clp->cl_clientid, &hdr);
2825 encode_nops(&hdr);
2826}
2827
2828/*
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002829 * a SEQUENCE request
2830 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002831static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr,
2832 struct nfs4_sequence_args *args)
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002833{
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002834 struct compound_hdr hdr = {
2835 .minorversion = nfs4_xdr_minorversion(args),
2836 };
2837
Chuck Lever9f06c712010-12-14 14:59:18 +00002838 encode_compound_hdr(xdr, req, &hdr);
2839 encode_sequence(xdr, args, &hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002840 encode_nops(&hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002841}
2842
2843/*
Andy Adamson2050f0c2009-04-01 09:22:30 -04002844 * a GET_LEASE_TIME request
2845 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002846static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req,
2847 struct xdr_stream *xdr,
2848 struct nfs4_get_lease_time_args *args)
Andy Adamson2050f0c2009-04-01 09:22:30 -04002849{
Andy Adamson2050f0c2009-04-01 09:22:30 -04002850 struct compound_hdr hdr = {
2851 .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
2852 };
Fred Isamandae100c2011-07-30 20:52:37 -04002853 const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
Andy Adamson2050f0c2009-04-01 09:22:30 -04002854
Chuck Lever9f06c712010-12-14 14:59:18 +00002855 encode_compound_hdr(xdr, req, &hdr);
2856 encode_sequence(xdr, &args->la_seq_args, &hdr);
2857 encode_putrootfh(xdr, &hdr);
2858 encode_fsinfo(xdr, lease_bitmap, &hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04002859 encode_nops(&hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04002860}
Ricardo Labiaga180197532009-12-05 16:08:40 -05002861
2862/*
2863 * a RECLAIM_COMPLETE request
2864 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002865static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req,
2866 struct xdr_stream *xdr,
2867 struct nfs41_reclaim_complete_args *args)
Ricardo Labiaga180197532009-12-05 16:08:40 -05002868{
Ricardo Labiaga180197532009-12-05 16:08:40 -05002869 struct compound_hdr hdr = {
2870 .minorversion = nfs4_xdr_minorversion(&args->seq_args)
2871 };
2872
Chuck Lever9f06c712010-12-14 14:59:18 +00002873 encode_compound_hdr(xdr, req, &hdr);
2874 encode_sequence(xdr, &args->seq_args, &hdr);
2875 encode_reclaim_complete(xdr, args, &hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05002876 encode_nops(&hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05002877}
2878
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002879/*
2880 * Encode GETDEVICEINFO request
2881 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002882static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req,
2883 struct xdr_stream *xdr,
2884 struct nfs4_getdeviceinfo_args *args)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002885{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002886 struct compound_hdr hdr = {
2887 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2888 };
2889
Chuck Lever9f06c712010-12-14 14:59:18 +00002890 encode_compound_hdr(xdr, req, &hdr);
2891 encode_sequence(xdr, &args->seq_args, &hdr);
2892 encode_getdeviceinfo(xdr, args, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002893
2894 /* set up reply kvec. Subtract notification bitmap max size (2)
2895 * so that notification bitmap is put in xdr_buf tail */
2896 xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
2897 args->pdev->pages, args->pdev->pgbase,
2898 args->pdev->pglen);
2899
2900 encode_nops(&hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002901}
2902
2903/*
2904 * Encode LAYOUTGET request
2905 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002906static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
2907 struct xdr_stream *xdr,
2908 struct nfs4_layoutget_args *args)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002909{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002910 struct compound_hdr hdr = {
2911 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2912 };
2913
Chuck Lever9f06c712010-12-14 14:59:18 +00002914 encode_compound_hdr(xdr, req, &hdr);
2915 encode_sequence(xdr, &args->seq_args, &hdr);
2916 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2917 encode_layoutget(xdr, args, &hdr);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04002918
2919 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2920 args->layout.pages, 0, args->layout.pglen);
2921
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002922 encode_nops(&hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002923}
Andy Adamson863a3c62011-03-23 13:27:54 +00002924
2925/*
2926 * Encode LAYOUTCOMMIT request
2927 */
Benny Halevycbe82602011-05-22 19:52:37 +03002928static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
2929 struct xdr_stream *xdr,
2930 struct nfs4_layoutcommit_args *args)
Andy Adamson863a3c62011-03-23 13:27:54 +00002931{
Benny Halevyac7db722011-05-22 19:53:48 +03002932 struct nfs4_layoutcommit_data *data =
2933 container_of(args, struct nfs4_layoutcommit_data, args);
Andy Adamson863a3c62011-03-23 13:27:54 +00002934 struct compound_hdr hdr = {
2935 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2936 };
2937
2938 encode_compound_hdr(xdr, req, &hdr);
2939 encode_sequence(xdr, &args->seq_args, &hdr);
2940 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
Benny Halevyac7db722011-05-22 19:53:48 +03002941 encode_layoutcommit(xdr, data->args.inode, args, &hdr);
Andy Adamson863a3c62011-03-23 13:27:54 +00002942 encode_getfattr(xdr, args->bitmask, &hdr);
2943 encode_nops(&hdr);
Benny Halevycbe82602011-05-22 19:52:37 +03002944}
2945
2946/*
2947 * Encode LAYOUTRETURN request
2948 */
2949static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
2950 struct xdr_stream *xdr,
2951 struct nfs4_layoutreturn_args *args)
2952{
2953 struct compound_hdr hdr = {
2954 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2955 };
2956
2957 encode_compound_hdr(xdr, req, &hdr);
2958 encode_sequence(xdr, &args->seq_args, &hdr);
2959 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2960 encode_layoutreturn(xdr, args, &hdr);
2961 encode_nops(&hdr);
Andy Adamson863a3c62011-03-23 13:27:54 +00002962}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002963
2964/*
2965 * Encode SECINFO_NO_NAME request
2966 */
2967static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
2968 struct xdr_stream *xdr,
2969 struct nfs41_secinfo_no_name_args *args)
2970{
2971 struct compound_hdr hdr = {
2972 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2973 };
2974
2975 encode_compound_hdr(xdr, req, &hdr);
2976 encode_sequence(xdr, &args->seq_args, &hdr);
2977 encode_putrootfh(xdr, &hdr);
2978 encode_secinfo_no_name(xdr, args, &hdr);
2979 encode_nops(&hdr);
2980 return 0;
2981}
Bryan Schumaker7d974792011-06-02 14:59:08 -04002982
2983/*
2984 * Encode TEST_STATEID request
2985 */
2986static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req,
2987 struct xdr_stream *xdr,
2988 struct nfs41_test_stateid_args *args)
2989{
2990 struct compound_hdr hdr = {
2991 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2992 };
2993
2994 encode_compound_hdr(xdr, req, &hdr);
2995 encode_sequence(xdr, &args->seq_args, &hdr);
2996 encode_test_stateid(xdr, args, &hdr);
2997 encode_nops(&hdr);
2998}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04002999
3000/*
3001 * Encode FREE_STATEID request
3002 */
3003static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req,
3004 struct xdr_stream *xdr,
3005 struct nfs41_free_stateid_args *args)
3006{
3007 struct compound_hdr hdr = {
3008 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
3009 };
3010
3011 encode_compound_hdr(xdr, req, &hdr);
3012 encode_sequence(xdr, &args->seq_args, &hdr);
3013 encode_free_stateid(xdr, args, &hdr);
3014 encode_nops(&hdr);
3015}
Benny Halevy99fe60d2009-04-01 09:22:29 -04003016#endif /* CONFIG_NFS_V4_1 */
3017
Benny Halevy686841b2009-08-14 17:19:48 +03003018static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
3019{
3020 dprintk("nfs: %s: prematurely hit end of receive buffer. "
3021 "Remaining buffer length is %tu words.\n",
3022 func, xdr->end - xdr->p);
3023}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024
Trond Myklebust683b57b2006-06-09 09:34:22 -04003025static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026{
Al Viro8687b632006-10-19 23:28:48 -07003027 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003028
Benny Halevyc0eae662009-08-14 17:20:14 +03003029 p = xdr_inline_decode(xdr, 4);
3030 if (unlikely(!p))
3031 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003032 *len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003033 p = xdr_inline_decode(xdr, *len);
3034 if (unlikely(!p))
3035 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003036 *string = (char *)p;
3037 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003038out_overflow:
3039 print_overflow_msg(__func__, xdr);
3040 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003041}
3042
3043static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
3044{
Al Viro8687b632006-10-19 23:28:48 -07003045 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003046
Benny Halevyc0eae662009-08-14 17:20:14 +03003047 p = xdr_inline_decode(xdr, 8);
3048 if (unlikely(!p))
3049 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003050 hdr->status = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03003051 hdr->taglen = be32_to_cpup(p);
Andy Adamson6c0195a2008-12-23 16:06:15 -05003052
Benny Halevyc0eae662009-08-14 17:20:14 +03003053 p = xdr_inline_decode(xdr, hdr->taglen + 4);
3054 if (unlikely(!p))
3055 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003056 hdr->tag = (char *)p;
3057 p += XDR_QUADLEN(hdr->taglen);
Benny Halevycccddf42009-08-14 17:20:19 +03003058 hdr->nops = be32_to_cpup(p);
Benny Halevyaadf6152008-12-23 16:06:13 -05003059 if (unlikely(hdr->nops < 1))
3060 return nfs4_stat_to_errno(hdr->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003062out_overflow:
3063 print_overflow_msg(__func__, xdr);
3064 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003065}
3066
Trond Myklebustc7848f62013-12-04 17:39:23 -05003067static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
3068 int *nfs_retval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069{
Al Viro8687b632006-10-19 23:28:48 -07003070 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 uint32_t opnum;
3072 int32_t nfserr;
3073
Benny Halevyc0eae662009-08-14 17:20:14 +03003074 p = xdr_inline_decode(xdr, 8);
3075 if (unlikely(!p))
3076 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003077 opnum = be32_to_cpup(p++);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003078 if (unlikely(opnum != expected))
3079 goto out_bad_operation;
Benny Halevycccddf42009-08-14 17:20:19 +03003080 nfserr = be32_to_cpup(p);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003081 if (nfserr == NFS_OK)
3082 *nfs_retval = 0;
3083 else
3084 *nfs_retval = nfs4_stat_to_errno(nfserr);
3085 return true;
3086out_bad_operation:
3087 dprintk("nfs: Server returned operation"
3088 " %d but we issued a request for %d\n",
3089 opnum, expected);
3090 *nfs_retval = -EREMOTEIO;
3091 return false;
Benny Halevyc0eae662009-08-14 17:20:14 +03003092out_overflow:
3093 print_overflow_msg(__func__, xdr);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003094 *nfs_retval = -EIO;
3095 return false;
3096}
3097
3098static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
3099{
3100 int retval;
3101
3102 __decode_op_hdr(xdr, expected, &retval);
3103 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104}
3105
3106/* Dummy routine */
David Howellsadfa6f92006-08-22 20:06:08 -04003107static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003108{
Al Viro8687b632006-10-19 23:28:48 -07003109 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003110 unsigned int strlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003111 char *str;
3112
Benny Halevyc0eae662009-08-14 17:20:14 +03003113 p = xdr_inline_decode(xdr, 12);
3114 if (likely(p))
3115 return decode_opaque_inline(xdr, &strlen, &str);
3116 print_overflow_msg(__func__, xdr);
3117 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003118}
3119
3120static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
3121{
Al Viro8687b632006-10-19 23:28:48 -07003122 uint32_t bmlen;
3123 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003124
Benny Halevyc0eae662009-08-14 17:20:14 +03003125 p = xdr_inline_decode(xdr, 4);
3126 if (unlikely(!p))
3127 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003128 bmlen = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003129
Fred Isamandae100c2011-07-30 20:52:37 -04003130 bitmap[0] = bitmap[1] = bitmap[2] = 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003131 p = xdr_inline_decode(xdr, (bmlen << 2));
3132 if (unlikely(!p))
3133 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003134 if (bmlen > 0) {
Benny Halevy6f723f72009-08-14 17:19:37 +03003135 bitmap[0] = be32_to_cpup(p++);
Fred Isamandae100c2011-07-30 20:52:37 -04003136 if (bmlen > 1) {
3137 bitmap[1] = be32_to_cpup(p++);
3138 if (bmlen > 2)
3139 bitmap[2] = be32_to_cpup(p);
3140 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141 }
3142 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003143out_overflow:
3144 print_overflow_msg(__func__, xdr);
3145 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003146}
3147
Trond Myklebust256e48b2012-06-21 11:18:13 -04003148static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003149{
Al Viro8687b632006-10-19 23:28:48 -07003150 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151
Benny Halevyc0eae662009-08-14 17:20:14 +03003152 p = xdr_inline_decode(xdr, 4);
3153 if (unlikely(!p))
3154 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003155 *attrlen = be32_to_cpup(p);
Trond Myklebust256e48b2012-06-21 11:18:13 -04003156 *savep = xdr_stream_pos(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003158out_overflow:
3159 print_overflow_msg(__func__, xdr);
3160 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161}
3162
3163static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
3164{
3165 if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
Roman Borisov3388bff2010-10-13 16:54:51 +04003166 int ret;
3167 ret = decode_attr_bitmap(xdr, bitmask);
3168 if (unlikely(ret < 0))
3169 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003170 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
3171 } else
Fred Isamandae100c2011-07-30 20:52:37 -04003172 bitmask[0] = bitmask[1] = bitmask[2] = 0;
3173 dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
3174 bitmask[0], bitmask[1], bitmask[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003175 return 0;
3176}
3177
3178static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
3179{
Al Viro8687b632006-10-19 23:28:48 -07003180 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003181 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182
3183 *type = 0;
3184 if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
3185 return -EIO;
3186 if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003187 p = xdr_inline_decode(xdr, 4);
3188 if (unlikely(!p))
3189 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003190 *type = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003191 if (*type < NF4REG || *type > NF4NAMEDATTR) {
Harvey Harrison3110ff82008-05-02 13:42:44 -07003192 dprintk("%s: bad type %d\n", __func__, *type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003193 return -EIO;
3194 }
3195 bitmap[0] &= ~FATTR4_WORD0_TYPE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003196 ret = NFS_ATTR_FATTR_TYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003197 }
Trond Myklebustbca79472009-03-11 14:10:26 -04003198 dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
Trond Myklebust409924e2009-03-11 14:10:27 -04003199 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003200out_overflow:
3201 print_overflow_msg(__func__, xdr);
3202 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203}
3204
Chuck Lever264e6352012-03-01 17:02:05 -05003205static int decode_attr_fh_expire_type(struct xdr_stream *xdr,
3206 uint32_t *bitmap, uint32_t *type)
3207{
3208 __be32 *p;
3209
3210 *type = 0;
3211 if (unlikely(bitmap[0] & (FATTR4_WORD0_FH_EXPIRE_TYPE - 1U)))
3212 return -EIO;
3213 if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) {
3214 p = xdr_inline_decode(xdr, 4);
3215 if (unlikely(!p))
3216 goto out_overflow;
3217 *type = be32_to_cpup(p);
3218 bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE;
3219 }
3220 dprintk("%s: expire type=0x%x\n", __func__, *type);
3221 return 0;
3222out_overflow:
3223 print_overflow_msg(__func__, xdr);
3224 return -EIO;
3225}
3226
Linus Torvalds1da177e2005-04-16 15:20:36 -07003227static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
3228{
Al Viro8687b632006-10-19 23:28:48 -07003229 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003230 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003231
3232 *change = 0;
3233 if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
3234 return -EIO;
3235 if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003236 p = xdr_inline_decode(xdr, 8);
3237 if (unlikely(!p))
3238 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003239 xdr_decode_hyper(p, change);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003240 bitmap[0] &= ~FATTR4_WORD0_CHANGE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003241 ret = NFS_ATTR_FATTR_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003242 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003243 dprintk("%s: change attribute=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 (unsigned long long)*change);
Trond Myklebust409924e2009-03-11 14:10:27 -04003245 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003246out_overflow:
3247 print_overflow_msg(__func__, xdr);
3248 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003249}
3250
3251static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
3252{
Al Viro8687b632006-10-19 23:28:48 -07003253 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003254 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003255
3256 *size = 0;
3257 if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
3258 return -EIO;
3259 if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003260 p = xdr_inline_decode(xdr, 8);
3261 if (unlikely(!p))
3262 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003263 xdr_decode_hyper(p, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264 bitmap[0] &= ~FATTR4_WORD0_SIZE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003265 ret = NFS_ATTR_FATTR_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003266 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003267 dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
Trond Myklebust409924e2009-03-11 14:10:27 -04003268 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003269out_overflow:
3270 print_overflow_msg(__func__, xdr);
3271 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003272}
3273
3274static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3275{
Al Viro8687b632006-10-19 23:28:48 -07003276 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277
3278 *res = 0;
3279 if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
3280 return -EIO;
3281 if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003282 p = xdr_inline_decode(xdr, 4);
3283 if (unlikely(!p))
3284 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003285 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003286 bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
3287 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003288 dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003289 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003290out_overflow:
3291 print_overflow_msg(__func__, xdr);
3292 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003293}
3294
3295static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3296{
Al Viro8687b632006-10-19 23:28:48 -07003297 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003298
3299 *res = 0;
3300 if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
3301 return -EIO;
3302 if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003303 p = xdr_inline_decode(xdr, 4);
3304 if (unlikely(!p))
3305 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003306 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003307 bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
3308 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003309 dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003311out_overflow:
3312 print_overflow_msg(__func__, xdr);
3313 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003314}
3315
Trond Myklebust8b4bdcf2006-06-09 09:34:19 -04003316static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003317{
Al Viro8687b632006-10-19 23:28:48 -07003318 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003319 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003320
3321 fsid->major = 0;
3322 fsid->minor = 0;
3323 if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
3324 return -EIO;
3325 if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003326 p = xdr_inline_decode(xdr, 16);
3327 if (unlikely(!p))
3328 goto out_overflow;
Benny Halevy3ceb4db2009-08-14 17:19:41 +03003329 p = xdr_decode_hyper(p, &fsid->major);
Benny Halevycccddf42009-08-14 17:20:19 +03003330 xdr_decode_hyper(p, &fsid->minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 bitmap[0] &= ~FATTR4_WORD0_FSID;
Trond Myklebust409924e2009-03-11 14:10:27 -04003332 ret = NFS_ATTR_FATTR_FSID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003333 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003334 dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003335 (unsigned long long)fsid->major,
3336 (unsigned long long)fsid->minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04003337 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003338out_overflow:
3339 print_overflow_msg(__func__, xdr);
3340 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003341}
3342
3343static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3344{
Al Viro8687b632006-10-19 23:28:48 -07003345 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003346
3347 *res = 60;
3348 if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
3349 return -EIO;
3350 if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003351 p = xdr_inline_decode(xdr, 4);
3352 if (unlikely(!p))
3353 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003354 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003355 bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
3356 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003357 dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003358 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003359out_overflow:
3360 print_overflow_msg(__func__, xdr);
3361 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362}
3363
Trond Myklebustee7b75f2011-06-16 13:15:41 -04003364static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
Bryan Schumakerae42c702010-10-21 16:33:17 -04003365{
3366 __be32 *p;
3367
3368 if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
3369 return -EIO;
3370 if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
3371 p = xdr_inline_decode(xdr, 4);
3372 if (unlikely(!p))
3373 goto out_overflow;
3374 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
Trond Myklebustee7b75f2011-06-16 13:15:41 -04003375 *res = -be32_to_cpup(p);
Bryan Schumakerae42c702010-10-21 16:33:17 -04003376 }
3377 return 0;
3378out_overflow:
3379 print_overflow_msg(__func__, xdr);
3380 return -EIO;
3381}
3382
Kinglong Mee8c612822015-08-26 21:12:58 +08003383static int decode_attr_exclcreat_supported(struct xdr_stream *xdr,
3384 uint32_t *bitmap, uint32_t *bitmask)
3385{
3386 if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) {
3387 int ret;
3388 ret = decode_attr_bitmap(xdr, bitmask);
3389 if (unlikely(ret < 0))
3390 return ret;
3391 bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT;
3392 } else
3393 bitmask[0] = bitmask[1] = bitmask[2] = 0;
3394 dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
3395 bitmask[0], bitmask[1], bitmask[2]);
3396 return 0;
3397}
3398
Bryan Schumakerae42c702010-10-21 16:33:17 -04003399static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
3400{
3401 __be32 *p;
3402 int len;
3403
Trond Myklebust7ad07352010-10-23 15:34:20 -04003404 if (fh != NULL)
3405 memset(fh, 0, sizeof(*fh));
Bryan Schumakerae42c702010-10-21 16:33:17 -04003406
3407 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
3408 return -EIO;
3409 if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
3410 p = xdr_inline_decode(xdr, 4);
3411 if (unlikely(!p))
3412 goto out_overflow;
3413 len = be32_to_cpup(p);
3414 if (len > NFS4_FHSIZE)
3415 return -EIO;
Bryan Schumakerae42c702010-10-21 16:33:17 -04003416 p = xdr_inline_decode(xdr, len);
3417 if (unlikely(!p))
3418 goto out_overflow;
Trond Myklebust7ad07352010-10-23 15:34:20 -04003419 if (fh != NULL) {
3420 memcpy(fh->data, p, len);
3421 fh->size = len;
3422 }
Bryan Schumakerae42c702010-10-21 16:33:17 -04003423 bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
3424 }
3425 return 0;
3426out_overflow:
3427 print_overflow_msg(__func__, xdr);
3428 return -EIO;
3429}
3430
Linus Torvalds1da177e2005-04-16 15:20:36 -07003431static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3432{
Al Viro8687b632006-10-19 23:28:48 -07003433 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003434
Malahal Nainenia1800ac2014-01-27 15:31:09 -06003435 *res = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003436 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
3437 return -EIO;
3438 if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003439 p = xdr_inline_decode(xdr, 4);
3440 if (unlikely(!p))
3441 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003442 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
3444 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003445 dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003446 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003447out_overflow:
3448 print_overflow_msg(__func__, xdr);
3449 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003450}
3451
3452static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
3453{
Al Viro8687b632006-10-19 23:28:48 -07003454 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003455 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003456
3457 *fileid = 0;
3458 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
3459 return -EIO;
3460 if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003461 p = xdr_inline_decode(xdr, 8);
3462 if (unlikely(!p))
3463 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003464 xdr_decode_hyper(p, fileid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 bitmap[0] &= ~FATTR4_WORD0_FILEID;
Trond Myklebust409924e2009-03-11 14:10:27 -04003466 ret = NFS_ATTR_FATTR_FILEID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003468 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003469 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003470out_overflow:
3471 print_overflow_msg(__func__, xdr);
3472 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003473}
3474
Manoj Naik99baf622006-06-09 09:34:24 -04003475static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
3476{
Al Viro8687b632006-10-19 23:28:48 -07003477 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003478 int ret = 0;
Manoj Naik99baf622006-06-09 09:34:24 -04003479
3480 *fileid = 0;
3481 if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
3482 return -EIO;
3483 if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003484 p = xdr_inline_decode(xdr, 8);
3485 if (unlikely(!p))
3486 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003487 xdr_decode_hyper(p, fileid);
Manoj Naik99baf622006-06-09 09:34:24 -04003488 bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
Trond Myklebust28331a42011-04-27 13:47:52 -04003489 ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
Manoj Naik99baf622006-06-09 09:34:24 -04003490 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003491 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003492 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003493out_overflow:
3494 print_overflow_msg(__func__, xdr);
3495 return -EIO;
Manoj Naik99baf622006-06-09 09:34:24 -04003496}
3497
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3499{
Al Viro8687b632006-10-19 23:28:48 -07003500 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 int status = 0;
3502
3503 *res = 0;
3504 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
3505 return -EIO;
3506 if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003507 p = xdr_inline_decode(xdr, 8);
3508 if (unlikely(!p))
3509 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003510 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003511 bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
3512 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003513 dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003515out_overflow:
3516 print_overflow_msg(__func__, xdr);
3517 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003518}
3519
3520static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3521{
Al Viro8687b632006-10-19 23:28:48 -07003522 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003523 int status = 0;
3524
3525 *res = 0;
3526 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
3527 return -EIO;
3528 if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003529 p = xdr_inline_decode(xdr, 8);
3530 if (unlikely(!p))
3531 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003532 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003533 bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
3534 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003535 dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003536 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003537out_overflow:
3538 print_overflow_msg(__func__, xdr);
3539 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003540}
3541
3542static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3543{
Al Viro8687b632006-10-19 23:28:48 -07003544 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003545 int status = 0;
3546
3547 *res = 0;
3548 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
3549 return -EIO;
3550 if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003551 p = xdr_inline_decode(xdr, 8);
3552 if (unlikely(!p))
3553 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003554 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003555 bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
3556 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003557 dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003559out_overflow:
3560 print_overflow_msg(__func__, xdr);
3561 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003562}
3563
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003564static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
3565{
Chuck Lever464ad6b2007-10-26 13:32:08 -04003566 u32 n;
Al Viro8687b632006-10-19 23:28:48 -07003567 __be32 *p;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003568 int status = 0;
3569
Benny Halevyc0eae662009-08-14 17:20:14 +03003570 p = xdr_inline_decode(xdr, 4);
3571 if (unlikely(!p))
3572 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003573 n = be32_to_cpup(p);
Andy Adamson33a43f22006-06-09 09:34:30 -04003574 if (n == 0)
3575 goto root_path;
Chuck Lever02a29762012-03-01 17:00:31 -05003576 dprintk("pathname4: ");
Trond Myklebust809b4262013-03-27 11:54:45 -04003577 if (n > NFS4_PATHNAME_MAXCOMPONENTS) {
3578 dprintk("cannot parse %d components in path\n", n);
3579 goto out_eio;
3580 }
3581 for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) {
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003582 struct nfs4_string *component = &path->components[path->ncomponents];
3583 status = decode_opaque_inline(xdr, &component->len, &component->data);
3584 if (unlikely(status != 0))
3585 goto out_eio;
Trond Myklebust95a13f72012-03-14 21:55:01 -04003586 ifdebug (XDR)
Chuck Lever02a29762012-03-01 17:00:31 -05003587 pr_cont("%s%.*s ",
3588 (path->ncomponents != n ? "/ " : ""),
3589 component->len, component->data);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003590 }
3591out:
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003592 return status;
Andy Adamson33a43f22006-06-09 09:34:30 -04003593root_path:
3594/* a root pathname is sent as a zero component4 */
3595 path->ncomponents = 1;
3596 path->components[0].len=0;
3597 path->components[0].data=NULL;
Chuck Lever02a29762012-03-01 17:00:31 -05003598 dprintk("pathname4: /\n");
Andy Adamson33a43f22006-06-09 09:34:30 -04003599 goto out;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003600out_eio:
3601 dprintk(" status %d", status);
3602 status = -EIO;
3603 goto out;
Benny Halevyc0eae662009-08-14 17:20:14 +03003604out_overflow:
3605 print_overflow_msg(__func__, xdr);
3606 return -EIO;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003607}
3608
3609static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04003610{
3611 int n;
Al Viro8687b632006-10-19 23:28:48 -07003612 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003613 int status = -EIO;
3614
3615 if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
3616 goto out;
3617 status = 0;
3618 if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
3619 goto out;
Kinglong Meef54423a2015-11-18 10:39:26 +08003620 bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS;
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05003621 status = -EIO;
3622 /* Ignore borken servers that return unrequested attrs */
3623 if (unlikely(res == NULL))
3624 goto out;
Chuck Lever02a29762012-03-01 17:00:31 -05003625 dprintk("%s: fsroot:\n", __func__);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003626 status = decode_pathname(xdr, &res->fs_path);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003627 if (unlikely(status != 0))
3628 goto out;
Benny Halevyc0eae662009-08-14 17:20:14 +03003629 p = xdr_inline_decode(xdr, 4);
3630 if (unlikely(!p))
3631 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003632 n = be32_to_cpup(p);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003633 if (n <= 0)
3634 goto out_eio;
Trond Myklebust809b4262013-03-27 11:54:45 -04003635 for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
Chuck Lever464ad6b2007-10-26 13:32:08 -04003636 u32 m;
Trond Myklebust809b4262013-03-27 11:54:45 -04003637 struct nfs4_fs_location *loc;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003638
Trond Myklebust809b4262013-03-27 11:54:45 -04003639 if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES)
3640 break;
3641 loc = &res->locations[res->nlocations];
Benny Halevyc0eae662009-08-14 17:20:14 +03003642 p = xdr_inline_decode(xdr, 4);
3643 if (unlikely(!p))
3644 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003645 m = be32_to_cpup(p);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003646
Chuck Lever02a29762012-03-01 17:00:31 -05003647 dprintk("%s: servers:\n", __func__);
Trond Myklebust809b4262013-03-27 11:54:45 -04003648 for (loc->nservers = 0; loc->nservers < m; loc->nservers++) {
3649 struct nfs4_string *server;
3650
3651 if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) {
Chuck Lever464ad6b2007-10-26 13:32:08 -04003652 unsigned int i;
3653 dprintk("%s: using first %u of %u servers "
3654 "returned for location %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003655 __func__,
Chuck Lever464ad6b2007-10-26 13:32:08 -04003656 NFS4_FS_LOCATION_MAXSERVERS,
3657 m, res->nlocations);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003658 for (i = loc->nservers; i < m; i++) {
Trond Myklebust2e42c3e2007-05-14 17:20:41 -04003659 unsigned int len;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003660 char *data;
3661 status = decode_opaque_inline(xdr, &len, &data);
3662 if (unlikely(status != 0))
3663 goto out_eio;
3664 }
Trond Myklebust809b4262013-03-27 11:54:45 -04003665 break;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003666 }
Trond Myklebust809b4262013-03-27 11:54:45 -04003667 server = &loc->servers[loc->nservers];
3668 status = decode_opaque_inline(xdr, &server->len, &server->data);
3669 if (unlikely(status != 0))
3670 goto out_eio;
3671 dprintk("%s ", server->data);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003672 }
3673 status = decode_pathname(xdr, &loc->rootpath);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003674 if (unlikely(status != 0))
3675 goto out_eio;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003676 }
Trond Myklebust409924e2009-03-11 14:10:27 -04003677 if (res->nlocations != 0)
Chuck Lever81934dd2012-03-01 17:01:57 -05003678 status = NFS_ATTR_FATTR_V4_LOCATIONS;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003679out:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003680 dprintk("%s: fs_locations done, error = %d\n", __func__, status);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003681 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003682out_overflow:
3683 print_overflow_msg(__func__, xdr);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003684out_eio:
3685 status = -EIO;
3686 goto out;
3687}
3688
Linus Torvalds1da177e2005-04-16 15:20:36 -07003689static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3690{
Al Viro8687b632006-10-19 23:28:48 -07003691 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003692 int status = 0;
3693
3694 *res = 0;
3695 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
3696 return -EIO;
3697 if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003698 p = xdr_inline_decode(xdr, 8);
3699 if (unlikely(!p))
3700 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003701 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003702 bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
3703 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003704 dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003705 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003706out_overflow:
3707 print_overflow_msg(__func__, xdr);
3708 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709}
3710
3711static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
3712{
Al Viro8687b632006-10-19 23:28:48 -07003713 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003714 int status = 0;
3715
3716 *maxlink = 1;
3717 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
3718 return -EIO;
3719 if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003720 p = xdr_inline_decode(xdr, 4);
3721 if (unlikely(!p))
3722 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003723 *maxlink = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003724 bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
3725 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003726 dprintk("%s: maxlink=%u\n", __func__, *maxlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003727 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003728out_overflow:
3729 print_overflow_msg(__func__, xdr);
3730 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003731}
3732
3733static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
3734{
Al Viro8687b632006-10-19 23:28:48 -07003735 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003736 int status = 0;
3737
3738 *maxname = 1024;
3739 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
3740 return -EIO;
3741 if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003742 p = xdr_inline_decode(xdr, 4);
3743 if (unlikely(!p))
3744 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003745 *maxname = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003746 bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
3747 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003748 dprintk("%s: maxname=%u\n", __func__, *maxname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003749 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003750out_overflow:
3751 print_overflow_msg(__func__, xdr);
3752 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003753}
3754
3755static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3756{
Al Viro8687b632006-10-19 23:28:48 -07003757 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003758 int status = 0;
3759
3760 *res = 1024;
3761 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
3762 return -EIO;
3763 if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
3764 uint64_t maxread;
Benny Halevyc0eae662009-08-14 17:20:14 +03003765 p = xdr_inline_decode(xdr, 8);
3766 if (unlikely(!p))
3767 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003768 xdr_decode_hyper(p, &maxread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 if (maxread > 0x7FFFFFFF)
3770 maxread = 0x7FFFFFFF;
3771 *res = (uint32_t)maxread;
3772 bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
3773 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003774 dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003775 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003776out_overflow:
3777 print_overflow_msg(__func__, xdr);
3778 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779}
3780
3781static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3782{
Al Viro8687b632006-10-19 23:28:48 -07003783 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 int status = 0;
3785
3786 *res = 1024;
3787 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
3788 return -EIO;
3789 if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
3790 uint64_t maxwrite;
Benny Halevyc0eae662009-08-14 17:20:14 +03003791 p = xdr_inline_decode(xdr, 8);
3792 if (unlikely(!p))
3793 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003794 xdr_decode_hyper(p, &maxwrite);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003795 if (maxwrite > 0x7FFFFFFF)
3796 maxwrite = 0x7FFFFFFF;
3797 *res = (uint32_t)maxwrite;
3798 bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
3799 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003800 dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003801 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003802out_overflow:
3803 print_overflow_msg(__func__, xdr);
3804 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805}
3806
Trond Myklebustbca79472009-03-11 14:10:26 -04003807static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808{
Trond Myklebustbca79472009-03-11 14:10:26 -04003809 uint32_t tmp;
Al Viro8687b632006-10-19 23:28:48 -07003810 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003811 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812
3813 *mode = 0;
3814 if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
3815 return -EIO;
3816 if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003817 p = xdr_inline_decode(xdr, 4);
3818 if (unlikely(!p))
3819 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003820 tmp = be32_to_cpup(p);
Trond Myklebustbca79472009-03-11 14:10:26 -04003821 *mode = tmp & ~S_IFMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003822 bitmap[1] &= ~FATTR4_WORD1_MODE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003823 ret = NFS_ATTR_FATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003824 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003825 dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
Trond Myklebust409924e2009-03-11 14:10:27 -04003826 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003827out_overflow:
3828 print_overflow_msg(__func__, xdr);
3829 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003830}
3831
3832static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
3833{
Al Viro8687b632006-10-19 23:28:48 -07003834 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003835 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003836
3837 *nlink = 1;
3838 if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
3839 return -EIO;
3840 if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003841 p = xdr_inline_decode(xdr, 4);
3842 if (unlikely(!p))
3843 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003844 *nlink = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845 bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
Trond Myklebust409924e2009-03-11 14:10:27 -04003846 ret = NFS_ATTR_FATTR_NLINK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003847 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003848 dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
Trond Myklebust409924e2009-03-11 14:10:27 -04003849 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003850out_overflow:
3851 print_overflow_msg(__func__, xdr);
3852 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003853}
3854
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003855static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
Eric W. Biedermane5782072013-02-01 14:22:02 -08003856 const struct nfs_server *server, kuid_t *uid,
Trond Myklebust6926afd2012-01-07 13:22:46 -05003857 struct nfs4_string *owner_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003858{
Al Viro8687b632006-10-19 23:28:48 -07003859 uint32_t len;
3860 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003861 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003862
Eric W. Biedermane5782072013-02-01 14:22:02 -08003863 *uid = make_kuid(&init_user_ns, -2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
3865 return -EIO;
3866 if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003867 p = xdr_inline_decode(xdr, 4);
3868 if (unlikely(!p))
3869 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003870 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003871 p = xdr_inline_decode(xdr, len);
3872 if (unlikely(!p))
3873 goto out_overflow;
Trond Myklebust6926afd2012-01-07 13:22:46 -05003874 if (owner_name != NULL) {
3875 owner_name->data = kmemdup(p, len, GFP_NOWAIT);
3876 if (owner_name->data != NULL) {
3877 owner_name->len = len;
3878 ret = NFS_ATTR_FATTR_OWNER_NAME;
3879 }
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003880 } else if (len < XDR_MAX_NETOBJ) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08003881 if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0)
Trond Myklebust409924e2009-03-11 14:10:27 -04003882 ret = NFS_ATTR_FATTR_OWNER;
3883 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003884 dprintk("%s: nfs_map_name_to_uid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003885 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003887 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003888 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003889 bitmap[1] &= ~FATTR4_WORD1_OWNER;
3890 }
Eric W. Biedermane5782072013-02-01 14:22:02 -08003891 dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid));
Trond Myklebust409924e2009-03-11 14:10:27 -04003892 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003893out_overflow:
3894 print_overflow_msg(__func__, xdr);
3895 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896}
3897
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003898static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
Eric W. Biedermane5782072013-02-01 14:22:02 -08003899 const struct nfs_server *server, kgid_t *gid,
Trond Myklebust6926afd2012-01-07 13:22:46 -05003900 struct nfs4_string *group_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901{
Al Viro8687b632006-10-19 23:28:48 -07003902 uint32_t len;
3903 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003904 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003905
Eric W. Biedermane5782072013-02-01 14:22:02 -08003906 *gid = make_kgid(&init_user_ns, -2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003907 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
3908 return -EIO;
3909 if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003910 p = xdr_inline_decode(xdr, 4);
3911 if (unlikely(!p))
3912 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003913 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003914 p = xdr_inline_decode(xdr, len);
3915 if (unlikely(!p))
3916 goto out_overflow;
Trond Myklebust6926afd2012-01-07 13:22:46 -05003917 if (group_name != NULL) {
3918 group_name->data = kmemdup(p, len, GFP_NOWAIT);
3919 if (group_name->data != NULL) {
3920 group_name->len = len;
3921 ret = NFS_ATTR_FATTR_GROUP_NAME;
3922 }
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003923 } else if (len < XDR_MAX_NETOBJ) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08003924 if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0)
Trond Myklebust409924e2009-03-11 14:10:27 -04003925 ret = NFS_ATTR_FATTR_GROUP;
3926 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003927 dprintk("%s: nfs_map_group_to_gid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003928 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003930 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003931 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003932 bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
3933 }
Eric W. Biedermane5782072013-02-01 14:22:02 -08003934 dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid));
Trond Myklebust409924e2009-03-11 14:10:27 -04003935 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003936out_overflow:
3937 print_overflow_msg(__func__, xdr);
3938 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003939}
3940
3941static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
3942{
Al Viro8687b632006-10-19 23:28:48 -07003943 uint32_t major = 0, minor = 0;
3944 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003945 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003946
3947 *rdev = MKDEV(0,0);
3948 if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
3949 return -EIO;
3950 if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
3951 dev_t tmp;
3952
Benny Halevyc0eae662009-08-14 17:20:14 +03003953 p = xdr_inline_decode(xdr, 8);
3954 if (unlikely(!p))
3955 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003956 major = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03003957 minor = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003958 tmp = MKDEV(major, minor);
3959 if (MAJOR(tmp) == major && MINOR(tmp) == minor)
3960 *rdev = tmp;
3961 bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
Trond Myklebust409924e2009-03-11 14:10:27 -04003962 ret = NFS_ATTR_FATTR_RDEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003963 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003964 dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04003965 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003966out_overflow:
3967 print_overflow_msg(__func__, xdr);
3968 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003969}
3970
3971static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3972{
Al Viro8687b632006-10-19 23:28:48 -07003973 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 int status = 0;
3975
3976 *res = 0;
3977 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
3978 return -EIO;
3979 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003980 p = xdr_inline_decode(xdr, 8);
3981 if (unlikely(!p))
3982 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003983 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003984 bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
3985 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003986 dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003987 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003988out_overflow:
3989 print_overflow_msg(__func__, xdr);
3990 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991}
3992
3993static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3994{
Al Viro8687b632006-10-19 23:28:48 -07003995 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 int status = 0;
3997
3998 *res = 0;
3999 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
4000 return -EIO;
4001 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004002 p = xdr_inline_decode(xdr, 8);
4003 if (unlikely(!p))
4004 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004005 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004006 bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
4007 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004008 dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004009 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004010out_overflow:
4011 print_overflow_msg(__func__, xdr);
4012 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004013}
4014
4015static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
4016{
Al Viro8687b632006-10-19 23:28:48 -07004017 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004018 int status = 0;
4019
4020 *res = 0;
4021 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
4022 return -EIO;
4023 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004024 p = xdr_inline_decode(xdr, 8);
4025 if (unlikely(!p))
4026 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004027 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004028 bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
4029 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004030 dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004031 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004032out_overflow:
4033 print_overflow_msg(__func__, xdr);
4034 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004035}
4036
4037static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
4038{
Al Viro8687b632006-10-19 23:28:48 -07004039 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04004040 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004041
4042 *used = 0;
4043 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
4044 return -EIO;
4045 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004046 p = xdr_inline_decode(xdr, 8);
4047 if (unlikely(!p))
4048 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004049 xdr_decode_hyper(p, used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004050 bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
Trond Myklebust409924e2009-03-11 14:10:27 -04004051 ret = NFS_ATTR_FATTR_SPACE_USED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004052 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004053 dprintk("%s: space used=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004054 (unsigned long long)*used);
Trond Myklebust409924e2009-03-11 14:10:27 -04004055 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03004056out_overflow:
4057 print_overflow_msg(__func__, xdr);
4058 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004059}
4060
4061static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
4062{
Al Viro8687b632006-10-19 23:28:48 -07004063 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 uint64_t sec;
4065 uint32_t nsec;
4066
Benny Halevyc0eae662009-08-14 17:20:14 +03004067 p = xdr_inline_decode(xdr, 12);
4068 if (unlikely(!p))
4069 goto out_overflow;
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004070 p = xdr_decode_hyper(p, &sec);
Benny Halevycccddf42009-08-14 17:20:19 +03004071 nsec = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004072 time->tv_sec = (time_t)sec;
4073 time->tv_nsec = (long)nsec;
4074 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004075out_overflow:
4076 print_overflow_msg(__func__, xdr);
4077 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078}
4079
4080static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4081{
4082 int status = 0;
4083
4084 time->tv_sec = 0;
4085 time->tv_nsec = 0;
4086 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
4087 return -EIO;
4088 if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
4089 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004090 if (status == 0)
4091 status = NFS_ATTR_FATTR_ATIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092 bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
4093 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004094 dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 return status;
4096}
4097
4098static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4099{
4100 int status = 0;
4101
4102 time->tv_sec = 0;
4103 time->tv_nsec = 0;
4104 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
4105 return -EIO;
4106 if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
4107 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004108 if (status == 0)
4109 status = NFS_ATTR_FATTR_CTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
4111 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004112 dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004113 return status;
4114}
4115
Ricardo Labiaga55b6e772010-10-12 16:30:06 -07004116static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
4117 struct timespec *time)
4118{
4119 int status = 0;
4120
4121 time->tv_sec = 0;
4122 time->tv_nsec = 0;
4123 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
4124 return -EIO;
4125 if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
4126 status = decode_attr_time(xdr, time);
4127 bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
4128 }
4129 dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec,
4130 (long)time->tv_nsec);
4131 return status;
4132}
4133
David Quigleyaa9c2662013-05-22 12:50:44 -04004134static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
4135 struct nfs4_label *label)
4136{
4137 uint32_t pi = 0;
4138 uint32_t lfs = 0;
4139 __u32 len;
4140 __be32 *p;
4141 int status = 0;
4142
4143 if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U)))
4144 return -EIO;
4145 if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) {
4146 p = xdr_inline_decode(xdr, 4);
4147 if (unlikely(!p))
4148 goto out_overflow;
4149 lfs = be32_to_cpup(p++);
4150 p = xdr_inline_decode(xdr, 4);
4151 if (unlikely(!p))
4152 goto out_overflow;
4153 pi = be32_to_cpup(p++);
4154 p = xdr_inline_decode(xdr, 4);
4155 if (unlikely(!p))
4156 goto out_overflow;
4157 len = be32_to_cpup(p++);
4158 p = xdr_inline_decode(xdr, len);
4159 if (unlikely(!p))
4160 goto out_overflow;
4161 if (len < NFS4_MAXLABELLEN) {
4162 if (label) {
4163 memcpy(label->label, p, len);
4164 label->len = len;
4165 label->pi = pi;
4166 label->lfs = lfs;
4167 status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
4168 }
4169 bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
4170 } else
4171 printk(KERN_WARNING "%s: label too long (%u)!\n",
4172 __func__, len);
4173 }
4174 if (label && label->label)
4175 dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__,
4176 (char *)label->label, label->len, label->pi, label->lfs);
4177 return status;
4178
4179out_overflow:
4180 print_overflow_msg(__func__, xdr);
4181 return -EIO;
4182}
4183
Linus Torvalds1da177e2005-04-16 15:20:36 -07004184static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4185{
4186 int status = 0;
4187
4188 time->tv_sec = 0;
4189 time->tv_nsec = 0;
4190 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
4191 return -EIO;
4192 if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
4193 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004194 if (status == 0)
4195 status = NFS_ATTR_FATTR_MTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004196 bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
4197 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004198 dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004199 return status;
4200}
4201
Trond Myklebust256e48b2012-06-21 11:18:13 -04004202static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004203{
4204 unsigned int attrwords = XDR_QUADLEN(attrlen);
Trond Myklebust256e48b2012-06-21 11:18:13 -04004205 unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004206
4207 if (unlikely(attrwords != nwords)) {
Chuck Leverfe82a182007-09-11 18:01:10 -04004208 dprintk("%s: server returned incorrect attribute length: "
4209 "%u %c %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07004210 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004211 attrwords << 2,
4212 (attrwords < nwords) ? '<' : '>',
4213 nwords << 2);
4214 return -EIO;
4215 }
4216 return 0;
4217}
4218
4219static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4220{
Al Viro8687b632006-10-19 23:28:48 -07004221 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004222
Benny Halevyc0eae662009-08-14 17:20:14 +03004223 p = xdr_inline_decode(xdr, 20);
4224 if (unlikely(!p))
4225 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03004226 cinfo->atomic = be32_to_cpup(p++);
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004227 p = xdr_decode_hyper(p, &cinfo->before);
Benny Halevycccddf42009-08-14 17:20:19 +03004228 xdr_decode_hyper(p, &cinfo->after);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004230out_overflow:
4231 print_overflow_msg(__func__, xdr);
4232 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004233}
4234
Weston Andros Adamson6168f622012-09-10 14:00:46 -04004235static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
Al Viro8687b632006-10-19 23:28:48 -07004237 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004238 uint32_t supp, acc;
4239 int status;
4240
4241 status = decode_op_hdr(xdr, OP_ACCESS);
4242 if (status)
4243 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004244 p = xdr_inline_decode(xdr, 8);
4245 if (unlikely(!p))
4246 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03004247 supp = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03004248 acc = be32_to_cpup(p);
Weston Andros Adamson6168f622012-09-10 14:00:46 -04004249 *supported = supp;
4250 *access = acc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004251 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004252out_overflow:
4253 print_overflow_msg(__func__, xdr);
4254 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255}
4256
Benny Halevy07d30432009-08-14 17:19:52 +03004257static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004258{
Al Viro8687b632006-10-19 23:28:48 -07004259 __be32 *p;
Benny Halevy07d30432009-08-14 17:19:52 +03004260
4261 p = xdr_inline_decode(xdr, len);
4262 if (likely(p)) {
4263 memcpy(buf, p, len);
4264 return 0;
4265 }
4266 print_overflow_msg(__func__, xdr);
4267 return -EIO;
4268}
4269
4270static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4271{
Trond Myklebust2d2f24a2012-03-04 18:13:57 -05004272 return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004273}
4274
Trond Myklebust93b717f2016-05-16 17:42:43 -04004275static int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4276{
4277 stateid->type = NFS4_OPEN_STATEID_TYPE;
4278 return decode_stateid(xdr, stateid);
4279}
4280
4281static int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4282{
4283 stateid->type = NFS4_LOCK_STATEID_TYPE;
4284 return decode_stateid(xdr, stateid);
4285}
4286
4287static int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4288{
4289 stateid->type = NFS4_DELEGATION_STATEID_TYPE;
4290 return decode_stateid(xdr, stateid);
4291}
4292
Linus Torvalds1da177e2005-04-16 15:20:36 -07004293static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
4294{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004295 int status;
4296
4297 status = decode_op_hdr(xdr, OP_CLOSE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04004298 if (status != -EIO)
4299 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03004300 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04004301 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03004302 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004303}
4304
Benny Halevydb942bb2009-08-14 17:19:56 +03004305static int decode_verifier(struct xdr_stream *xdr, void *verifier)
4306{
Chuck Levercd937102012-03-02 17:14:31 -05004307 return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004308}
4309
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04004310static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
4311{
4312 return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE);
4313}
4314
Fred Isaman0b7c0152012-04-20 14:47:39 -04004315static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004316{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004317 int status;
4318
4319 status = decode_op_hdr(xdr, OP_COMMIT);
Benny Halevydb942bb2009-08-14 17:19:56 +03004320 if (!status)
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04004321 status = decode_write_verifier(xdr, &res->verf->verifier);
Benny Halevydb942bb2009-08-14 17:19:56 +03004322 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323}
4324
4325static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4326{
Al Viro8687b632006-10-19 23:28:48 -07004327 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 uint32_t bmlen;
4329 int status;
4330
4331 status = decode_op_hdr(xdr, OP_CREATE);
4332 if (status)
4333 return status;
4334 if ((status = decode_change_info(xdr, cinfo)))
4335 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004336 p = xdr_inline_decode(xdr, 4);
4337 if (unlikely(!p))
4338 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004339 bmlen = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03004340 p = xdr_inline_decode(xdr, bmlen << 2);
4341 if (likely(p))
4342 return 0;
4343out_overflow:
4344 print_overflow_msg(__func__, xdr);
4345 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004346}
4347
4348static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
4349{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004350 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004351 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004352 int status;
4353
4354 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4355 goto xdr_error;
4356 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4357 goto xdr_error;
4358 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4359 goto xdr_error;
4360 if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
4361 goto xdr_error;
Chuck Lever264e6352012-03-01 17:02:05 -05004362 if ((status = decode_attr_fh_expire_type(xdr, bitmap,
4363 &res->fh_expire_type)) != 0)
4364 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004365 if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
4366 goto xdr_error;
4367 if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
4368 goto xdr_error;
4369 if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
4370 goto xdr_error;
Kinglong Mee8c612822015-08-26 21:12:58 +08004371 if ((status = decode_attr_exclcreat_supported(xdr, bitmap,
4372 res->exclcreat_bitmask)) != 0)
4373 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004374 status = verify_attr_len(xdr, savep, attrlen);
4375xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004376 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004377 return status;
4378}
Andy Adamson6c0195a2008-12-23 16:06:15 -05004379
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
4381{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004382 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004383 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004384 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004385
Linus Torvalds1da177e2005-04-16 15:20:36 -07004386 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4387 goto xdr_error;
4388 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4389 goto xdr_error;
4390 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4391 goto xdr_error;
4392
4393 if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
4394 goto xdr_error;
4395 if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
4396 goto xdr_error;
4397 if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
4398 goto xdr_error;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004399
4400 status = -EIO;
4401 if (unlikely(bitmap[0]))
4402 goto xdr_error;
4403
Linus Torvalds1da177e2005-04-16 15:20:36 -07004404 if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
4405 goto xdr_error;
4406 if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
4407 goto xdr_error;
4408 if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
4409 goto xdr_error;
4410
4411 status = verify_attr_len(xdr, savep, attrlen);
4412xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004413 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004414 return status;
4415}
4416
4417static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
4418{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004419 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004420 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004421 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004422
Linus Torvalds1da177e2005-04-16 15:20:36 -07004423 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4424 goto xdr_error;
4425 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4426 goto xdr_error;
4427 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4428 goto xdr_error;
4429
4430 if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
4431 goto xdr_error;
4432 if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
4433 goto xdr_error;
4434
4435 status = verify_attr_len(xdr, savep, attrlen);
4436xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004437 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004438 return status;
4439}
4440
Andy Adamson88034c32012-05-23 05:02:34 -04004441static int decode_threshold_hint(struct xdr_stream *xdr,
4442 uint32_t *bitmap,
4443 uint64_t *res,
4444 uint32_t hint_bit)
4445{
4446 __be32 *p;
4447
4448 *res = 0;
4449 if (likely(bitmap[0] & hint_bit)) {
4450 p = xdr_inline_decode(xdr, 8);
4451 if (unlikely(!p))
4452 goto out_overflow;
4453 xdr_decode_hyper(p, res);
4454 }
4455 return 0;
4456out_overflow:
4457 print_overflow_msg(__func__, xdr);
4458 return -EIO;
4459}
4460
4461static int decode_first_threshold_item4(struct xdr_stream *xdr,
4462 struct nfs4_threshold *res)
4463{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004464 __be32 *p;
4465 unsigned int savep;
Andy Adamson88034c32012-05-23 05:02:34 -04004466 uint32_t bitmap[3] = {0,}, attrlen;
4467 int status;
4468
4469 /* layout type */
4470 p = xdr_inline_decode(xdr, 4);
4471 if (unlikely(!p)) {
4472 print_overflow_msg(__func__, xdr);
4473 return -EIO;
4474 }
4475 res->l_type = be32_to_cpup(p);
4476
4477 /* thi_hintset bitmap */
4478 status = decode_attr_bitmap(xdr, bitmap);
4479 if (status < 0)
4480 goto xdr_error;
4481
4482 /* thi_hintlist length */
4483 status = decode_attr_length(xdr, &attrlen, &savep);
4484 if (status < 0)
4485 goto xdr_error;
4486 /* thi_hintlist */
4487 status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD);
4488 if (status < 0)
4489 goto xdr_error;
4490 status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR);
4491 if (status < 0)
4492 goto xdr_error;
4493 status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz,
4494 THRESHOLD_RD_IO);
4495 if (status < 0)
4496 goto xdr_error;
4497 status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz,
4498 THRESHOLD_WR_IO);
4499 if (status < 0)
4500 goto xdr_error;
4501
4502 status = verify_attr_len(xdr, savep, attrlen);
4503 res->bm = bitmap[0];
4504
4505 dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n",
4506 __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz,
4507 res->wr_io_sz);
4508xdr_error:
4509 dprintk("%s ret=%d!\n", __func__, status);
4510 return status;
4511}
4512
4513/*
4514 * Thresholds on pNFS direct I/O vrs MDS I/O
4515 */
4516static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
4517 uint32_t *bitmap,
4518 struct nfs4_threshold *res)
4519{
4520 __be32 *p;
4521 int status = 0;
4522 uint32_t num;
4523
4524 if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
4525 return -EIO;
Trond Myklebust029c5342012-06-05 09:35:44 -04004526 if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) {
Trond Myklebust1549210f2012-06-05 09:16:47 -04004527 /* Did the server return an unrequested attribute? */
4528 if (unlikely(res == NULL))
4529 return -EREMOTEIO;
Andy Adamson88034c32012-05-23 05:02:34 -04004530 p = xdr_inline_decode(xdr, 4);
4531 if (unlikely(!p))
4532 goto out_overflow;
4533 num = be32_to_cpup(p);
4534 if (num == 0)
4535 return 0;
4536 if (num > 1)
4537 printk(KERN_INFO "%s: Warning: Multiple pNFS layout "
4538 "drivers per filesystem not supported\n",
4539 __func__);
4540
4541 status = decode_first_threshold_item4(xdr, res);
Trond Myklebust029c5342012-06-05 09:35:44 -04004542 bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
Andy Adamson88034c32012-05-23 05:02:34 -04004543 }
4544 return status;
4545out_overflow:
4546 print_overflow_msg(__func__, xdr);
4547 return -EIO;
4548}
4549
Bryan Schumakerae42c702010-10-21 16:33:17 -04004550static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
4551 struct nfs_fattr *fattr, struct nfs_fh *fh,
David Quigleyaa9c2662013-05-22 12:50:44 -04004552 struct nfs4_fs_locations *fs_loc, struct nfs4_label *label,
Trond Myklebust6926afd2012-01-07 13:22:46 -05004553 const struct nfs_server *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004554{
Trond Myklebustbca79472009-03-11 14:10:26 -04004555 int status;
4556 umode_t fmode = 0;
Bryan Schumakerae42c702010-10-21 16:33:17 -04004557 uint32_t type;
Trond Myklebustee7b75f2011-06-16 13:15:41 -04004558 int32_t err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004559
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004560 status = decode_attr_type(xdr, bitmap, &type);
4561 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004562 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004563 fattr->mode = 0;
4564 if (status != 0) {
4565 fattr->mode |= nfs_type2fmt[type];
4566 fattr->valid |= status;
4567 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004569 status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
4570 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004571 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004572 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004573
4574 status = decode_attr_size(xdr, bitmap, &fattr->size);
4575 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004576 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004577 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004578
4579 status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
4580 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004581 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004582 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004583
Trond Myklebustee7b75f2011-06-16 13:15:41 -04004584 err = 0;
4585 status = decode_attr_error(xdr, bitmap, &err);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004586 if (status < 0)
4587 goto xdr_error;
4588
4589 status = decode_attr_filehandle(xdr, bitmap, fh);
4590 if (status < 0)
4591 goto xdr_error;
4592
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004593 status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
4594 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004596 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004597
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05004598 status = decode_attr_fs_locations(xdr, bitmap, fs_loc);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004599 if (status < 0)
Trond Myklebust683b57b2006-06-09 09:34:22 -04004600 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004601 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004602
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004603 status = -EIO;
4604 if (unlikely(bitmap[0]))
4605 goto xdr_error;
4606
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004607 status = decode_attr_mode(xdr, bitmap, &fmode);
4608 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004610 if (status != 0) {
4611 fattr->mode |= fmode;
4612 fattr->valid |= status;
4613 }
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004614
4615 status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
4616 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004617 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004618 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004619
Trond Myklebust6926afd2012-01-07 13:22:46 -05004620 status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004621 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004622 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004623 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004624
Trond Myklebust6926afd2012-01-07 13:22:46 -05004625 status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004626 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004627 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004628 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004629
4630 status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
4631 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004632 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004633 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004634
4635 status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
4636 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004637 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004638 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004639
4640 status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
4641 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004643 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004644
4645 status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
4646 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004647 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004648 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004649
4650 status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
4651 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004652 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004653 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004654
Trond Myklebust28331a42011-04-27 13:47:52 -04004655 status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004656 if (status < 0)
Manoj Naik99baf622006-06-09 09:34:24 -04004657 goto xdr_error;
Trond Myklebust28331a42011-04-27 13:47:52 -04004658 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004659
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004660 status = -EIO;
4661 if (unlikely(bitmap[1]))
4662 goto xdr_error;
4663
Andy Adamson88034c32012-05-23 05:02:34 -04004664 status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold);
4665 if (status < 0)
4666 goto xdr_error;
4667
David Quigleyaa9c2662013-05-22 12:50:44 -04004668 if (label) {
4669 status = decode_attr_security_label(xdr, bitmap, label);
4670 if (status < 0)
4671 goto xdr_error;
4672 fattr->valid |= status;
4673 }
4674
Bryan Schumakerae42c702010-10-21 16:33:17 -04004675xdr_error:
4676 dprintk("%s: xdr returned %d\n", __func__, -status);
4677 return status;
4678}
4679
4680static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05004681 struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
David Quigleyaa9c2662013-05-22 12:50:44 -04004682 struct nfs4_label *label, const struct nfs_server *server)
Bryan Schumakerae42c702010-10-21 16:33:17 -04004683{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004684 unsigned int savep;
Bryan Schumakerae42c702010-10-21 16:33:17 -04004685 uint32_t attrlen,
Fred Isamandae100c2011-07-30 20:52:37 -04004686 bitmap[3] = {0};
Bryan Schumakerae42c702010-10-21 16:33:17 -04004687 int status;
4688
4689 status = decode_op_hdr(xdr, OP_GETATTR);
4690 if (status < 0)
4691 goto xdr_error;
4692
4693 status = decode_attr_bitmap(xdr, bitmap);
4694 if (status < 0)
4695 goto xdr_error;
4696
4697 status = decode_attr_length(xdr, &attrlen, &savep);
4698 if (status < 0)
4699 goto xdr_error;
4700
David Quigleyaa9c2662013-05-22 12:50:44 -04004701 status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc,
4702 label, server);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004703 if (status < 0)
4704 goto xdr_error;
4705
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004706 status = verify_attr_len(xdr, savep, attrlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004707xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004708 dprintk("%s: xdr returned %d\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004709 return status;
4710}
4711
David Quigleyaa9c2662013-05-22 12:50:44 -04004712static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr,
4713 struct nfs4_label *label, const struct nfs_server *server)
4714{
4715 return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server);
4716}
4717
Bryan Schumakerae42c702010-10-21 16:33:17 -04004718static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
Trond Myklebust6926afd2012-01-07 13:22:46 -05004719 const struct nfs_server *server)
Bryan Schumakerae42c702010-10-21 16:33:17 -04004720{
David Quigleyaa9c2662013-05-22 12:50:44 -04004721 return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004722}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004723
Andy Adamson504913f2010-10-20 00:17:57 -04004724/*
Jeff Layton3132e492016-08-10 15:58:24 -04004725 * Decode potentially multiple layout types.
Andy Adamson504913f2010-10-20 00:17:57 -04004726 */
Jeff Layton3132e492016-08-10 15:58:24 -04004727static int decode_pnfs_layout_types(struct xdr_stream *xdr,
Jeff Laytonca440c32016-09-15 14:40:49 -04004728 struct nfs_fsinfo *fsinfo)
Andy Adamson504913f2010-10-20 00:17:57 -04004729{
Trond Myklebustb8a8a0d2013-08-20 21:08:56 -04004730 __be32 *p;
Jeff Laytonca440c32016-09-15 14:40:49 -04004731 uint32_t i;
Andy Adamson504913f2010-10-20 00:17:57 -04004732
4733 p = xdr_inline_decode(xdr, 4);
4734 if (unlikely(!p))
4735 goto out_overflow;
Jeff Laytonca440c32016-09-15 14:40:49 -04004736 fsinfo->nlayouttypes = be32_to_cpup(p);
Andy Adamson504913f2010-10-20 00:17:57 -04004737
4738 /* pNFS is not supported by the underlying file system */
Jeff Laytonca440c32016-09-15 14:40:49 -04004739 if (fsinfo->nlayouttypes == 0)
Andy Adamson504913f2010-10-20 00:17:57 -04004740 return 0;
Andy Adamson504913f2010-10-20 00:17:57 -04004741
4742 /* Decode and set first layout type, move xdr->p past unused types */
Jeff Laytonca440c32016-09-15 14:40:49 -04004743 p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4);
Andy Adamson504913f2010-10-20 00:17:57 -04004744 if (unlikely(!p))
4745 goto out_overflow;
Jeff Laytonca440c32016-09-15 14:40:49 -04004746
4747 /* If we get too many, then just cap it at the max */
4748 if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) {
4749 printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n",
4750 __func__, fsinfo->nlayouttypes);
4751 fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES;
4752 }
4753
4754 for(i = 0; i < fsinfo->nlayouttypes; ++i)
4755 fsinfo->layouttype[i] = be32_to_cpup(p++);
Andy Adamson504913f2010-10-20 00:17:57 -04004756 return 0;
4757out_overflow:
4758 print_overflow_msg(__func__, xdr);
4759 return -EIO;
4760}
4761
4762/*
4763 * The type of file system exported.
4764 * Note we must ensure that layouttype is set in any non-error case.
4765 */
4766static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
Jeff Laytonca440c32016-09-15 14:40:49 -04004767 struct nfs_fsinfo *fsinfo)
Andy Adamson504913f2010-10-20 00:17:57 -04004768{
4769 int status = 0;
4770
4771 dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
4772 if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
4773 return -EIO;
4774 if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
Jeff Laytonca440c32016-09-15 14:40:49 -04004775 status = decode_pnfs_layout_types(xdr, fsinfo);
Andy Adamson504913f2010-10-20 00:17:57 -04004776 bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
Jeff Layton3132e492016-08-10 15:58:24 -04004777 }
Andy Adamson504913f2010-10-20 00:17:57 -04004778 return status;
4779}
4780
Fred Isamandae100c2011-07-30 20:52:37 -04004781/*
4782 * The prefered block size for layout directed io
4783 */
4784static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
4785 uint32_t *res)
4786{
4787 __be32 *p;
4788
4789 dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
4790 *res = 0;
4791 if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
4792 p = xdr_inline_decode(xdr, 4);
4793 if (unlikely(!p)) {
4794 print_overflow_msg(__func__, xdr);
4795 return -EIO;
4796 }
4797 *res = be32_to_cpup(p);
4798 bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
4799 }
4800 return 0;
4801}
4802
Peng Tao2a92ee92015-09-26 02:24:37 +08004803/*
4804 * The granularity of a CLONE operation.
4805 */
4806static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
4807 uint32_t *res)
4808{
4809 __be32 *p;
4810
4811 dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
4812 *res = 0;
4813 if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) {
4814 p = xdr_inline_decode(xdr, 4);
4815 if (unlikely(!p)) {
4816 print_overflow_msg(__func__, xdr);
4817 return -EIO;
4818 }
4819 *res = be32_to_cpup(p);
4820 bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE;
4821 }
4822 return 0;
4823}
4824
Linus Torvalds1da177e2005-04-16 15:20:36 -07004825static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
4826{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004827 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004828 uint32_t attrlen, bitmap[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004829 int status;
4830
4831 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4832 goto xdr_error;
4833 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4834 goto xdr_error;
4835 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4836 goto xdr_error;
4837
4838 fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
4839
4840 if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
4841 goto xdr_error;
4842 if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
4843 goto xdr_error;
4844 if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
4845 goto xdr_error;
4846 fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
4847 if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
4848 goto xdr_error;
4849 fsinfo->wtpref = fsinfo->wtmax;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004850
4851 status = -EIO;
4852 if (unlikely(bitmap[0]))
4853 goto xdr_error;
4854
Ricardo Labiaga55b6e772010-10-12 16:30:06 -07004855 status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
4856 if (status != 0)
4857 goto xdr_error;
Jeff Laytonca440c32016-09-15 14:40:49 -04004858 status = decode_attr_pnfstype(xdr, bitmap, fsinfo);
Andy Adamson504913f2010-10-20 00:17:57 -04004859 if (status != 0)
4860 goto xdr_error;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004861
4862 status = -EIO;
4863 if (unlikely(bitmap[1]))
4864 goto xdr_error;
4865
Fred Isamandae100c2011-07-30 20:52:37 -04004866 status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize);
4867 if (status)
4868 goto xdr_error;
Peng Tao2a92ee92015-09-26 02:24:37 +08004869 status = decode_attr_clone_blksize(xdr, bitmap, &fsinfo->clone_blksize);
4870 if (status)
4871 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004872
4873 status = verify_attr_len(xdr, savep, attrlen);
4874xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004875 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004876 return status;
4877}
4878
4879static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
4880{
Al Viro8687b632006-10-19 23:28:48 -07004881 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004882 uint32_t len;
4883 int status;
4884
Trond Myklebust99367812007-07-17 21:52:41 -04004885 /* Zero handle first to allow comparisons */
4886 memset(fh, 0, sizeof(*fh));
4887
Linus Torvalds1da177e2005-04-16 15:20:36 -07004888 status = decode_op_hdr(xdr, OP_GETFH);
4889 if (status)
4890 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004891
Benny Halevyc0eae662009-08-14 17:20:14 +03004892 p = xdr_inline_decode(xdr, 4);
4893 if (unlikely(!p))
4894 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004895 len = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004896 if (len > NFS4_FHSIZE)
4897 return -EIO;
4898 fh->size = len;
Benny Halevyc0eae662009-08-14 17:20:14 +03004899 p = xdr_inline_decode(xdr, len);
4900 if (unlikely(!p))
4901 goto out_overflow;
Benny Halevy99398d02009-08-14 17:20:05 +03004902 memcpy(fh->data, p, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004903 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004904out_overflow:
4905 print_overflow_msg(__func__, xdr);
4906 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907}
4908
4909static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4910{
4911 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004912
Linus Torvalds1da177e2005-04-16 15:20:36 -07004913 status = decode_op_hdr(xdr, OP_LINK);
4914 if (status)
4915 return status;
4916 return decode_change_info(xdr, cinfo);
4917}
4918
4919/*
4920 * We create the owner, so we know a proper owner.id length is 4.
4921 */
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004922static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004923{
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004924 uint64_t offset, length, clientid;
Al Viro8687b632006-10-19 23:28:48 -07004925 __be32 *p;
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004926 uint32_t namelen, type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004927
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004928 p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
Benny Halevyc0eae662009-08-14 17:20:14 +03004929 if (unlikely(!p))
4930 goto out_overflow;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004931 p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004932 p = xdr_decode_hyper(p, &length);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004933 type = be32_to_cpup(p++); /* 4 byte read */
4934 if (fl != NULL) { /* manipulate file lock */
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004935 fl->fl_start = (loff_t)offset;
4936 fl->fl_end = fl->fl_start + (loff_t)length - 1;
4937 if (length == ~(uint64_t)0)
4938 fl->fl_end = OFFSET_MAX;
4939 fl->fl_type = F_WRLCK;
4940 if (type & 1)
4941 fl->fl_type = F_RDLCK;
4942 fl->fl_pid = 0;
4943 }
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004944 p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
4945 namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */
4946 p = xdr_inline_decode(xdr, namelen); /* variable size field */
Benny Halevyc0eae662009-08-14 17:20:14 +03004947 if (likely(p))
4948 return -NFS4ERR_DENIED;
4949out_overflow:
4950 print_overflow_msg(__func__, xdr);
4951 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004952}
4953
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004954static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004955{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956 int status;
4957
4958 status = decode_op_hdr(xdr, OP_LOCK);
Trond Myklebustc1d51932008-04-07 13:20:54 -04004959 if (status == -EIO)
4960 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004961 if (status == 0) {
Trond Myklebust93b717f2016-05-16 17:42:43 -04004962 status = decode_lock_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03004963 if (unlikely(status))
4964 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004965 } else if (status == -NFS4ERR_DENIED)
Trond Myklebustc1d51932008-04-07 13:20:54 -04004966 status = decode_lock_denied(xdr, NULL);
4967 if (res->open_seqid != NULL)
4968 nfs_increment_open_seqid(status, res->open_seqid);
4969 nfs_increment_lock_seqid(status, res->lock_seqid);
4970out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07004971 return status;
4972}
4973
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004974static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004975{
4976 int status;
4977 status = decode_op_hdr(xdr, OP_LOCKT);
4978 if (status == -NFS4ERR_DENIED)
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004979 return decode_lock_denied(xdr, res->denied);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004980 return status;
4981}
4982
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004983static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004984{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985 int status;
4986
4987 status = decode_op_hdr(xdr, OP_LOCKU);
Trond Myklebustc1d51932008-04-07 13:20:54 -04004988 if (status != -EIO)
4989 nfs_increment_lock_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03004990 if (status == 0)
Trond Myklebust93b717f2016-05-16 17:42:43 -04004991 status = decode_lock_stateid(xdr, &res->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004992 return status;
4993}
4994
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04004995static int decode_release_lockowner(struct xdr_stream *xdr)
4996{
4997 return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
4998}
4999
Linus Torvalds1da177e2005-04-16 15:20:36 -07005000static int decode_lookup(struct xdr_stream *xdr)
5001{
5002 return decode_op_hdr(xdr, OP_LOOKUP);
5003}
5004
5005/* This is too sick! */
Trond Myklebust7d160a62015-09-05 19:06:57 -04005006static int decode_space_limit(struct xdr_stream *xdr,
5007 unsigned long *pagemod_limit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008{
Andy Adamson05d564f2008-12-23 16:06:15 -05005009 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005010 uint32_t limit_type, nblocks, blocksize;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005011 u64 maxsize = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005012
Benny Halevyc0eae662009-08-14 17:20:14 +03005013 p = xdr_inline_decode(xdr, 12);
5014 if (unlikely(!p))
5015 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005016 limit_type = be32_to_cpup(p++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017 switch (limit_type) {
Trond Myklebust7d160a62015-09-05 19:06:57 -04005018 case NFS4_LIMIT_SIZE:
5019 xdr_decode_hyper(p, &maxsize);
Andy Adamson05d564f2008-12-23 16:06:15 -05005020 break;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005021 case NFS4_LIMIT_BLOCKS:
Benny Halevy6f723f72009-08-14 17:19:37 +03005022 nblocks = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005023 blocksize = be32_to_cpup(p);
Trond Myklebust7d160a62015-09-05 19:06:57 -04005024 maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025 }
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03005026 maxsize >>= PAGE_SHIFT;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005027 *pagemod_limit = min_t(u64, maxsize, ULONG_MAX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005028 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005029out_overflow:
5030 print_overflow_msg(__func__, xdr);
5031 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005032}
5033
Trond Myklebust6ae37332015-01-30 14:21:14 -05005034static int decode_rw_delegation(struct xdr_stream *xdr,
5035 uint32_t delegation_type,
5036 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005037{
Andy Adamson05d564f2008-12-23 16:06:15 -05005038 __be32 *p;
Benny Halevy07d30432009-08-14 17:19:52 +03005039 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005040
Trond Myklebust93b717f2016-05-16 17:42:43 -04005041 status = decode_delegation_stateid(xdr, &res->delegation);
Benny Halevy07d30432009-08-14 17:19:52 +03005042 if (unlikely(status))
5043 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005044 p = xdr_inline_decode(xdr, 4);
5045 if (unlikely(!p))
5046 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005047 res->do_recall = be32_to_cpup(p);
Andy Adamson05d564f2008-12-23 16:06:15 -05005048
Linus Torvalds1da177e2005-04-16 15:20:36 -07005049 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05005050 case NFS4_OPEN_DELEGATE_READ:
5051 res->delegation_type = FMODE_READ;
5052 break;
5053 case NFS4_OPEN_DELEGATE_WRITE:
5054 res->delegation_type = FMODE_WRITE|FMODE_READ;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005055 if (decode_space_limit(xdr, &res->pagemod_limit) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056 return -EIO;
5057 }
David Howells7539bba2006-08-22 20:06:09 -04005058 return decode_ace(xdr, NULL, res->server->nfs_client);
Benny Halevyc0eae662009-08-14 17:20:14 +03005059out_overflow:
5060 print_overflow_msg(__func__, xdr);
5061 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005062}
5063
Trond Myklebust6ae37332015-01-30 14:21:14 -05005064static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
5065{
5066 __be32 *p;
5067 uint32_t why_no_delegation;
5068
5069 p = xdr_inline_decode(xdr, 4);
5070 if (unlikely(!p))
5071 goto out_overflow;
5072 why_no_delegation = be32_to_cpup(p);
5073 switch (why_no_delegation) {
5074 case WND4_CONTENTION:
5075 case WND4_RESOURCE:
5076 xdr_inline_decode(xdr, 4);
5077 /* Ignore for now */
5078 }
5079 return 0;
5080out_overflow:
5081 print_overflow_msg(__func__, xdr);
5082 return -EIO;
5083}
5084
5085static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
5086{
5087 __be32 *p;
5088 uint32_t delegation_type;
5089
5090 p = xdr_inline_decode(xdr, 4);
5091 if (unlikely(!p))
5092 goto out_overflow;
5093 delegation_type = be32_to_cpup(p);
5094 res->delegation_type = 0;
5095 switch (delegation_type) {
5096 case NFS4_OPEN_DELEGATE_NONE:
5097 return 0;
5098 case NFS4_OPEN_DELEGATE_READ:
5099 case NFS4_OPEN_DELEGATE_WRITE:
5100 return decode_rw_delegation(xdr, delegation_type, res);
5101 case NFS4_OPEN_DELEGATE_NONE_EXT:
5102 return decode_no_delegation(xdr, res);
5103 }
5104 return -EIO;
5105out_overflow:
5106 print_overflow_msg(__func__, xdr);
5107 return -EIO;
5108}
5109
Linus Torvalds1da177e2005-04-16 15:20:36 -07005110static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
5111{
Andy Adamson05d564f2008-12-23 16:06:15 -05005112 __be32 *p;
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005113 uint32_t savewords, bmlen, i;
Andy Adamson05d564f2008-12-23 16:06:15 -05005114 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005115
Trond Myklebustc7848f62013-12-04 17:39:23 -05005116 if (!__decode_op_hdr(xdr, OP_OPEN, &status))
5117 return status;
5118 nfs_increment_open_seqid(status, res->seqid);
5119 if (status)
5120 return status;
Trond Myklebust93b717f2016-05-16 17:42:43 -04005121 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005122 if (unlikely(status))
Andy Adamson05d564f2008-12-23 16:06:15 -05005123 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005124
Andy Adamson05d564f2008-12-23 16:06:15 -05005125 decode_change_info(xdr, &res->cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005126
Benny Halevyc0eae662009-08-14 17:20:14 +03005127 p = xdr_inline_decode(xdr, 8);
5128 if (unlikely(!p))
5129 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005130 res->rflags = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005131 bmlen = be32_to_cpup(p);
Andy Adamson05d564f2008-12-23 16:06:15 -05005132 if (bmlen > 10)
5133 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005134
Benny Halevyc0eae662009-08-14 17:20:14 +03005135 p = xdr_inline_decode(xdr, bmlen << 2);
5136 if (unlikely(!p))
5137 goto out_overflow;
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005138 savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
5139 for (i = 0; i < savewords; ++i)
Benny Halevy6f723f72009-08-14 17:19:37 +03005140 res->attrset[i] = be32_to_cpup(p++);
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005141 for (; i < NFS4_BITMAP_SIZE; i++)
5142 res->attrset[i] = 0;
5143
Linus Torvalds1da177e2005-04-16 15:20:36 -07005144 return decode_delegation(xdr, res);
5145xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07005146 dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005147 return -EIO;
Benny Halevyc0eae662009-08-14 17:20:14 +03005148out_overflow:
5149 print_overflow_msg(__func__, xdr);
5150 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005151}
5152
5153static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
5154{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005155 int status;
5156
Andy Adamson05d564f2008-12-23 16:06:15 -05005157 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
Trond Myklebustc1d51932008-04-07 13:20:54 -04005158 if (status != -EIO)
5159 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03005160 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005161 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005162 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005163}
5164
5165static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
5166{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167 int status;
5168
5169 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04005170 if (status != -EIO)
5171 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03005172 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005173 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005174 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005175}
5176
5177static int decode_putfh(struct xdr_stream *xdr)
5178{
5179 return decode_op_hdr(xdr, OP_PUTFH);
5180}
5181
5182static int decode_putrootfh(struct xdr_stream *xdr)
5183{
5184 return decode_op_hdr(xdr, OP_PUTROOTFH);
5185}
5186
Anna Schumaker9137bdf2014-05-06 09:12:25 -04005187static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
5188 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005189{
Al Viro8687b632006-10-19 23:28:48 -07005190 __be32 *p;
Trond Myklebust64bd5772012-06-20 22:35:05 -04005191 uint32_t count, eof, recvd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005192 int status;
5193
5194 status = decode_op_hdr(xdr, OP_READ);
5195 if (status)
5196 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005197 p = xdr_inline_decode(xdr, 8);
5198 if (unlikely(!p))
5199 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005200 eof = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005201 count = be32_to_cpup(p);
Trond Myklebust64bd5772012-06-20 22:35:05 -04005202 recvd = xdr_read_pages(xdr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005203 if (count > recvd) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005204 dprintk("NFS: server cheating in read reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07005205 "count %u > recvd %u\n", count, recvd);
5206 count = recvd;
5207 eof = 0;
5208 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005209 res->eof = eof;
5210 res->count = count;
5211 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005212out_overflow:
5213 print_overflow_msg(__func__, xdr);
5214 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005215}
5216
5217static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
5218{
Chuck Leverbcecff72007-10-26 13:32:03 -04005219 int status;
Chuck Levercd937102012-03-02 17:14:31 -05005220 __be32 verf[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005221
5222 status = decode_op_hdr(xdr, OP_READDIR);
Benny Halevydb942bb2009-08-14 17:19:56 +03005223 if (!status)
5224 status = decode_verifier(xdr, readdir->verifier.data);
5225 if (unlikely(status))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005226 return status;
Chuck Levercd937102012-03-02 17:14:31 -05005227 memcpy(verf, readdir->verifier.data, sizeof(verf));
Fred Isaman44109242008-04-02 15:21:15 +03005228 dprintk("%s: verifier = %08x:%08x\n",
Chuck Levercd937102012-03-02 17:14:31 -05005229 __func__, verf[0], verf[1]);
Trond Myklebust64bd5772012-06-20 22:35:05 -04005230 return xdr_read_pages(xdr, xdr->buf->page_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005231}
5232
5233static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
5234{
5235 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
Chuck Leverbcecff72007-10-26 13:32:03 -04005236 u32 len, recvd;
Al Viro8687b632006-10-19 23:28:48 -07005237 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238 int status;
5239
5240 status = decode_op_hdr(xdr, OP_READLINK);
5241 if (status)
5242 return status;
5243
5244 /* Convert length of symlink */
Benny Halevyc0eae662009-08-14 17:20:14 +03005245 p = xdr_inline_decode(xdr, 4);
5246 if (unlikely(!p))
5247 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005248 len = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005249 if (len >= rcvbuf->page_len || len <= 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005250 dprintk("nfs: server returned giant symlink!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005251 return -ENAMETOOLONG;
5252 }
Trond Myklebust64bd5772012-06-20 22:35:05 -04005253 recvd = xdr_read_pages(xdr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254 if (recvd < len) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005255 dprintk("NFS: server cheating in readlink reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07005256 "count %u > recvd %u\n", len, recvd);
5257 return -EIO;
5258 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 /*
5260 * The XDR encode routine has set things up so that
5261 * the link text will be copied directly into the
5262 * buffer. We just have to do overflow-checking,
5263 * and and null-terminate the text (the VFS expects
5264 * null-termination).
5265 */
Chuck Leverb4687da2010-09-21 16:55:48 -04005266 xdr_terminate_string(rcvbuf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005267 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005268out_overflow:
5269 print_overflow_msg(__func__, xdr);
5270 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271}
5272
5273static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
5274{
5275 int status;
5276
5277 status = decode_op_hdr(xdr, OP_REMOVE);
5278 if (status)
5279 goto out;
5280 status = decode_change_info(xdr, cinfo);
5281out:
5282 return status;
5283}
5284
5285static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
5286 struct nfs4_change_info *new_cinfo)
5287{
5288 int status;
5289
5290 status = decode_op_hdr(xdr, OP_RENAME);
5291 if (status)
5292 goto out;
5293 if ((status = decode_change_info(xdr, old_cinfo)))
5294 goto out;
5295 status = decode_change_info(xdr, new_cinfo);
5296out:
5297 return status;
5298}
5299
5300static int decode_renew(struct xdr_stream *xdr)
5301{
5302 return decode_op_hdr(xdr, OP_RENEW);
5303}
5304
Trond Myklebust56ae19f2005-10-27 22:12:40 -04005305static int
5306decode_restorefh(struct xdr_stream *xdr)
5307{
5308 return decode_op_hdr(xdr, OP_RESTOREFH);
5309}
5310
J. Bruce Fields029d1052005-06-22 17:16:22 +00005311static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
Andy Adamsonbf118a32011-12-07 11:55:27 -05005312 struct nfs_getaclres *res)
J. Bruce Fields029d1052005-06-22 17:16:22 +00005313{
Trond Myklebust256e48b2012-06-21 11:18:13 -04005314 unsigned int savep;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005315 uint32_t attrlen,
Fred Isamandae100c2011-07-30 20:52:37 -04005316 bitmap[3] = {0};
J. Bruce Fields029d1052005-06-22 17:16:22 +00005317 int status;
Trond Myklebustcff298c2012-08-14 17:14:17 -04005318 unsigned int pg_offset;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005319
Andy Adamsonbf118a32011-12-07 11:55:27 -05005320 res->acl_len = 0;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005321 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
5322 goto out;
Sachin Prabhu5a006892012-04-17 14:35:39 +01005323
Trond Myklebust519d3952012-08-14 17:30:10 -04005324 xdr_enter_page(xdr, xdr->buf->page_len);
5325
Trond Myklebustcff298c2012-08-14 17:14:17 -04005326 /* Calculate the offset of the page data */
5327 pg_offset = xdr->buf->head[0].iov_len;
Sachin Prabhu5a006892012-04-17 14:35:39 +01005328
J. Bruce Fields029d1052005-06-22 17:16:22 +00005329 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
5330 goto out;
5331 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
5332 goto out;
5333
5334 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
5335 return -EIO;
5336 if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
J. Bruce Fields029d1052005-06-22 17:16:22 +00005337
Andy Adamsonbf118a32011-12-07 11:55:27 -05005338 /* The bitmap (xdr len + bitmaps) and the attr xdr len words
5339 * are stored with the acl data to handle the problem of
5340 * variable length bitmaps.*/
Trond Myklebustcff298c2012-08-14 17:14:17 -04005341 res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
Trond Myklebust519d3952012-08-14 17:30:10 -04005342 res->acl_len = attrlen;
Trond Myklebust1f1ea6c2012-08-26 11:44:43 -07005343
5344 /* Check for receive buffer overflow */
5345 if (res->acl_len > (xdr->nwords << 2) ||
5346 res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
5347 res->acl_flags |= NFS4_ACL_TRUNC;
Trond Myklebust519d3952012-08-14 17:30:10 -04005348 dprintk("NFS: acl reply: attrlen %u > page_len %u\n",
Trond Myklebustcff298c2012-08-14 17:14:17 -04005349 attrlen, xdr->nwords << 2);
J. Bruce Fields029d1052005-06-22 17:16:22 +00005350 }
J. Bruce Fields8c233cf2005-10-13 16:54:27 -04005351 } else
5352 status = -EOPNOTSUPP;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005353
5354out:
5355 return status;
5356}
5357
Linus Torvalds1da177e2005-04-16 15:20:36 -07005358static int
5359decode_savefh(struct xdr_stream *xdr)
5360{
5361 return decode_op_hdr(xdr, OP_SAVEFH);
5362}
5363
Benny Halevy9e9ecc02009-04-01 09:22:00 -04005364static int decode_setattr(struct xdr_stream *xdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005365{
Al Viro8687b632006-10-19 23:28:48 -07005366 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005367 uint32_t bmlen;
5368 int status;
5369
Linus Torvalds1da177e2005-04-16 15:20:36 -07005370 status = decode_op_hdr(xdr, OP_SETATTR);
5371 if (status)
5372 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005373 p = xdr_inline_decode(xdr, 4);
5374 if (unlikely(!p))
5375 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005376 bmlen = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005377 p = xdr_inline_decode(xdr, bmlen << 2);
5378 if (likely(p))
5379 return 0;
5380out_overflow:
5381 print_overflow_msg(__func__, xdr);
5382 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005383}
5384
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04005385static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005386{
Al Viro8687b632006-10-19 23:28:48 -07005387 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005388 uint32_t opnum;
5389 int32_t nfserr;
5390
Benny Halevyc0eae662009-08-14 17:20:14 +03005391 p = xdr_inline_decode(xdr, 8);
5392 if (unlikely(!p))
5393 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005394 opnum = be32_to_cpup(p++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005395 if (opnum != OP_SETCLIENTID) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005396 dprintk("nfs: decode_setclientid: Server returned operation"
Andy Adamson6c0195a2008-12-23 16:06:15 -05005397 " %d\n", opnum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398 return -EIO;
5399 }
Benny Halevycccddf42009-08-14 17:20:19 +03005400 nfserr = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005401 if (nfserr == NFS_OK) {
Benny Halevyc0eae662009-08-14 17:20:14 +03005402 p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
5403 if (unlikely(!p))
5404 goto out_overflow;
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04005405 p = xdr_decode_hyper(p, &res->clientid);
5406 memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005407 } else if (nfserr == NFSERR_CLID_INUSE) {
5408 uint32_t len;
5409
5410 /* skip netid string */
Benny Halevyc0eae662009-08-14 17:20:14 +03005411 p = xdr_inline_decode(xdr, 4);
5412 if (unlikely(!p))
5413 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005414 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005415 p = xdr_inline_decode(xdr, len);
5416 if (unlikely(!p))
5417 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005418
5419 /* skip uaddr string */
Benny Halevyc0eae662009-08-14 17:20:14 +03005420 p = xdr_inline_decode(xdr, 4);
5421 if (unlikely(!p))
5422 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005423 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005424 p = xdr_inline_decode(xdr, len);
5425 if (unlikely(!p))
5426 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005427 return -NFSERR_CLID_INUSE;
5428 } else
Benny Halevy856dff32008-03-31 17:39:06 +03005429 return nfs4_stat_to_errno(nfserr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005430
5431 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005432out_overflow:
5433 print_overflow_msg(__func__, xdr);
5434 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005435}
5436
5437static int decode_setclientid_confirm(struct xdr_stream *xdr)
5438{
5439 return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
5440}
5441
Anna Schumaker9137bdf2014-05-06 09:12:25 -04005442static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005443{
Al Viro8687b632006-10-19 23:28:48 -07005444 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005445 int status;
5446
5447 status = decode_op_hdr(xdr, OP_WRITE);
5448 if (status)
5449 return status;
5450
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04005451 p = xdr_inline_decode(xdr, 8);
Benny Halevyc0eae662009-08-14 17:20:14 +03005452 if (unlikely(!p))
5453 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005454 res->count = be32_to_cpup(p++);
5455 res->verf->committed = be32_to_cpup(p++);
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04005456 return decode_write_verifier(xdr, &res->verf->verifier);
Benny Halevyc0eae662009-08-14 17:20:14 +03005457out_overflow:
5458 print_overflow_msg(__func__, xdr);
5459 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460}
5461
5462static int decode_delegreturn(struct xdr_stream *xdr)
5463{
5464 return decode_op_hdr(xdr, OP_DELEGRETURN);
5465}
5466
Chuck Leverfb15b262013-03-16 15:54:34 -04005467static int decode_secinfo_gss(struct xdr_stream *xdr,
5468 struct nfs4_secinfo4 *flavor)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005469{
Chuck Leverfb15b262013-03-16 15:54:34 -04005470 u32 oid_len;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005471 __be32 *p;
5472
5473 p = xdr_inline_decode(xdr, 4);
5474 if (unlikely(!p))
5475 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005476 oid_len = be32_to_cpup(p);
5477 if (oid_len > GSS_OID_MAX_LEN)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005478 goto out_err;
5479
Chuck Leverfb15b262013-03-16 15:54:34 -04005480 p = xdr_inline_decode(xdr, oid_len);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005481 if (unlikely(!p))
5482 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005483 memcpy(flavor->flavor_info.oid.data, p, oid_len);
5484 flavor->flavor_info.oid.len = oid_len;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005485
5486 p = xdr_inline_decode(xdr, 8);
5487 if (unlikely(!p))
5488 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005489 flavor->flavor_info.qop = be32_to_cpup(p++);
5490 flavor->flavor_info.service = be32_to_cpup(p);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005491
5492 return 0;
5493
5494out_overflow:
5495 print_overflow_msg(__func__, xdr);
5496 return -EIO;
5497out_err:
5498 return -EINVAL;
5499}
5500
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005501static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005502{
Chuck Leverfb15b262013-03-16 15:54:34 -04005503 struct nfs4_secinfo4 *sec_flavor;
5504 unsigned int i, num_flavors;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005505 int status;
5506 __be32 *p;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005507
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005508 p = xdr_inline_decode(xdr, 4);
5509 if (unlikely(!p))
5510 goto out_overflow;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005511
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005512 res->flavors->num_flavors = 0;
5513 num_flavors = be32_to_cpup(p);
5514
5515 for (i = 0; i < num_flavors; i++) {
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005516 sec_flavor = &res->flavors->flavors[i];
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005517 if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005518 break;
5519
5520 p = xdr_inline_decode(xdr, 4);
5521 if (unlikely(!p))
5522 goto out_overflow;
5523 sec_flavor->flavor = be32_to_cpup(p);
5524
5525 if (sec_flavor->flavor == RPC_AUTH_GSS) {
Bryan Schumaker613e9012011-04-27 15:28:44 -04005526 status = decode_secinfo_gss(xdr, sec_flavor);
5527 if (status)
5528 goto out;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005529 }
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005530 res->flavors->num_flavors++;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005531 }
5532
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005533 status = 0;
Bryan Schumaker613e9012011-04-27 15:28:44 -04005534out:
5535 return status;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005536out_overflow:
5537 print_overflow_msg(__func__, xdr);
5538 return -EIO;
5539}
5540
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005541static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
5542{
5543 int status = decode_op_hdr(xdr, OP_SECINFO);
5544 if (status)
5545 return status;
5546 return decode_secinfo_common(xdr, res);
5547}
5548
Benny Halevy99fe60d2009-04-01 09:22:29 -04005549#if defined(CONFIG_NFS_V4_1)
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005550static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
5551{
5552 int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME);
5553 if (status)
5554 return status;
5555 return decode_secinfo_common(xdr, res);
5556}
5557
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005558static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
5559{
5560 __be32 *p;
5561 uint32_t bitmap_words;
5562 unsigned int i;
5563
5564 p = xdr_inline_decode(xdr, 4);
5565 bitmap_words = be32_to_cpup(p++);
5566 if (bitmap_words > NFS4_OP_MAP_NUM_WORDS)
5567 return -EIO;
5568 p = xdr_inline_decode(xdr, 4 * bitmap_words);
5569 for (i = 0; i < bitmap_words; i++)
5570 op_map->u.words[i] = be32_to_cpup(p++);
5571
5572 return 0;
5573}
5574
Benny Halevy99fe60d2009-04-01 09:22:29 -04005575static int decode_exchange_id(struct xdr_stream *xdr,
5576 struct nfs41_exchange_id_res *res)
5577{
5578 __be32 *p;
5579 uint32_t dummy;
Benny Halevy2460ba52009-08-14 17:20:10 +03005580 char *dummy_str;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005581 int status;
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005582 uint32_t impl_id_count;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005583
5584 status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
5585 if (status)
5586 return status;
5587
Benny Halevyc0eae662009-08-14 17:20:14 +03005588 p = xdr_inline_decode(xdr, 8);
5589 if (unlikely(!p))
5590 goto out_overflow;
Trond Myklebust32b01312012-05-26 13:41:04 -04005591 xdr_decode_hyper(p, &res->clientid);
Benny Halevyc0eae662009-08-14 17:20:14 +03005592 p = xdr_inline_decode(xdr, 12);
5593 if (unlikely(!p))
5594 goto out_overflow;
Trond Myklebust32b01312012-05-26 13:41:04 -04005595 res->seqid = be32_to_cpup(p++);
5596 res->flags = be32_to_cpup(p++);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005597
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005598 res->state_protect.how = be32_to_cpup(p);
5599 switch (res->state_protect.how) {
5600 case SP4_NONE:
5601 break;
5602 case SP4_MACH_CRED:
5603 status = decode_op_map(xdr, &res->state_protect.enforce);
5604 if (status)
5605 return status;
5606 status = decode_op_map(xdr, &res->state_protect.allow);
5607 if (status)
5608 return status;
5609 break;
5610 default:
5611 WARN_ON_ONCE(1);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005612 return -EIO;
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005613 }
Benny Halevy99fe60d2009-04-01 09:22:29 -04005614
Chuck Leveracdeb692012-05-21 22:46:16 -04005615 /* server_owner4.so_minor_id */
Benny Halevyc0eae662009-08-14 17:20:14 +03005616 p = xdr_inline_decode(xdr, 8);
5617 if (unlikely(!p))
5618 goto out_overflow;
Chuck Leveracdeb692012-05-21 22:46:16 -04005619 p = xdr_decode_hyper(p, &res->server_owner->minor_id);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005620
Chuck Leveracdeb692012-05-21 22:46:16 -04005621 /* server_owner4.so_major_id */
Benny Halevy2460ba52009-08-14 17:20:10 +03005622 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5623 if (unlikely(status))
5624 return status;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005625 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5626 return -EIO;
Chuck Leveracdeb692012-05-21 22:46:16 -04005627 memcpy(res->server_owner->major_id, dummy_str, dummy);
5628 res->server_owner->major_id_sz = dummy;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005629
Chuck Leveracdeb692012-05-21 22:46:16 -04005630 /* server_scope4 */
5631 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5632 if (unlikely(status))
5633 return status;
5634 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5635 return -EIO;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005636 memcpy(res->server_scope->server_scope, dummy_str, dummy);
5637 res->server_scope->server_scope_sz = dummy;
5638
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005639 /* Implementation Id */
5640 p = xdr_inline_decode(xdr, 4);
5641 if (unlikely(!p))
5642 goto out_overflow;
5643 impl_id_count = be32_to_cpup(p++);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005644
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005645 if (impl_id_count) {
5646 /* nii_domain */
5647 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5648 if (unlikely(status))
5649 return status;
5650 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5651 return -EIO;
5652 memcpy(res->impl_id->domain, dummy_str, dummy);
5653
5654 /* nii_name */
5655 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5656 if (unlikely(status))
5657 return status;
5658 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5659 return -EIO;
5660 memcpy(res->impl_id->name, dummy_str, dummy);
5661
5662 /* nii_date */
5663 p = xdr_inline_decode(xdr, 12);
5664 if (unlikely(!p))
5665 goto out_overflow;
5666 p = xdr_decode_hyper(p, &res->impl_id->date.seconds);
5667 res->impl_id->date.nseconds = be32_to_cpup(p);
5668
5669 /* if there's more than one entry, ignore the rest */
5670 }
Benny Halevy99fe60d2009-04-01 09:22:29 -04005671 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005672out_overflow:
5673 print_overflow_msg(__func__, xdr);
5674 return -EIO;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005675}
Andy Adamsonfc931582009-04-01 09:22:31 -04005676
5677static int decode_chan_attrs(struct xdr_stream *xdr,
5678 struct nfs4_channel_attrs *attrs)
5679{
5680 __be32 *p;
Benny Halevyc9c30dd2011-06-11 17:08:39 -04005681 u32 nr_attrs, val;
Andy Adamsonfc931582009-04-01 09:22:31 -04005682
Benny Halevyc0eae662009-08-14 17:20:14 +03005683 p = xdr_inline_decode(xdr, 28);
5684 if (unlikely(!p))
5685 goto out_overflow;
Benny Halevyc9c30dd2011-06-11 17:08:39 -04005686 val = be32_to_cpup(p++); /* headerpadsz */
5687 if (val)
5688 return -EINVAL; /* no support for header padding yet */
Benny Halevy6f723f72009-08-14 17:19:37 +03005689 attrs->max_rqst_sz = be32_to_cpup(p++);
5690 attrs->max_resp_sz = be32_to_cpup(p++);
5691 attrs->max_resp_sz_cached = be32_to_cpup(p++);
5692 attrs->max_ops = be32_to_cpup(p++);
5693 attrs->max_reqs = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005694 nr_attrs = be32_to_cpup(p);
Andy Adamsonfc931582009-04-01 09:22:31 -04005695 if (unlikely(nr_attrs > 1)) {
Weston Andros Adamsona0308892012-01-26 13:32:23 -05005696 printk(KERN_WARNING "NFS: %s: Invalid rdma channel attrs "
5697 "count %u\n", __func__, nr_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005698 return -EINVAL;
5699 }
Benny Halevyc0eae662009-08-14 17:20:14 +03005700 if (nr_attrs == 1) {
5701 p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
5702 if (unlikely(!p))
5703 goto out_overflow;
5704 }
Andy Adamsonfc931582009-04-01 09:22:31 -04005705 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005706out_overflow:
5707 print_overflow_msg(__func__, xdr);
5708 return -EIO;
Andy Adamsonfc931582009-04-01 09:22:31 -04005709}
5710
Benny Halevye78291e2009-08-14 17:20:00 +03005711static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
5712{
5713 return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
Andy Adamsonfc931582009-04-01 09:22:31 -04005714}
5715
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04005716static int decode_bind_conn_to_session(struct xdr_stream *xdr,
5717 struct nfs41_bind_conn_to_session_res *res)
5718{
5719 __be32 *p;
5720 int status;
5721
5722 status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
5723 if (!status)
Trond Myklebust71a097c2015-02-18 09:27:18 -08005724 status = decode_sessionid(xdr, &res->sessionid);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04005725 if (unlikely(status))
5726 return status;
5727
5728 /* dir flags, rdma mode bool */
5729 p = xdr_inline_decode(xdr, 8);
5730 if (unlikely(!p))
5731 goto out_overflow;
5732
5733 res->dir = be32_to_cpup(p++);
5734 if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH)
5735 return -EIO;
5736 if (be32_to_cpup(p) == 0)
5737 res->use_conn_in_rdma_mode = false;
5738 else
5739 res->use_conn_in_rdma_mode = true;
5740
5741 return 0;
5742out_overflow:
5743 print_overflow_msg(__func__, xdr);
5744 return -EIO;
5745}
5746
Andy Adamsonfc931582009-04-01 09:22:31 -04005747static int decode_create_session(struct xdr_stream *xdr,
5748 struct nfs41_create_session_res *res)
5749{
5750 __be32 *p;
5751 int status;
Andy Adamsonfc931582009-04-01 09:22:31 -04005752
5753 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
Benny Halevye78291e2009-08-14 17:20:00 +03005754 if (!status)
Trond Myklebust79969dd2015-02-18 11:30:18 -08005755 status = decode_sessionid(xdr, &res->sessionid);
Benny Halevye78291e2009-08-14 17:20:00 +03005756 if (unlikely(status))
Andy Adamsonfc931582009-04-01 09:22:31 -04005757 return status;
5758
Andy Adamsonfc931582009-04-01 09:22:31 -04005759 /* seqid, flags */
Benny Halevyc0eae662009-08-14 17:20:14 +03005760 p = xdr_inline_decode(xdr, 8);
5761 if (unlikely(!p))
5762 goto out_overflow;
Trond Myklebust79969dd2015-02-18 11:30:18 -08005763 res->seqid = be32_to_cpup(p++);
5764 res->flags = be32_to_cpup(p);
Andy Adamsonfc931582009-04-01 09:22:31 -04005765
5766 /* Channel attributes */
Trond Myklebust79969dd2015-02-18 11:30:18 -08005767 status = decode_chan_attrs(xdr, &res->fc_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005768 if (!status)
Trond Myklebust79969dd2015-02-18 11:30:18 -08005769 status = decode_chan_attrs(xdr, &res->bc_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005770 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005771out_overflow:
5772 print_overflow_msg(__func__, xdr);
5773 return -EIO;
Andy Adamsonfc931582009-04-01 09:22:31 -04005774}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04005775
5776static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
5777{
5778 return decode_op_hdr(xdr, OP_DESTROY_SESSION);
5779}
Ricardo Labiaga180197532009-12-05 16:08:40 -05005780
Trond Myklebust66245532012-05-25 17:18:09 -04005781static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy)
5782{
5783 return decode_op_hdr(xdr, OP_DESTROY_CLIENTID);
5784}
5785
Ricardo Labiaga180197532009-12-05 16:08:40 -05005786static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
5787{
5788 return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
5789}
Benny Halevy99fe60d2009-04-01 09:22:29 -04005790#endif /* CONFIG_NFS_V4_1 */
5791
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005792static int decode_sequence(struct xdr_stream *xdr,
5793 struct nfs4_sequence_res *res,
5794 struct rpc_rqst *rqstp)
5795{
5796#if defined(CONFIG_NFS_V4_1)
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005797 struct nfs4_session *session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005798 struct nfs4_sessionid id;
5799 u32 dummy;
5800 int status;
5801 __be32 *p;
5802
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005803 if (res->sr_slot == NULL)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005804 return 0;
Chuck Lever3bd23842013-08-09 12:49:19 -04005805 if (!res->sr_slot->table->session)
5806 return 0;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005807
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005808 status = decode_op_hdr(xdr, OP_SEQUENCE);
Benny Halevye78291e2009-08-14 17:20:00 +03005809 if (!status)
5810 status = decode_sessionid(xdr, &id);
5811 if (unlikely(status))
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005812 goto out_err;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005813
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005814 /*
5815 * If the server returns different values for sessionID, slotID or
5816 * sequence number, the server is looney tunes.
5817 */
Trond Myklebustfdcb4572010-02-08 09:32:40 -05005818 status = -EREMOTEIO;
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005819 session = res->sr_slot->table->session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005820
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005821 if (memcmp(id.data, session->sess_id.data,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005822 NFS4_MAX_SESSIONID_LEN)) {
5823 dprintk("%s Invalid session id\n", __func__);
5824 goto out_err;
5825 }
Benny Halevye78291e2009-08-14 17:20:00 +03005826
Benny Halevyc0eae662009-08-14 17:20:14 +03005827 p = xdr_inline_decode(xdr, 20);
5828 if (unlikely(!p))
5829 goto out_overflow;
Benny Halevye78291e2009-08-14 17:20:00 +03005830
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005831 /* seqid */
Benny Halevy6f723f72009-08-14 17:19:37 +03005832 dummy = be32_to_cpup(p++);
Benny Halevydfb4f3092010-09-24 09:17:01 -04005833 if (dummy != res->sr_slot->seq_nr) {
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005834 dprintk("%s Invalid sequence number\n", __func__);
5835 goto out_err;
5836 }
5837 /* slot id */
Benny Halevy6f723f72009-08-14 17:19:37 +03005838 dummy = be32_to_cpup(p++);
Trond Myklebustdf2fabf2012-11-16 12:45:06 -05005839 if (dummy != res->sr_slot->slot_nr) {
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005840 dprintk("%s Invalid slot id\n", __func__);
5841 goto out_err;
5842 }
Trond Myklebustda0507b2012-11-20 18:10:30 -05005843 /* highest slot id */
5844 res->sr_highest_slotid = be32_to_cpup(p++);
Trond Myklebust464ee9f2012-11-20 12:49:27 -05005845 /* target highest slot id */
5846 res->sr_target_highest_slotid = be32_to_cpup(p++);
Alexandros Batsakis0629e372009-12-05 13:46:14 -05005847 /* result flags */
5848 res->sr_status_flags = be32_to_cpup(p);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005849 status = 0;
5850out_err:
5851 res->sr_status = status;
5852 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005853out_overflow:
5854 print_overflow_msg(__func__, xdr);
5855 status = -EIO;
5856 goto out_err;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005857#else /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005858 return 0;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005859#endif /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005860}
5861
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005862#if defined(CONFIG_NFS_V4_1)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005863static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
5864{
5865 stateid->type = NFS4_LAYOUT_STATEID_TYPE;
5866 return decode_stateid(xdr, stateid);
5867}
5868
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005869static int decode_getdeviceinfo(struct xdr_stream *xdr,
Trond Myklebust4e590802015-03-09 14:01:25 -04005870 struct nfs4_getdeviceinfo_res *res)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005871{
Trond Myklebust4e590802015-03-09 14:01:25 -04005872 struct pnfs_device *pdev = res->pdev;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005873 __be32 *p;
5874 uint32_t len, type;
5875 int status;
5876
5877 status = decode_op_hdr(xdr, OP_GETDEVICEINFO);
5878 if (status) {
5879 if (status == -ETOOSMALL) {
5880 p = xdr_inline_decode(xdr, 4);
5881 if (unlikely(!p))
5882 goto out_overflow;
5883 pdev->mincount = be32_to_cpup(p);
5884 dprintk("%s: Min count too small. mincnt = %u\n",
5885 __func__, pdev->mincount);
5886 }
5887 return status;
5888 }
5889
5890 p = xdr_inline_decode(xdr, 8);
5891 if (unlikely(!p))
5892 goto out_overflow;
5893 type = be32_to_cpup(p++);
5894 if (type != pdev->layout_type) {
5895 dprintk("%s: layout mismatch req: %u pdev: %u\n",
5896 __func__, pdev->layout_type, type);
5897 return -EINVAL;
5898 }
5899 /*
5900 * Get the length of the opaque device_addr4. xdr_read_pages places
5901 * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages)
5902 * and places the remaining xdr data in xdr_buf->tail
5903 */
5904 pdev->mincount = be32_to_cpup(p);
Trond Myklebust13fe4ba2012-08-01 14:21:12 -04005905 if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount)
5906 goto out_overflow;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005907
5908 /* Parse notification bitmap, verifying that it is zero. */
5909 p = xdr_inline_decode(xdr, 4);
5910 if (unlikely(!p))
5911 goto out_overflow;
5912 len = be32_to_cpup(p);
5913 if (len) {
Chuck Leveread00592010-12-14 14:58:21 +00005914 uint32_t i;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005915
5916 p = xdr_inline_decode(xdr, 4 * len);
5917 if (unlikely(!p))
5918 goto out_overflow;
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07005919
Trond Myklebust4e590802015-03-09 14:01:25 -04005920 res->notification = be32_to_cpup(p++);
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07005921 for (i = 1; i < len; i++) {
5922 if (be32_to_cpup(p++)) {
5923 dprintk("%s: unsupported notification\n",
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005924 __func__);
5925 return -EIO;
5926 }
5927 }
5928 }
5929 return 0;
5930out_overflow:
5931 print_overflow_msg(__func__, xdr);
5932 return -EIO;
5933}
5934
5935static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
5936 struct nfs4_layoutget_res *res)
5937{
5938 __be32 *p;
5939 int status;
5940 u32 layout_count;
Trond Myklebust64bd5772012-06-20 22:35:05 -04005941 u32 recvd;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005942
5943 status = decode_op_hdr(xdr, OP_LAYOUTGET);
5944 if (status)
5945 return status;
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005946 p = xdr_inline_decode(xdr, 4);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005947 if (unlikely(!p))
5948 goto out_overflow;
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005949 res->return_on_close = be32_to_cpup(p);
Trond Myklebust93b717f2016-05-16 17:42:43 -04005950 decode_layout_stateid(xdr, &res->stateid);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005951 p = xdr_inline_decode(xdr, 4);
5952 if (unlikely(!p))
5953 goto out_overflow;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005954 layout_count = be32_to_cpup(p);
5955 if (!layout_count) {
5956 dprintk("%s: server responded with empty layout array\n",
5957 __func__);
5958 return -EINVAL;
5959 }
5960
Weston Andros Adamson35124a02011-03-24 16:48:21 -04005961 p = xdr_inline_decode(xdr, 28);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005962 if (unlikely(!p))
5963 goto out_overflow;
5964 p = xdr_decode_hyper(p, &res->range.offset);
5965 p = xdr_decode_hyper(p, &res->range.length);
5966 res->range.iomode = be32_to_cpup(p++);
5967 res->type = be32_to_cpup(p++);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04005968 res->layoutp->len = be32_to_cpup(p);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005969
5970 dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
5971 __func__,
5972 (unsigned long)res->range.offset,
5973 (unsigned long)res->range.length,
5974 res->range.iomode,
5975 res->type,
Weston Andros Adamson35124a02011-03-24 16:48:21 -04005976 res->layoutp->len);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005977
Trond Myklebust64bd5772012-06-20 22:35:05 -04005978 recvd = xdr_read_pages(xdr, res->layoutp->len);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04005979 if (res->layoutp->len > recvd) {
5980 dprintk("NFS: server cheating in layoutget reply: "
5981 "layout len %u > recvd %u\n",
5982 res->layoutp->len, recvd);
5983 return -EINVAL;
5984 }
5985
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005986 if (layout_count > 1) {
5987 /* We only handle a length one array at the moment. Any
5988 * further entries are just ignored. Note that this means
5989 * the client may see a response that is less than the
5990 * minimum it requested.
5991 */
5992 dprintk("%s: server responded with %d layouts, dropping tail\n",
5993 __func__, layout_count);
5994 }
5995
5996 return 0;
5997out_overflow:
5998 print_overflow_msg(__func__, xdr);
5999 return -EIO;
6000}
Andy Adamson863a3c62011-03-23 13:27:54 +00006001
Benny Halevycbe82602011-05-22 19:52:37 +03006002static int decode_layoutreturn(struct xdr_stream *xdr,
6003 struct nfs4_layoutreturn_res *res)
6004{
6005 __be32 *p;
6006 int status;
6007
6008 status = decode_op_hdr(xdr, OP_LAYOUTRETURN);
6009 if (status)
6010 return status;
6011 p = xdr_inline_decode(xdr, 4);
6012 if (unlikely(!p))
6013 goto out_overflow;
6014 res->lrs_present = be32_to_cpup(p);
6015 if (res->lrs_present)
Trond Myklebust93b717f2016-05-16 17:42:43 -04006016 status = decode_layout_stateid(xdr, &res->stateid);
Benny Halevycbe82602011-05-22 19:52:37 +03006017 return status;
6018out_overflow:
6019 print_overflow_msg(__func__, xdr);
6020 return -EIO;
6021}
6022
Andy Adamson863a3c62011-03-23 13:27:54 +00006023static int decode_layoutcommit(struct xdr_stream *xdr,
6024 struct rpc_rqst *req,
6025 struct nfs4_layoutcommit_res *res)
6026{
6027 __be32 *p;
6028 __u32 sizechanged;
6029 int status;
6030
6031 status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT);
Andy Adamsondb29c082011-07-30 20:52:38 -04006032 res->status = status;
Andy Adamson863a3c62011-03-23 13:27:54 +00006033 if (status)
6034 return status;
6035
6036 p = xdr_inline_decode(xdr, 4);
6037 if (unlikely(!p))
6038 goto out_overflow;
6039 sizechanged = be32_to_cpup(p);
6040
6041 if (sizechanged) {
6042 /* throw away new size */
6043 p = xdr_inline_decode(xdr, 8);
6044 if (unlikely(!p))
6045 goto out_overflow;
6046 }
6047 return 0;
6048out_overflow:
6049 print_overflow_msg(__func__, xdr);
6050 return -EIO;
6051}
Bryan Schumaker7d974792011-06-02 14:59:08 -04006052
6053static int decode_test_stateid(struct xdr_stream *xdr,
6054 struct nfs41_test_stateid_res *res)
6055{
6056 __be32 *p;
6057 int status;
6058 int num_res;
6059
6060 status = decode_op_hdr(xdr, OP_TEST_STATEID);
6061 if (status)
6062 return status;
6063
6064 p = xdr_inline_decode(xdr, 4);
6065 if (unlikely(!p))
6066 goto out_overflow;
6067 num_res = be32_to_cpup(p++);
6068 if (num_res != 1)
6069 goto out;
6070
6071 p = xdr_inline_decode(xdr, 4);
6072 if (unlikely(!p))
6073 goto out_overflow;
6074 res->status = be32_to_cpup(p++);
Bryan Schumaker1cab0652012-01-31 10:39:29 -05006075
6076 return status;
Bryan Schumaker7d974792011-06-02 14:59:08 -04006077out_overflow:
6078 print_overflow_msg(__func__, xdr);
6079out:
6080 return -EIO;
6081}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006082
6083static int decode_free_stateid(struct xdr_stream *xdr,
6084 struct nfs41_free_stateid_res *res)
6085{
Andy Adamson9f79fb42013-09-10 12:56:29 -04006086 res->status = decode_op_hdr(xdr, OP_FREE_STATEID);
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006087 return res->status;
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006088}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04006089#endif /* CONFIG_NFS_V4_1 */
6090
Linus Torvalds1da177e2005-04-16 15:20:36 -07006091/*
Benny Halevy49c25592008-12-23 16:06:16 -05006092 * END OF "GENERIC" DECODE ROUTINES.
6093 */
6094
6095/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006096 * Decode OPEN_DOWNGRADE response
6097 */
Chuck Leverbf269552010-12-14 14:59:29 +00006098static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp,
6099 struct xdr_stream *xdr,
6100 struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006101{
Andy Adamson05d564f2008-12-23 16:06:15 -05006102 struct compound_hdr hdr;
6103 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006104
Chuck Leverbf269552010-12-14 14:59:29 +00006105 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006106 if (status)
6107 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006108 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006109 if (status)
6110 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006111 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006112 if (status)
6113 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006114 status = decode_open_downgrade(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006115out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006116 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006117}
6118
6119/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006120 * Decode ACCESS response
6121 */
Chuck Leverbf269552010-12-14 14:59:29 +00006122static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6123 struct nfs4_accessres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006124{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006125 struct compound_hdr hdr;
6126 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006127
Chuck Leverbf269552010-12-14 14:59:29 +00006128 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006129 if (status)
6130 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006131 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006132 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006133 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006134 status = decode_putfh(xdr);
Trond Myklebust76b32992007-08-10 17:45:11 -04006135 if (status != 0)
6136 goto out;
Weston Andros Adamson6168f622012-09-10 14:00:46 -04006137 status = decode_access(xdr, &res->supported, &res->access);
Trond Myklebust76b32992007-08-10 17:45:11 -04006138 if (status != 0)
6139 goto out;
Trond Myklebust6926afd2012-01-07 13:22:46 -05006140 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141out:
6142 return status;
6143}
6144
6145/*
6146 * Decode LOOKUP response
6147 */
Chuck Leverbf269552010-12-14 14:59:29 +00006148static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6149 struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006150{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006151 struct compound_hdr hdr;
6152 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006153
Chuck Leverbf269552010-12-14 14:59:29 +00006154 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006155 if (status)
6156 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006157 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006158 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006159 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006160 status = decode_putfh(xdr);
6161 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006162 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006163 status = decode_lookup(xdr);
6164 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006166 status = decode_getfh(xdr, res->fh);
6167 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006168 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006169 status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006170out:
6171 return status;
6172}
6173
6174/*
6175 * Decode LOOKUP_ROOT response
6176 */
Chuck Leverbf269552010-12-14 14:59:29 +00006177static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp,
6178 struct xdr_stream *xdr,
6179 struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006180{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181 struct compound_hdr hdr;
6182 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006183
Chuck Leverbf269552010-12-14 14:59:29 +00006184 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006185 if (status)
6186 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006187 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006188 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006189 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006190 status = decode_putrootfh(xdr);
6191 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006192 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006193 status = decode_getfh(xdr, res->fh);
6194 if (status == 0)
David Quigleyaa9c2662013-05-22 12:50:44 -04006195 status = decode_getfattr_label(xdr, res->fattr,
6196 res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006197out:
6198 return status;
6199}
6200
6201/*
6202 * Decode REMOVE response
6203 */
Chuck Leverbf269552010-12-14 14:59:29 +00006204static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6205 struct nfs_removeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006206{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006207 struct compound_hdr hdr;
6208 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006209
Chuck Leverbf269552010-12-14 14:59:29 +00006210 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006211 if (status)
6212 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006213 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006214 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006215 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006216 status = decode_putfh(xdr);
6217 if (status)
Trond Myklebust16e42952005-10-27 22:12:44 -04006218 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006219 status = decode_remove(xdr, &res->cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220out:
6221 return status;
6222}
6223
6224/*
6225 * Decode RENAME response
6226 */
Chuck Leverbf269552010-12-14 14:59:29 +00006227static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6228 struct nfs_renameres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006230 struct compound_hdr hdr;
6231 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006232
Chuck Leverbf269552010-12-14 14:59:29 +00006233 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006234 if (status)
6235 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006236 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006237 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006238 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006239 status = decode_putfh(xdr);
6240 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006241 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006242 status = decode_savefh(xdr);
6243 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006244 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006245 status = decode_putfh(xdr);
6246 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006248 status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006249out:
6250 return status;
6251}
6252
6253/*
6254 * Decode LINK response
6255 */
Chuck Leverbf269552010-12-14 14:59:29 +00006256static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6257 struct nfs4_link_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006258{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006259 struct compound_hdr hdr;
6260 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006261
Chuck Leverbf269552010-12-14 14:59:29 +00006262 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006263 if (status)
6264 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006265 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006266 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006267 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006268 status = decode_putfh(xdr);
6269 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006271 status = decode_savefh(xdr);
6272 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006273 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006274 status = decode_putfh(xdr);
6275 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006276 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006277 status = decode_link(xdr, &res->cinfo);
6278 if (status)
Trond Myklebust91ba2ee2005-10-27 22:12:42 -04006279 goto out;
6280 /*
6281 * Note order: OP_LINK leaves the directory as the current
6282 * filehandle.
6283 */
Chuck Leverbf269552010-12-14 14:59:29 +00006284 status = decode_restorefh(xdr);
6285 if (status)
Trond Myklebust91ba2ee2005-10-27 22:12:42 -04006286 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006287 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006288out:
6289 return status;
6290}
6291
6292/*
6293 * Decode CREATE response
6294 */
Chuck Leverbf269552010-12-14 14:59:29 +00006295static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6296 struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006297{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298 struct compound_hdr hdr;
6299 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006300
Chuck Leverbf269552010-12-14 14:59:29 +00006301 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006302 if (status)
6303 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006304 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006305 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006306 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006307 status = decode_putfh(xdr);
6308 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006309 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006310 status = decode_create(xdr, &res->dir_cinfo);
6311 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006312 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006313 status = decode_getfh(xdr, res->fh);
6314 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006315 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006316 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006317out:
6318 return status;
6319}
6320
6321/*
6322 * Decode SYMLINK response
6323 */
Chuck Leverbf269552010-12-14 14:59:29 +00006324static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6325 struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006326{
Chuck Leverbf269552010-12-14 14:59:29 +00006327 return nfs4_xdr_dec_create(rqstp, xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328}
6329
6330/*
6331 * Decode GETATTR response
6332 */
Chuck Leverbf269552010-12-14 14:59:29 +00006333static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6334 struct nfs4_getattr_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006335{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006336 struct compound_hdr hdr;
6337 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006338
Chuck Leverbf269552010-12-14 14:59:29 +00006339 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006340 if (status)
6341 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006342 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006343 if (status)
6344 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006345 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346 if (status)
6347 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006348 status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349out:
6350 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006351}
6352
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006353/*
6354 * Encode an SETACL request
6355 */
Chuck Lever9f06c712010-12-14 14:59:18 +00006356static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr,
6357 struct nfs_setaclargs *args)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006358{
Andy Adamson05d564f2008-12-23 16:06:15 -05006359 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04006360 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05006361 };
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006362
Chuck Lever9f06c712010-12-14 14:59:18 +00006363 encode_compound_hdr(xdr, req, &hdr);
6364 encode_sequence(xdr, &args->seq_args, &hdr);
6365 encode_putfh(xdr, args->fh, &hdr);
6366 encode_setacl(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05006367 encode_nops(&hdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006368}
Andy Adamson05d564f2008-12-23 16:06:15 -05006369
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006370/*
6371 * Decode SETACL response
6372 */
6373static int
Chuck Leverbf269552010-12-14 14:59:29 +00006374nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Benny Halevy73c403a2009-04-01 09:22:01 -04006375 struct nfs_setaclres *res)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006376{
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006377 struct compound_hdr hdr;
6378 int status;
6379
Chuck Leverbf269552010-12-14 14:59:29 +00006380 status = decode_compound_hdr(xdr, &hdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006381 if (status)
6382 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006383 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006384 if (status)
6385 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006386 status = decode_putfh(xdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006387 if (status)
6388 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006389 status = decode_setattr(xdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006390out:
6391 return status;
6392}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006393
6394/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00006395 * Decode GETACL response
6396 */
6397static int
Chuck Leverbf269552010-12-14 14:59:29 +00006398nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Benny Halevy663c79b2009-04-01 09:21:59 -04006399 struct nfs_getaclres *res)
J. Bruce Fields029d1052005-06-22 17:16:22 +00006400{
J. Bruce Fields029d1052005-06-22 17:16:22 +00006401 struct compound_hdr hdr;
6402 int status;
6403
Trond Myklebust331818f2012-02-03 18:30:53 -05006404 if (res->acl_scratch != NULL) {
6405 void *p = page_address(res->acl_scratch);
6406 xdr_set_scratch_buffer(xdr, p, PAGE_SIZE);
6407 }
Chuck Leverbf269552010-12-14 14:59:29 +00006408 status = decode_compound_hdr(xdr, &hdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006409 if (status)
6410 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006411 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006412 if (status)
6413 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006414 status = decode_putfh(xdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006415 if (status)
6416 goto out;
Andy Adamsonbf118a32011-12-07 11:55:27 -05006417 status = decode_getacl(xdr, rqstp, res);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006418
6419out:
6420 return status;
6421}
6422
6423/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006424 * Decode CLOSE response
6425 */
Chuck Leverbf269552010-12-14 14:59:29 +00006426static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6427 struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006428{
Andy Adamson05d564f2008-12-23 16:06:15 -05006429 struct compound_hdr hdr;
6430 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006431
Chuck Leverbf269552010-12-14 14:59:29 +00006432 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006433 if (status)
6434 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006435 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006436 if (status)
6437 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006438 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006439 if (status)
6440 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006441 status = decode_close(xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04006442 if (status != 0)
6443 goto out;
6444 /*
6445 * Note: Server may do delete on close for this file
6446 * in which case the getattr call will fail with
6447 * an ESTALE error. Shouldn't be a problem,
6448 * though, since fattr->valid will remain unset.
6449 */
Trond Myklebust6926afd2012-01-07 13:22:46 -05006450 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006451out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006452 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006453}
6454
6455/*
6456 * Decode OPEN response
6457 */
Chuck Leverbf269552010-12-14 14:59:29 +00006458static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6459 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006460{
Andy Adamson05d564f2008-12-23 16:06:15 -05006461 struct compound_hdr hdr;
6462 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006463
Chuck Leverbf269552010-12-14 14:59:29 +00006464 status = decode_compound_hdr(xdr, &hdr);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04006465 if (status)
6466 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006467 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006468 if (status)
6469 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006470 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006471 if (status)
6472 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006473 status = decode_open(xdr, res);
Andy Adamson05d564f2008-12-23 16:06:15 -05006474 if (status)
6475 goto out;
Weston Andros Adamson01913b42012-09-06 15:54:27 -04006476 status = decode_getfh(xdr, &res->fh);
6477 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006478 goto out;
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07006479 if (res->access_request)
6480 decode_access(xdr, &res->access_supported, &res->access_result);
David Quigleyaa9c2662013-05-22 12:50:44 -04006481 decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006482out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006483 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006484}
6485
6486/*
6487 * Decode OPEN_CONFIRM response
6488 */
Chuck Leverbf269552010-12-14 14:59:29 +00006489static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp,
6490 struct xdr_stream *xdr,
6491 struct nfs_open_confirmres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006492{
Andy Adamson05d564f2008-12-23 16:06:15 -05006493 struct compound_hdr hdr;
6494 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006495
Chuck Leverbf269552010-12-14 14:59:29 +00006496 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006497 if (status)
6498 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006499 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006500 if (status)
6501 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006502 status = decode_open_confirm(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006503out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006504 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006505}
6506
6507/*
6508 * Decode OPEN response
6509 */
Chuck Leverbf269552010-12-14 14:59:29 +00006510static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
6511 struct xdr_stream *xdr,
6512 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006513{
Andy Adamson05d564f2008-12-23 16:06:15 -05006514 struct compound_hdr hdr;
6515 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006516
Chuck Leverbf269552010-12-14 14:59:29 +00006517 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006518 if (status)
6519 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006520 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006521 if (status)
6522 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006523 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006524 if (status)
6525 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006526 status = decode_open(xdr, res);
Andy Adamson05d564f2008-12-23 16:06:15 -05006527 if (status)
6528 goto out;
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07006529 if (res->access_request)
6530 decode_access(xdr, &res->access_supported, &res->access_result);
Trond Myklebust6926afd2012-01-07 13:22:46 -05006531 decode_getfattr(xdr, res->f_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006532out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006533 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006534}
6535
6536/*
6537 * Decode SETATTR response
6538 */
Chuck Leverbf269552010-12-14 14:59:29 +00006539static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp,
6540 struct xdr_stream *xdr,
6541 struct nfs_setattrres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006542{
Andy Adamson05d564f2008-12-23 16:06:15 -05006543 struct compound_hdr hdr;
6544 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006545
Chuck Leverbf269552010-12-14 14:59:29 +00006546 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006547 if (status)
6548 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006549 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006550 if (status)
6551 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006552 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006553 if (status)
6554 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006555 status = decode_setattr(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006556 if (status)
6557 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006558 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006559out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006560 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006561}
6562
6563/*
6564 * Decode LOCK response
6565 */
Chuck Leverbf269552010-12-14 14:59:29 +00006566static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6567 struct nfs_lock_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006568{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006569 struct compound_hdr hdr;
6570 int status;
6571
Chuck Leverbf269552010-12-14 14:59:29 +00006572 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006573 if (status)
6574 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006575 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006576 if (status)
6577 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006578 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006579 if (status)
6580 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006581 status = decode_lock(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006582out:
6583 return status;
6584}
6585
6586/*
6587 * Decode LOCKT response
6588 */
Chuck Leverbf269552010-12-14 14:59:29 +00006589static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6590 struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006592 struct compound_hdr hdr;
6593 int status;
6594
Chuck Leverbf269552010-12-14 14:59:29 +00006595 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006596 if (status)
6597 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006598 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006599 if (status)
6600 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006601 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006602 if (status)
6603 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006604 status = decode_lockt(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006605out:
6606 return status;
6607}
6608
6609/*
6610 * Decode LOCKU response
6611 */
Chuck Leverbf269552010-12-14 14:59:29 +00006612static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6613 struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006614{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006615 struct compound_hdr hdr;
6616 int status;
6617
Chuck Leverbf269552010-12-14 14:59:29 +00006618 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006619 if (status)
6620 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006621 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006622 if (status)
6623 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006624 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006625 if (status)
6626 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006627 status = decode_locku(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628out:
6629 return status;
6630}
6631
Chuck Leverbf269552010-12-14 14:59:29 +00006632static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp,
6633 struct xdr_stream *xdr, void *dummy)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006634{
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006635 struct compound_hdr hdr;
6636 int status;
6637
Chuck Leverbf269552010-12-14 14:59:29 +00006638 status = decode_compound_hdr(xdr, &hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006639 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006640 status = decode_release_lockowner(xdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006641 return status;
6642}
6643
Linus Torvalds1da177e2005-04-16 15:20:36 -07006644/*
6645 * Decode READLINK response
6646 */
Chuck Leverbf269552010-12-14 14:59:29 +00006647static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp,
6648 struct xdr_stream *xdr,
Benny Halevyf50c7002009-04-01 09:21:55 -04006649 struct nfs4_readlink_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006650{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006651 struct compound_hdr hdr;
6652 int status;
6653
Chuck Leverbf269552010-12-14 14:59:29 +00006654 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006655 if (status)
6656 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006657 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006658 if (status)
6659 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006660 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006661 if (status)
6662 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006663 status = decode_readlink(xdr, rqstp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006664out:
6665 return status;
6666}
6667
6668/*
6669 * Decode READDIR response
6670 */
Chuck Leverbf269552010-12-14 14:59:29 +00006671static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6672 struct nfs4_readdir_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006673{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006674 struct compound_hdr hdr;
6675 int status;
6676
Chuck Leverbf269552010-12-14 14:59:29 +00006677 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006678 if (status)
6679 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006680 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006681 if (status)
6682 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006683 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006684 if (status)
6685 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006686 status = decode_readdir(xdr, rqstp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006687out:
6688 return status;
6689}
6690
6691/*
6692 * Decode Read response
6693 */
Chuck Leverbf269552010-12-14 14:59:29 +00006694static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Anna Schumaker9137bdf2014-05-06 09:12:25 -04006695 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006696{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006697 struct compound_hdr hdr;
6698 int status;
6699
Chuck Leverbf269552010-12-14 14:59:29 +00006700 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006701 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006702 if (status)
6703 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006704 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006705 if (status)
6706 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006707 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006708 if (status)
6709 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006710 status = decode_read(xdr, rqstp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006711 if (!status)
6712 status = res->count;
6713out:
6714 return status;
6715}
6716
6717/*
6718 * Decode WRITE response
6719 */
Chuck Leverbf269552010-12-14 14:59:29 +00006720static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Anna Schumaker9137bdf2014-05-06 09:12:25 -04006721 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006722{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006723 struct compound_hdr hdr;
6724 int status;
6725
Chuck Leverbf269552010-12-14 14:59:29 +00006726 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006727 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006728 if (status)
6729 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006730 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006731 if (status)
6732 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006733 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006734 if (status)
6735 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006736 status = decode_write(xdr, res);
Trond Myklebust4f9838c2005-10-27 22:12:44 -04006737 if (status)
6738 goto out;
Fred Isaman7ffd1062011-03-03 15:13:46 +00006739 if (res->fattr)
Trond Myklebust6926afd2012-01-07 13:22:46 -05006740 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006741 if (!status)
6742 status = res->count;
6743out:
6744 return status;
6745}
6746
6747/*
6748 * Decode COMMIT response
6749 */
Chuck Leverbf269552010-12-14 14:59:29 +00006750static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Fred Isaman0b7c0152012-04-20 14:47:39 -04006751 struct nfs_commitres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006752{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006753 struct compound_hdr hdr;
6754 int status;
6755
Chuck Leverbf269552010-12-14 14:59:29 +00006756 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006757 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006758 if (status)
6759 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006760 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006761 if (status)
6762 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006763 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006764 if (status)
6765 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006766 status = decode_commit(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006767out:
6768 return status;
6769}
6770
6771/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006772 * Decode FSINFO response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006773 */
Chuck Leverbf269552010-12-14 14:59:29 +00006774static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevy3dda5e42009-04-01 09:21:57 -04006775 struct nfs4_fsinfo_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006776{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006777 struct compound_hdr hdr;
6778 int status;
6779
Chuck Leverbf269552010-12-14 14:59:29 +00006780 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006781 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006782 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006783 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006784 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006785 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006786 status = decode_fsinfo(xdr, res->fsinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006787 return status;
6788}
6789
6790/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006791 * Decode PATHCONF response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006792 */
Chuck Leverbf269552010-12-14 14:59:29 +00006793static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevyd45b2982009-04-01 09:21:58 -04006794 struct nfs4_pathconf_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006795{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006796 struct compound_hdr hdr;
6797 int status;
6798
Chuck Leverbf269552010-12-14 14:59:29 +00006799 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006800 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006801 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006802 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006803 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006805 status = decode_pathconf(xdr, res->pathconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006806 return status;
6807}
6808
6809/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006810 * Decode STATFS response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006811 */
Chuck Leverbf269552010-12-14 14:59:29 +00006812static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevy24ad1482009-04-01 09:21:56 -04006813 struct nfs4_statfs_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006814{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006815 struct compound_hdr hdr;
6816 int status;
6817
Chuck Leverbf269552010-12-14 14:59:29 +00006818 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006820 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006821 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006822 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006823 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006824 status = decode_statfs(xdr, res->fsstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006825 return status;
6826}
6827
6828/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006829 * Decode GETATTR_BITMAP response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006830 */
Chuck Leverbf269552010-12-14 14:59:29 +00006831static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req,
6832 struct xdr_stream *xdr,
6833 struct nfs4_server_caps_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006834{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006835 struct compound_hdr hdr;
6836 int status;
6837
Chuck Leverbf269552010-12-14 14:59:29 +00006838 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006839 if (status)
6840 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006841 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006842 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006843 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006844 status = decode_putfh(xdr);
6845 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006846 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006847 status = decode_server_caps(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006848out:
6849 return status;
6850}
6851
6852/*
6853 * Decode RENEW response
6854 */
Chuck Leverbf269552010-12-14 14:59:29 +00006855static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6856 void *__unused)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006857{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006858 struct compound_hdr hdr;
6859 int status;
6860
Chuck Leverbf269552010-12-14 14:59:29 +00006861 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006862 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006863 status = decode_renew(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006864 return status;
6865}
6866
6867/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006868 * Decode SETCLIENTID response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006869 */
Chuck Leverbf269552010-12-14 14:59:29 +00006870static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req,
6871 struct xdr_stream *xdr,
6872 struct nfs4_setclientid_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006873{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006874 struct compound_hdr hdr;
6875 int status;
6876
Chuck Leverbf269552010-12-14 14:59:29 +00006877 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006878 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006879 status = decode_setclientid(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006880 return status;
6881}
6882
6883/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006884 * Decode SETCLIENTID_CONFIRM response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006885 */
Chuck Leverbf269552010-12-14 14:59:29 +00006886static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req,
Chuck Lever83ca7f52013-03-16 15:55:53 -04006887 struct xdr_stream *xdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006888{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006889 struct compound_hdr hdr;
6890 int status;
6891
Chuck Leverbf269552010-12-14 14:59:29 +00006892 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006893 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006894 status = decode_setclientid_confirm(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006895 return status;
6896}
6897
6898/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006899 * Decode DELEGRETURN response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006900 */
Chuck Leverbf269552010-12-14 14:59:29 +00006901static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp,
6902 struct xdr_stream *xdr,
6903 struct nfs4_delegreturnres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006904{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006905 struct compound_hdr hdr;
6906 int status;
6907
Chuck Leverbf269552010-12-14 14:59:29 +00006908 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006909 if (status)
6910 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006911 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006912 if (status)
Trond Myklebustfa178f22006-01-03 09:55:38 +01006913 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006914 status = decode_putfh(xdr);
Trond Myklebustfa178f22006-01-03 09:55:38 +01006915 if (status != 0)
6916 goto out;
Trond Myklebuste144cbc2012-04-28 16:05:03 -04006917 status = decode_getfattr(xdr, res->fattr, res->server);
Jeff Layton556ae3b2010-03-21 12:10:36 -04006918 if (status != 0)
6919 goto out;
Trond Myklebuste144cbc2012-04-28 16:05:03 -04006920 status = decode_delegreturn(xdr);
Trond Myklebustfa178f22006-01-03 09:55:38 +01006921out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006922 return status;
6923}
6924
Trond Myklebust683b57b2006-06-09 09:34:22 -04006925/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006926 * Decode FS_LOCATIONS response
Trond Myklebust683b57b2006-06-09 09:34:22 -04006927 */
Chuck Leverbf269552010-12-14 14:59:29 +00006928static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req,
6929 struct xdr_stream *xdr,
Benny Halevy22958462009-04-01 09:22:02 -04006930 struct nfs4_fs_locations_res *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006931{
Trond Myklebust683b57b2006-06-09 09:34:22 -04006932 struct compound_hdr hdr;
6933 int status;
6934
Chuck Leverbf269552010-12-14 14:59:29 +00006935 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006936 if (status)
6937 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006938 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006939 if (status)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006940 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006941 status = decode_putfh(xdr);
6942 if (status)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006943 goto out;
Chuck Leverb03d7352013-10-17 14:12:50 -04006944 if (res->migration) {
6945 xdr_enter_page(xdr, PAGE_SIZE);
6946 status = decode_getfattr_generic(xdr,
6947 &res->fs_locations->fattr,
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05006948 NULL, res->fs_locations,
David Quigleyaa9c2662013-05-22 12:50:44 -04006949 NULL, res->fs_locations->server);
Chuck Leverb03d7352013-10-17 14:12:50 -04006950 if (status)
6951 goto out;
6952 if (res->renew)
6953 status = decode_renew(xdr);
6954 } else {
6955 status = decode_lookup(xdr);
6956 if (status)
6957 goto out;
6958 xdr_enter_page(xdr, PAGE_SIZE);
6959 status = decode_getfattr_generic(xdr,
6960 &res->fs_locations->fattr,
6961 NULL, res->fs_locations,
6962 NULL, res->fs_locations->server);
6963 }
Trond Myklebust683b57b2006-06-09 09:34:22 -04006964out:
6965 return status;
6966}
6967
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00006968/*
6969 * Decode SECINFO response
6970 */
6971static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp,
6972 struct xdr_stream *xdr,
6973 struct nfs4_secinfo_res *res)
6974{
6975 struct compound_hdr hdr;
6976 int status;
6977
6978 status = decode_compound_hdr(xdr, &hdr);
6979 if (status)
6980 goto out;
6981 status = decode_sequence(xdr, &res->seq_res, rqstp);
6982 if (status)
6983 goto out;
6984 status = decode_putfh(xdr);
6985 if (status)
6986 goto out;
6987 status = decode_secinfo(xdr, res);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00006988out:
6989 return status;
6990}
6991
Chuck Lever44c99932013-10-17 14:13:30 -04006992/*
6993 * Decode FSID_PRESENT response
6994 */
6995static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp,
6996 struct xdr_stream *xdr,
6997 struct nfs4_fsid_present_res *res)
6998{
6999 struct compound_hdr hdr;
7000 int status;
7001
7002 status = decode_compound_hdr(xdr, &hdr);
7003 if (status)
7004 goto out;
7005 status = decode_sequence(xdr, &res->seq_res, rqstp);
7006 if (status)
7007 goto out;
7008 status = decode_putfh(xdr);
7009 if (status)
7010 goto out;
7011 status = decode_getfh(xdr, res->fh);
7012 if (status)
7013 goto out;
7014 if (res->renew)
7015 status = decode_renew(xdr);
7016out:
7017 return status;
7018}
7019
Benny Halevy99fe60d2009-04-01 09:22:29 -04007020#if defined(CONFIG_NFS_V4_1)
7021/*
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04007022 * Decode BIND_CONN_TO_SESSION response
7023 */
7024static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp,
7025 struct xdr_stream *xdr,
7026 void *res)
7027{
7028 struct compound_hdr hdr;
7029 int status;
7030
7031 status = decode_compound_hdr(xdr, &hdr);
7032 if (!status)
7033 status = decode_bind_conn_to_session(xdr, res);
7034 return status;
7035}
7036
7037/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007038 * Decode EXCHANGE_ID response
Benny Halevy99fe60d2009-04-01 09:22:29 -04007039 */
Chuck Leverbf269552010-12-14 14:59:29 +00007040static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp,
7041 struct xdr_stream *xdr,
Benny Halevy99fe60d2009-04-01 09:22:29 -04007042 void *res)
7043{
Benny Halevy99fe60d2009-04-01 09:22:29 -04007044 struct compound_hdr hdr;
7045 int status;
7046
Chuck Leverbf269552010-12-14 14:59:29 +00007047 status = decode_compound_hdr(xdr, &hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04007048 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007049 status = decode_exchange_id(xdr, res);
Benny Halevy99fe60d2009-04-01 09:22:29 -04007050 return status;
7051}
Andy Adamson2050f0c2009-04-01 09:22:30 -04007052
7053/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007054 * Decode CREATE_SESSION response
Andy Adamsonfc931582009-04-01 09:22:31 -04007055 */
Chuck Leverbf269552010-12-14 14:59:29 +00007056static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp,
7057 struct xdr_stream *xdr,
Andy Adamsonfc931582009-04-01 09:22:31 -04007058 struct nfs41_create_session_res *res)
7059{
Andy Adamsonfc931582009-04-01 09:22:31 -04007060 struct compound_hdr hdr;
7061 int status;
7062
Chuck Leverbf269552010-12-14 14:59:29 +00007063 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04007064 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007065 status = decode_create_session(xdr, res);
Andy Adamsonfc931582009-04-01 09:22:31 -04007066 return status;
7067}
7068
7069/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007070 * Decode DESTROY_SESSION response
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007071 */
Chuck Leverbf269552010-12-14 14:59:29 +00007072static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp,
7073 struct xdr_stream *xdr,
7074 void *res)
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007075{
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007076 struct compound_hdr hdr;
7077 int status;
7078
Chuck Leverbf269552010-12-14 14:59:29 +00007079 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007080 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007081 status = decode_destroy_session(xdr, res);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007082 return status;
7083}
7084
7085/*
Trond Myklebust66245532012-05-25 17:18:09 -04007086 * Decode DESTROY_CLIENTID response
7087 */
7088static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp,
7089 struct xdr_stream *xdr,
7090 void *res)
7091{
7092 struct compound_hdr hdr;
7093 int status;
7094
7095 status = decode_compound_hdr(xdr, &hdr);
7096 if (!status)
7097 status = decode_destroy_clientid(xdr, res);
7098 return status;
7099}
7100
7101/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007102 * Decode SEQUENCE response
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007103 */
Chuck Leverbf269552010-12-14 14:59:29 +00007104static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp,
7105 struct xdr_stream *xdr,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007106 struct nfs4_sequence_res *res)
7107{
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007108 struct compound_hdr hdr;
7109 int status;
7110
Chuck Leverbf269552010-12-14 14:59:29 +00007111 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007112 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007113 status = decode_sequence(xdr, res, rqstp);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007114 return status;
7115}
7116
7117/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007118 * Decode GET_LEASE_TIME response
Andy Adamson2050f0c2009-04-01 09:22:30 -04007119 */
Chuck Leverbf269552010-12-14 14:59:29 +00007120static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp,
7121 struct xdr_stream *xdr,
Andy Adamson2050f0c2009-04-01 09:22:30 -04007122 struct nfs4_get_lease_time_res *res)
7123{
Andy Adamson2050f0c2009-04-01 09:22:30 -04007124 struct compound_hdr hdr;
7125 int status;
7126
Chuck Leverbf269552010-12-14 14:59:29 +00007127 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007128 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007129 status = decode_sequence(xdr, &res->lr_seq_res, rqstp);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007130 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007131 status = decode_putrootfh(xdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007132 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007133 status = decode_fsinfo(xdr, res->lr_fsinfo);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007134 return status;
7135}
Ricardo Labiaga180197532009-12-05 16:08:40 -05007136
7137/*
7138 * Decode RECLAIM_COMPLETE response
7139 */
Chuck Leverbf269552010-12-14 14:59:29 +00007140static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp,
7141 struct xdr_stream *xdr,
Ricardo Labiaga180197532009-12-05 16:08:40 -05007142 struct nfs41_reclaim_complete_res *res)
7143{
Ricardo Labiaga180197532009-12-05 16:08:40 -05007144 struct compound_hdr hdr;
7145 int status;
7146
Chuck Leverbf269552010-12-14 14:59:29 +00007147 status = decode_compound_hdr(xdr, &hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007148 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007149 status = decode_sequence(xdr, &res->seq_res, rqstp);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007150 if (!status)
Himangi Saraogi8ee2b782014-06-27 00:09:09 +05307151 status = decode_reclaim_complete(xdr, NULL);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007152 return status;
7153}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007154
7155/*
7156 * Decode GETDEVINFO response
7157 */
Chuck Leverbf269552010-12-14 14:59:29 +00007158static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp,
7159 struct xdr_stream *xdr,
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007160 struct nfs4_getdeviceinfo_res *res)
7161{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007162 struct compound_hdr hdr;
7163 int status;
7164
Chuck Leverbf269552010-12-14 14:59:29 +00007165 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007166 if (status != 0)
7167 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007168 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007169 if (status != 0)
7170 goto out;
Trond Myklebust4e590802015-03-09 14:01:25 -04007171 status = decode_getdeviceinfo(xdr, res);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007172out:
7173 return status;
7174}
7175
7176/*
7177 * Decode LAYOUTGET response
7178 */
Chuck Leverbf269552010-12-14 14:59:29 +00007179static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp,
7180 struct xdr_stream *xdr,
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007181 struct nfs4_layoutget_res *res)
7182{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007183 struct compound_hdr hdr;
7184 int status;
7185
Chuck Leverbf269552010-12-14 14:59:29 +00007186 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007187 if (status)
7188 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007189 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007190 if (status)
7191 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007192 status = decode_putfh(xdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007193 if (status)
7194 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007195 status = decode_layoutget(xdr, rqstp, res);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007196out:
7197 return status;
7198}
Andy Adamson863a3c62011-03-23 13:27:54 +00007199
7200/*
Benny Halevycbe82602011-05-22 19:52:37 +03007201 * Decode LAYOUTRETURN response
7202 */
7203static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp,
7204 struct xdr_stream *xdr,
7205 struct nfs4_layoutreturn_res *res)
7206{
7207 struct compound_hdr hdr;
7208 int status;
7209
7210 status = decode_compound_hdr(xdr, &hdr);
7211 if (status)
7212 goto out;
7213 status = decode_sequence(xdr, &res->seq_res, rqstp);
7214 if (status)
7215 goto out;
7216 status = decode_putfh(xdr);
7217 if (status)
7218 goto out;
7219 status = decode_layoutreturn(xdr, res);
7220out:
7221 return status;
7222}
7223
7224/*
Andy Adamson863a3c62011-03-23 13:27:54 +00007225 * Decode LAYOUTCOMMIT response
7226 */
7227static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
7228 struct xdr_stream *xdr,
7229 struct nfs4_layoutcommit_res *res)
7230{
7231 struct compound_hdr hdr;
7232 int status;
7233
7234 status = decode_compound_hdr(xdr, &hdr);
7235 if (status)
7236 goto out;
7237 status = decode_sequence(xdr, &res->seq_res, rqstp);
7238 if (status)
7239 goto out;
7240 status = decode_putfh(xdr);
7241 if (status)
7242 goto out;
7243 status = decode_layoutcommit(xdr, rqstp, res);
7244 if (status)
7245 goto out;
Trond Myklebust6926afd2012-01-07 13:22:46 -05007246 decode_getfattr(xdr, res->fattr, res->server);
Andy Adamson863a3c62011-03-23 13:27:54 +00007247out:
7248 return status;
7249}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007250
7251/*
7252 * Decode SECINFO_NO_NAME response
7253 */
7254static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
7255 struct xdr_stream *xdr,
7256 struct nfs4_secinfo_res *res)
7257{
7258 struct compound_hdr hdr;
7259 int status;
7260
7261 status = decode_compound_hdr(xdr, &hdr);
7262 if (status)
7263 goto out;
7264 status = decode_sequence(xdr, &res->seq_res, rqstp);
7265 if (status)
7266 goto out;
7267 status = decode_putrootfh(xdr);
7268 if (status)
7269 goto out;
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04007270 status = decode_secinfo_no_name(xdr, res);
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007271out:
7272 return status;
7273}
Bryan Schumaker7d974792011-06-02 14:59:08 -04007274
7275/*
7276 * Decode TEST_STATEID response
7277 */
7278static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp,
7279 struct xdr_stream *xdr,
7280 struct nfs41_test_stateid_res *res)
7281{
7282 struct compound_hdr hdr;
7283 int status;
7284
7285 status = decode_compound_hdr(xdr, &hdr);
7286 if (status)
7287 goto out;
7288 status = decode_sequence(xdr, &res->seq_res, rqstp);
7289 if (status)
7290 goto out;
7291 status = decode_test_stateid(xdr, res);
7292out:
7293 return status;
7294}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04007295
7296/*
7297 * Decode FREE_STATEID response
7298 */
7299static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
7300 struct xdr_stream *xdr,
7301 struct nfs41_free_stateid_res *res)
7302{
7303 struct compound_hdr hdr;
7304 int status;
7305
7306 status = decode_compound_hdr(xdr, &hdr);
7307 if (status)
7308 goto out;
7309 status = decode_sequence(xdr, &res->seq_res, rqstp);
7310 if (status)
7311 goto out;
7312 status = decode_free_stateid(xdr, res);
7313out:
7314 return status;
7315}
Benny Halevy99fe60d2009-04-01 09:22:29 -04007316#endif /* CONFIG_NFS_V4_1 */
7317
Chuck Lever573c4e12010-12-14 14:58:11 +00007318/**
7319 * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in
7320 * the local page cache.
7321 * @xdr: XDR stream where entry resides
7322 * @entry: buffer to fill in with entry data
7323 * @plus: boolean indicating whether this should be a readdirplus entry
7324 *
7325 * Returns zero if successful, otherwise a negative errno value is
7326 * returned.
7327 *
7328 * This function is not invoked during READDIR reply decoding, but
7329 * rather whenever an application invokes the getdents(2) system call
7330 * on a directory already in our cache.
7331 */
7332int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
7333 int plus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007334{
Trond Myklebust256e48b2012-06-21 11:18:13 -04007335 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04007336 uint32_t bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007337 uint32_t len;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007338 __be32 *p = xdr_inline_decode(xdr, 4);
7339 if (unlikely(!p))
7340 goto out_overflow;
Chuck Leverc08e76d2011-01-28 12:40:55 -05007341 if (*p == xdr_zero) {
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007342 p = xdr_inline_decode(xdr, 4);
7343 if (unlikely(!p))
7344 goto out_overflow;
Chuck Leverc08e76d2011-01-28 12:40:55 -05007345 if (*p == xdr_zero)
Chuck Lever573c4e12010-12-14 14:58:11 +00007346 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007347 entry->eof = 1;
Chuck Lever573c4e12010-12-14 14:58:11 +00007348 return -EBADCOOKIE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007349 }
7350
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007351 p = xdr_inline_decode(xdr, 12);
7352 if (unlikely(!p))
7353 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007354 entry->prev_cookie = entry->cookie;
7355 p = xdr_decode_hyper(p, &entry->cookie);
Chuck Leverc08e76d2011-01-28 12:40:55 -05007356 entry->len = be32_to_cpup(p);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007357
Trond Myklebust9af8c222010-10-24 11:52:55 -04007358 p = xdr_inline_decode(xdr, entry->len);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007359 if (unlikely(!p))
7360 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007361 entry->name = (const char *) p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007362
7363 /*
7364 * In case the server doesn't return an inode number,
7365 * we fake one here. (We don't use inode number 0,
7366 * since glibc seems to choke on it...)
7367 */
7368 entry->ino = 1;
Trond Myklebust4f082222010-10-24 13:14:02 -04007369 entry->fattr->valid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007370
Trond Myklebust9af8c222010-10-24 11:52:55 -04007371 if (decode_attr_bitmap(xdr, bitmap) < 0)
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007372 goto out_overflow;
Trond Myklebust9af8c222010-10-24 11:52:55 -04007373
Trond Myklebust256e48b2012-06-21 11:18:13 -04007374 if (decode_attr_length(xdr, &len, &savep) < 0)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007375 goto out_overflow;
7376
Chuck Lever573c4e12010-12-14 14:58:11 +00007377 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
David Quigleyaa9c2662013-05-22 12:50:44 -04007378 NULL, entry->label, entry->server) < 0)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007379 goto out_overflow;
Trond Myklebust28331a42011-04-27 13:47:52 -04007380 if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
7381 entry->ino = entry->fattr->mounted_on_fileid;
7382 else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007383 entry->ino = entry->fattr->fileid;
7384
Trond Myklebust0b26a0b2010-11-20 14:26:44 -05007385 entry->d_type = DT_UNKNOWN;
7386 if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
7387 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
7388
Chuck Lever573c4e12010-12-14 14:58:11 +00007389 return 0;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007390
7391out_overflow:
7392 print_overflow_msg(__func__, xdr);
Chuck Lever573c4e12010-12-14 14:58:11 +00007393 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007394}
7395
7396/*
7397 * We need to translate between nfs status return values and
7398 * the local errno values which may not be the same.
7399 */
7400static struct {
7401 int stat;
7402 int errno;
7403} nfs_errtbl[] = {
7404 { NFS4_OK, 0 },
Benny Halevy856dff32008-03-31 17:39:06 +03007405 { NFS4ERR_PERM, -EPERM },
7406 { NFS4ERR_NOENT, -ENOENT },
7407 { NFS4ERR_IO, -errno_NFSERR_IO},
7408 { NFS4ERR_NXIO, -ENXIO },
7409 { NFS4ERR_ACCESS, -EACCES },
7410 { NFS4ERR_EXIST, -EEXIST },
7411 { NFS4ERR_XDEV, -EXDEV },
7412 { NFS4ERR_NOTDIR, -ENOTDIR },
7413 { NFS4ERR_ISDIR, -EISDIR },
7414 { NFS4ERR_INVAL, -EINVAL },
7415 { NFS4ERR_FBIG, -EFBIG },
7416 { NFS4ERR_NOSPC, -ENOSPC },
7417 { NFS4ERR_ROFS, -EROFS },
7418 { NFS4ERR_MLINK, -EMLINK },
7419 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
7420 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
7421 { NFS4ERR_DQUOT, -EDQUOT },
7422 { NFS4ERR_STALE, -ESTALE },
7423 { NFS4ERR_BADHANDLE, -EBADHANDLE },
Benny Halevy856dff32008-03-31 17:39:06 +03007424 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
7425 { NFS4ERR_NOTSUPP, -ENOTSUPP },
7426 { NFS4ERR_TOOSMALL, -ETOOSMALL },
Trond Myklebustfdcb4572010-02-08 09:32:40 -05007427 { NFS4ERR_SERVERFAULT, -EREMOTEIO },
Benny Halevy856dff32008-03-31 17:39:06 +03007428 { NFS4ERR_BADTYPE, -EBADTYPE },
7429 { NFS4ERR_LOCKED, -EAGAIN },
Benny Halevy856dff32008-03-31 17:39:06 +03007430 { NFS4ERR_SYMLINK, -ELOOP },
7431 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
7432 { NFS4ERR_DEADLOCK, -EDEADLK },
Benny Halevy856dff32008-03-31 17:39:06 +03007433 { -1, -EIO }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007434};
7435
7436/*
7437 * Convert an NFS error code to a local one.
7438 * This one is used jointly by NFSv2 and NFSv3.
7439 */
7440static int
David Howells0a8ea432006-08-22 20:06:08 -04007441nfs4_stat_to_errno(int stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007442{
7443 int i;
7444 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
7445 if (nfs_errtbl[i].stat == stat)
7446 return nfs_errtbl[i].errno;
7447 }
7448 if (stat <= 10000 || stat > 10100) {
7449 /* The server is looney tunes. */
Trond Myklebustfdcb4572010-02-08 09:32:40 -05007450 return -EREMOTEIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007451 }
7452 /* If we cannot translate the error, the recovery routines should
7453 * handle it.
7454 * Note: remaining NFSv4 error codes have values > 10000, so should
7455 * not conflict with native Linux error codes.
7456 */
Benny Halevy856dff32008-03-31 17:39:06 +03007457 return -stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007458}
7459
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007460#ifdef CONFIG_NFS_V4_2
7461#include "nfs42xdr.c"
7462#endif /* CONFIG_NFS_V4_2 */
7463
Linus Torvalds1da177e2005-04-16 15:20:36 -07007464#define PROC(proc, argtype, restype) \
7465[NFSPROC4_CLNT_##proc] = { \
7466 .p_proc = NFSPROC4_COMPOUND, \
Chuck Lever9f06c712010-12-14 14:59:18 +00007467 .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \
Chuck Leverbf269552010-12-14 14:59:29 +00007468 .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \
Chuck Lever2bea90d2007-03-29 16:47:53 -04007469 .p_arglen = NFS4_##argtype##_sz, \
7470 .p_replen = NFS4_##restype##_sz, \
Chuck Levercc0175c2006-03-20 13:44:22 -05007471 .p_statidx = NFSPROC4_CLNT_##proc, \
7472 .p_name = #proc, \
Andy Adamson05d564f2008-12-23 16:06:15 -05007473}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007474
Anna Schumaker7c61f0d2015-04-14 10:34:20 -04007475#define STUB(proc) \
7476[NFSPROC4_CLNT_##proc] = { \
7477 .p_name = #proc, \
7478}
7479
Linus Torvalds1da177e2005-04-16 15:20:36 -07007480struct rpc_procinfo nfs4_procedures[] = {
Chuck Lever7d93bd712010-12-14 14:57:42 +00007481 PROC(READ, enc_read, dec_read),
7482 PROC(WRITE, enc_write, dec_write),
7483 PROC(COMMIT, enc_commit, dec_commit),
7484 PROC(OPEN, enc_open, dec_open),
7485 PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
7486 PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr),
7487 PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade),
7488 PROC(CLOSE, enc_close, dec_close),
7489 PROC(SETATTR, enc_setattr, dec_setattr),
7490 PROC(FSINFO, enc_fsinfo, dec_fsinfo),
7491 PROC(RENEW, enc_renew, dec_renew),
7492 PROC(SETCLIENTID, enc_setclientid, dec_setclientid),
7493 PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm),
7494 PROC(LOCK, enc_lock, dec_lock),
7495 PROC(LOCKT, enc_lockt, dec_lockt),
7496 PROC(LOCKU, enc_locku, dec_locku),
7497 PROC(ACCESS, enc_access, dec_access),
7498 PROC(GETATTR, enc_getattr, dec_getattr),
7499 PROC(LOOKUP, enc_lookup, dec_lookup),
7500 PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
7501 PROC(REMOVE, enc_remove, dec_remove),
7502 PROC(RENAME, enc_rename, dec_rename),
7503 PROC(LINK, enc_link, dec_link),
7504 PROC(SYMLINK, enc_symlink, dec_symlink),
7505 PROC(CREATE, enc_create, dec_create),
7506 PROC(PATHCONF, enc_pathconf, dec_pathconf),
7507 PROC(STATFS, enc_statfs, dec_statfs),
7508 PROC(READLINK, enc_readlink, dec_readlink),
7509 PROC(READDIR, enc_readdir, dec_readdir),
7510 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
7511 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
7512 PROC(GETACL, enc_getacl, dec_getacl),
7513 PROC(SETACL, enc_setacl, dec_setacl),
7514 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
7515 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00007516 PROC(SECINFO, enc_secinfo, dec_secinfo),
Chuck Lever44c99932013-10-17 14:13:30 -04007517 PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present),
Benny Halevy99fe60d2009-04-01 09:22:29 -04007518#if defined(CONFIG_NFS_V4_1)
Chuck Lever7d93bd712010-12-14 14:57:42 +00007519 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
7520 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
7521 PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
7522 PROC(SEQUENCE, enc_sequence, dec_sequence),
7523 PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
7524 PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete),
7525 PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo),
7526 PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
Andy Adamson863a3c62011-03-23 13:27:54 +00007527 PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
Benny Halevycbe82602011-05-22 19:52:37 +03007528 PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn),
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007529 PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name),
Bryan Schumaker7d974792011-06-02 14:59:08 -04007530 PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid),
Bryan Schumaker9aeda352011-06-02 14:59:09 -04007531 PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid),
Anna Schumaker7c61f0d2015-04-14 10:34:20 -04007532 STUB(GETDEVICELIST),
Trond Myklebustad24ecf2012-05-25 17:11:42 -04007533 PROC(BIND_CONN_TO_SESSION,
7534 enc_bind_conn_to_session, dec_bind_conn_to_session),
Trond Myklebust66245532012-05-25 17:18:09 -04007535 PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid),
Benny Halevy99fe60d2009-04-01 09:22:29 -04007536#endif /* CONFIG_NFS_V4_1 */
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007537#ifdef CONFIG_NFS_V4_2
7538 PROC(SEEK, enc_seek, dec_seek),
Anna Schumakerf4ac1672014-11-25 13:18:15 -05007539 PROC(ALLOCATE, enc_allocate, dec_allocate),
Anna Schumaker624bd5b2014-11-25 13:18:16 -05007540 PROC(DEALLOCATE, enc_deallocate, dec_deallocate),
Trond Myklebustbe3a5d22015-06-23 19:51:55 +08007541 PROC(LAYOUTSTATS, enc_layoutstats, dec_layoutstats),
Peng Tao36022772015-09-26 02:24:34 +08007542 PROC(CLONE, enc_clone, dec_clone),
Anna Schumaker2e724482013-05-21 16:53:03 -04007543 PROC(COPY, enc_copy, dec_copy),
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007544#endif /* CONFIG_NFS_V4_2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007545};
7546
Trond Myklebusta613fa12012-01-20 13:53:56 -05007547const struct rpc_version nfs_version4 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007548 .number = 4,
Tobias Klausere8c96f82006-03-24 03:15:34 -08007549 .nrprocs = ARRAY_SIZE(nfs4_procedures),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007550 .procs = nfs4_procedures
7551};
7552
7553/*
7554 * Local variables:
7555 * c-basic-offset: 8
7556 * End:
7557 */