blob: 1af6268a7d8c4c71779d3b64f7ce087b431df723 [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>
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -050055#include <linux/fs_struct.h>
Chuck Leverf0920752012-05-21 22:45:41 -040056
Trond Myklebust4ce79712005-06-22 17:16:21 +000057#include "nfs4_fs.h"
Alexandros Batsakis4882ef72009-12-05 13:30:21 -050058#include "internal.h"
Anna Schumaker40c64c22015-04-15 13:00:05 -040059#include "nfs4idmap.h"
Trond Myklebust76e697b2012-11-26 14:20:49 -050060#include "nfs4session.h"
Andy Adamsonb1f69b72010-10-20 00:18:03 -040061#include "pnfs.h"
Chuck Leverf0920752012-05-21 22:45:41 -040062#include "netns.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070063
64#define NFSDBG_FACILITY NFSDBG_XDR
65
66/* Mapping from NFS error code to "errno" error code. */
67#define errno_NFSERR_IO EIO
68
David Howells0a8ea432006-08-22 20:06:08 -040069static int nfs4_stat_to_errno(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -070070
71/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
72#ifdef DEBUG
73#define NFS4_MAXTAGLEN 20
74#else
75#define NFS4_MAXTAGLEN 0
76#endif
77
Andy Adamson6c0195a2008-12-23 16:06:15 -050078/* lock,open owner id:
Trond Myklebust9f958ab2007-07-02 13:58:33 -040079 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070080 */
Trond Myklebust95b72eb2012-04-20 19:24:51 -040081#define open_owner_id_maxsz (1 + 2 + 1 + 1 + 2)
Trond Myklebustd035c362010-12-21 10:45:27 -050082#define lock_owner_id_maxsz (1 + 1 + 4)
Trond Myklebust9104a552007-07-17 21:52:42 -040083#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
85#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
86#define op_encode_hdr_maxsz (1)
87#define op_decode_hdr_maxsz (2)
Trond Myklebust9104a552007-07-17 21:52:42 -040088#define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
89#define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
90#define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
91#define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -070092#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
93 (NFS4_FHSIZE >> 2))
94#define decode_putfh_maxsz (op_decode_hdr_maxsz)
95#define encode_putrootfh_maxsz (op_encode_hdr_maxsz)
96#define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
97#define encode_getfh_maxsz (op_encode_hdr_maxsz)
98#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
99 ((3+NFS4_FHSIZE) >> 2))
Andy Adamsone5012d12011-07-11 17:17:42 -0400100#define nfs4_fattr_bitmap_maxsz 4
J. Bruce Fields96928202005-06-22 17:16:22 +0000101#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700102#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
103#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
Trond Myklebustbd625ba2007-07-08 18:38:23 -0400104#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
105#define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
David Quigleyaa9c2662013-05-22 12:50:44 -0400106#ifdef CONFIG_NFS_V4_SECURITY_LABEL
107/* PI(4 bytes) + LFS(4 bytes) + 1(for null terminator?) + MAXLABELLEN */
108#define nfs4_label_maxsz (4 + 4 + 1 + XDR_QUADLEN(NFS4_MAXLABELLEN))
David Quigleyaa9c2662013-05-22 12:50:44 -0400109#else
110#define nfs4_label_maxsz 0
David Quigleyaa9c2662013-05-22 12:50:44 -0400111#endif
Andy Adamson88034c32012-05-23 05:02:34 -0400112/* We support only one layout type per file system */
113#define decode_mdsthreshold_maxsz (1 + 1 + nfs4_fattr_bitmap_maxsz + 1 + 8)
J. Bruce Fields96928202005-06-22 17:16:22 +0000114/* This is based on getfattr, which uses the most attributes: */
115#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
Andy Adamson88034c32012-05-23 05:02:34 -0400116 3 + 3 + 3 + nfs4_owner_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400117 nfs4_group_maxsz + nfs4_label_maxsz + \
118 decode_mdsthreshold_maxsz))
J. Bruce Fields96928202005-06-22 17:16:22 +0000119#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
120 nfs4_fattr_value_maxsz)
121#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400122#define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \
123 1 + 2 + 1 + \
124 nfs4_owner_maxsz + \
125 nfs4_group_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400126 nfs4_label_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400127 4 + 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700128#define encode_savefh_maxsz (op_encode_hdr_maxsz)
129#define decode_savefh_maxsz (op_decode_hdr_maxsz)
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400130#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
131#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
Fred Isaman2f42b5d2008-03-13 15:26:30 +0200132#define encode_fsinfo_maxsz (encode_getattr_maxsz)
Fred Isamandae100c2011-07-30 20:52:37 -0400133/* The 5 accounts for the PNFS attributes, and assumes that at most three
134 * layout types will be returned.
135 */
136#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + \
137 nfs4_fattr_bitmap_maxsz + 4 + 8 + 5)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700138#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
139#define decode_renew_maxsz (op_decode_hdr_maxsz)
140#define encode_setclientid_maxsz \
141 (op_encode_hdr_maxsz + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500142 XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
Jeff Laytonb8fb2f52015-06-09 19:43:58 -0400143 /* client name */ \
144 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500145 1 /* sc_prog */ + \
Chuck Lever6dd34362014-11-08 20:15:18 -0500146 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
147 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500148 1) /* sc_cb_ident */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700149#define decode_setclientid_maxsz \
150 (op_decode_hdr_maxsz + \
Chuck Lever6dd34362014-11-08 20:15:18 -0500151 2 /* clientid */ + \
152 XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
153 1 + XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
154 1 + XDR_QUADLEN(RPCBIND_MAXUADDRLEN))
Linus Torvalds1da177e2005-04-16 15:20:36 -0700155#define encode_setclientid_confirm_maxsz \
156 (op_encode_hdr_maxsz + \
157 3 + (NFS4_VERIFIER_SIZE >> 2))
158#define decode_setclientid_confirm_maxsz \
159 (op_decode_hdr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400160#define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
161#define decode_lookup_maxsz (op_decode_hdr_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400162#define encode_share_access_maxsz \
163 (2)
Alexandros Batsakis4882ef72009-12-05 13:30:21 -0500164#define encode_createmode_maxsz (1 + encode_attrs_maxsz + encode_verifier_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400165#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
166#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
167#define encode_open_maxsz (op_encode_hdr_maxsz + \
168 2 + encode_share_access_maxsz + 2 + \
169 open_owner_id_maxsz + \
170 encode_opentype_maxsz + \
171 encode_claim_null_maxsz)
172#define decode_ace_maxsz (3 + nfs4_owner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400173#define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400174 decode_ace_maxsz)
175#define decode_change_info_maxsz (5)
176#define decode_open_maxsz (op_decode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400177 decode_stateid_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400178 decode_change_info_maxsz + 1 + \
179 nfs4_fattr_bitmap_maxsz + \
180 decode_delegation_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400181#define encode_open_confirm_maxsz \
182 (op_encode_hdr_maxsz + \
183 encode_stateid_maxsz + 1)
184#define decode_open_confirm_maxsz \
185 (op_decode_hdr_maxsz + \
186 decode_stateid_maxsz)
187#define encode_open_downgrade_maxsz \
188 (op_encode_hdr_maxsz + \
189 encode_stateid_maxsz + 1 + \
190 encode_share_access_maxsz)
191#define decode_open_downgrade_maxsz \
192 (op_decode_hdr_maxsz + \
193 decode_stateid_maxsz)
194#define encode_close_maxsz (op_encode_hdr_maxsz + \
195 1 + encode_stateid_maxsz)
196#define decode_close_maxsz (op_decode_hdr_maxsz + \
197 decode_stateid_maxsz)
198#define encode_setattr_maxsz (op_encode_hdr_maxsz + \
199 encode_stateid_maxsz + \
200 encode_attrs_maxsz)
201#define decode_setattr_maxsz (op_decode_hdr_maxsz + \
202 nfs4_fattr_bitmap_maxsz)
203#define encode_read_maxsz (op_encode_hdr_maxsz + \
204 encode_stateid_maxsz + 3)
205#define decode_read_maxsz (op_decode_hdr_maxsz + 2)
206#define encode_readdir_maxsz (op_encode_hdr_maxsz + \
David Quigleyaa9c2662013-05-22 12:50:44 -0400207 2 + encode_verifier_maxsz + 5 + \
208 nfs4_label_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400209#define decode_readdir_maxsz (op_decode_hdr_maxsz + \
Chuck Levera7697f62014-03-12 12:51:17 -0400210 decode_verifier_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400211#define encode_readlink_maxsz (op_encode_hdr_maxsz)
212#define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
213#define encode_write_maxsz (op_encode_hdr_maxsz + \
214 encode_stateid_maxsz + 4)
215#define decode_write_maxsz (op_decode_hdr_maxsz + \
216 2 + decode_verifier_maxsz)
217#define encode_commit_maxsz (op_encode_hdr_maxsz + 3)
218#define decode_commit_maxsz (op_decode_hdr_maxsz + \
219 decode_verifier_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220#define encode_remove_maxsz (op_encode_hdr_maxsz + \
221 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400222#define decode_remove_maxsz (op_decode_hdr_maxsz + \
223 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700224#define encode_rename_maxsz (op_encode_hdr_maxsz + \
225 2 * nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400226#define decode_rename_maxsz (op_decode_hdr_maxsz + \
227 decode_change_info_maxsz + \
228 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700229#define encode_link_maxsz (op_encode_hdr_maxsz + \
230 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400231#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400232#define encode_lockowner_maxsz (7)
Trond Myklebust9104a552007-07-17 21:52:42 -0400233#define encode_lock_maxsz (op_encode_hdr_maxsz + \
234 7 + \
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400235 1 + encode_stateid_maxsz + 1 + \
236 encode_lockowner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400237#define decode_lock_denied_maxsz \
238 (8 + decode_lockowner_maxsz)
239#define decode_lock_maxsz (op_decode_hdr_maxsz + \
240 decode_lock_denied_maxsz)
Trond Myklebustdaccbde2010-06-25 18:11:43 -0400241#define encode_lockt_maxsz (op_encode_hdr_maxsz + 5 + \
242 encode_lockowner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400243#define decode_lockt_maxsz (op_decode_hdr_maxsz + \
244 decode_lock_denied_maxsz)
245#define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
246 encode_stateid_maxsz + \
247 4)
248#define decode_locku_maxsz (op_decode_hdr_maxsz + \
249 decode_stateid_maxsz)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -0400250#define encode_release_lockowner_maxsz \
251 (op_encode_hdr_maxsz + \
252 encode_lockowner_maxsz)
253#define decode_release_lockowner_maxsz \
254 (op_decode_hdr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400255#define encode_access_maxsz (op_encode_hdr_maxsz + 1)
256#define decode_access_maxsz (op_decode_hdr_maxsz + 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700257#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
258 1 + nfs4_name_maxsz + \
Chuck Lever94a6d752006-08-22 20:06:23 -0400259 1 + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000260 nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700261#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
262#define encode_create_maxsz (op_encode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400263 1 + 2 + nfs4_name_maxsz + \
264 encode_attrs_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400265#define decode_create_maxsz (op_decode_hdr_maxsz + \
266 decode_change_info_maxsz + \
267 nfs4_fattr_bitmap_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400268#define encode_statfs_maxsz (encode_getattr_maxsz)
269#define decode_statfs_maxsz (decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700270#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
271#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400272#define encode_getacl_maxsz (encode_getattr_maxsz)
273#define decode_getacl_maxsz (op_decode_hdr_maxsz + \
274 nfs4_fattr_bitmap_maxsz + 1)
275#define encode_setacl_maxsz (op_encode_hdr_maxsz + \
276 encode_stateid_maxsz + 3)
277#define decode_setacl_maxsz (decode_setattr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400278#define encode_fs_locations_maxsz \
279 (encode_getattr_maxsz)
280#define decode_fs_locations_maxsz \
281 (0)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +0000282#define encode_secinfo_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
Bryan Schumaker1650add2011-06-02 15:07:35 -0400283#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 -0400284
285#if defined(CONFIG_NFS_V4_1)
Andy Adamsonfc931582009-04-01 09:22:31 -0400286#define NFS4_MAX_MACHINE_NAME_LEN (64)
Jim Reesd751f742012-11-16 18:12:06 -0500287#define IMPL_NAME_LIMIT (sizeof(utsname()->sysname) + sizeof(utsname()->release) + \
288 sizeof(utsname()->version) + sizeof(utsname()->machine) + 8)
Andy Adamsonfc931582009-04-01 09:22:31 -0400289
Benny Halevy99fe60d2009-04-01 09:22:29 -0400290#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
291 encode_verifier_maxsz + \
292 1 /* co_ownerid.len */ + \
Jeff Laytonb8fb2f52015-06-09 19:43:58 -0400293 /* eia_clientowner */ \
294 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
Benny Halevy99fe60d2009-04-01 09:22:29 -0400295 1 /* flags */ + \
296 1 /* spa_how */ + \
Weston Andros Adamson2031cd12013-08-13 16:37:32 -0400297 /* max is SP4_MACH_CRED (for now) */ + \
298 1 + NFS4_OP_MAP_NUM_WORDS + \
299 1 + NFS4_OP_MAP_NUM_WORDS + \
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -0500300 1 /* implementation id array of size 1 */ + \
301 1 /* nii_domain */ + \
302 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
303 1 /* nii_name */ + \
Jim Reesd751f742012-11-16 18:12:06 -0500304 XDR_QUADLEN(IMPL_NAME_LIMIT) + \
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -0500305 3 /* nii_date */)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400306#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
307 2 /* eir_clientid */ + \
308 1 /* eir_sequenceid */ + \
309 1 /* eir_flags */ + \
310 1 /* spr_how */ + \
Weston Andros Adamson2031cd12013-08-13 16:37:32 -0400311 /* max is SP4_MACH_CRED (for now) */ + \
312 1 + NFS4_OP_MAP_NUM_WORDS + \
313 1 + NFS4_OP_MAP_NUM_WORDS + \
Benny Halevy99fe60d2009-04-01 09:22:29 -0400314 2 /* eir_server_owner.so_minor_id */ + \
315 /* eir_server_owner.so_major_id<> */ \
316 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
317 /* eir_server_scope<> */ \
318 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
319 1 /* eir_server_impl_id array length */ + \
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -0500320 1 /* nii_domain */ + \
321 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
322 1 /* nii_name */ + \
323 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + \
324 3 /* nii_date */)
Andy Adamsonfc931582009-04-01 09:22:31 -0400325#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
326#define decode_channel_attrs_maxsz (6 + \
327 1 /* ca_rdma_ird.len */ + \
328 1 /* ca_rdma_ird */)
329#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
330 2 /* csa_clientid */ + \
331 1 /* csa_sequence */ + \
332 1 /* csa_flags */ + \
333 encode_channel_attrs_maxsz + \
334 encode_channel_attrs_maxsz + \
335 1 /* csa_cb_program */ + \
336 1 /* csa_sec_parms.len (1) */ + \
337 1 /* cb_secflavor (AUTH_SYS) */ + \
338 1 /* stamp */ + \
339 1 /* machinename.len */ + \
340 XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
341 1 /* uid */ + \
342 1 /* gid */ + \
343 1 /* gids.len (0) */)
344#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
345 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
346 1 /* csr_sequence */ + \
347 1 /* csr_flags */ + \
348 decode_channel_attrs_maxsz + \
349 decode_channel_attrs_maxsz)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -0400350#define encode_bind_conn_to_session_maxsz (op_encode_hdr_maxsz + \
351 /* bctsa_sessid */ \
352 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
353 1 /* bctsa_dir */ + \
354 1 /* bctsa_use_conn_in_rdma_mode */)
355#define decode_bind_conn_to_session_maxsz (op_decode_hdr_maxsz + \
356 /* bctsr_sessid */ \
357 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
358 1 /* bctsr_dir */ + \
359 1 /* bctsr_use_conn_in_rdma_mode */)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400360#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
361#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
Trond Myklebust66245532012-05-25 17:18:09 -0400362#define encode_destroy_clientid_maxsz (op_encode_hdr_maxsz + 2)
363#define decode_destroy_clientid_maxsz (op_decode_hdr_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400364#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
365 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
366#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
367 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
Ricardo Labiaga180197532009-12-05 16:08:40 -0500368#define encode_reclaim_complete_maxsz (op_encode_hdr_maxsz + 4)
369#define decode_reclaim_complete_maxsz (op_decode_hdr_maxsz + 4)
Christoph Hellwig84c9dee2014-09-10 17:37:28 -0700370#define encode_getdeviceinfo_maxsz (op_encode_hdr_maxsz + \
371 XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
372 1 /* layout type */ + \
373 1 /* maxcount */ + \
374 1 /* bitmap size */ + \
375 1 /* notification bitmap length */ + \
376 1 /* notification bitmap, word 0 */)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400377#define decode_getdeviceinfo_maxsz (op_decode_hdr_maxsz + \
378 1 /* layout type */ + \
379 1 /* opaque devaddr4 length */ + \
380 /* devaddr4 payload is read into page */ \
381 1 /* notification bitmap length */ + \
Christoph Hellwig84c9dee2014-09-10 17:37:28 -0700382 1 /* notification bitmap, word 0 */)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400383#define encode_layoutget_maxsz (op_encode_hdr_maxsz + 10 + \
384 encode_stateid_maxsz)
385#define decode_layoutget_maxsz (op_decode_hdr_maxsz + 8 + \
386 decode_stateid_maxsz + \
387 XDR_QUADLEN(PNFS_LAYOUT_MAXSIZE))
Andy Adamson863a3c62011-03-23 13:27:54 +0000388#define encode_layoutcommit_maxsz (op_encode_hdr_maxsz + \
389 2 /* offset */ + \
390 2 /* length */ + \
391 1 /* reclaim */ + \
392 encode_stateid_maxsz + \
393 1 /* new offset (true) */ + \
394 2 /* last byte written */ + \
395 1 /* nt_timechanged (false) */ + \
396 1 /* layoutupdate4 layout type */ + \
Christoph Hellwig5f919c92014-08-21 11:09:25 -0500397 1 /* layoutupdate4 opaqueue len */)
398 /* the actual content of layoutupdate4 should
399 be allocated by drivers and spliced in
400 using xdr_write_pages */
Andy Adamson863a3c62011-03-23 13:27:54 +0000401#define decode_layoutcommit_maxsz (op_decode_hdr_maxsz + 3)
Benny Halevycbe82602011-05-22 19:52:37 +0300402#define encode_layoutreturn_maxsz (8 + op_encode_hdr_maxsz + \
403 encode_stateid_maxsz + \
Trond Myklebust6669cb82015-08-27 20:43:20 -0400404 1 + \
405 XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
Benny Halevycbe82602011-05-22 19:52:37 +0300406#define decode_layoutreturn_maxsz (op_decode_hdr_maxsz + \
407 1 + decode_stateid_maxsz)
Bryan Schumakerfca78d62011-06-02 14:59:07 -0400408#define encode_secinfo_no_name_maxsz (op_encode_hdr_maxsz + 1)
409#define decode_secinfo_no_name_maxsz decode_secinfo_maxsz
Bryan Schumaker7d974792011-06-02 14:59:08 -0400410#define encode_test_stateid_maxsz (op_encode_hdr_maxsz + 2 + \
411 XDR_QUADLEN(NFS4_STATEID_SIZE))
412#define decode_test_stateid_maxsz (op_decode_hdr_maxsz + 2 + 1)
Bryan Schumaker9aeda352011-06-02 14:59:09 -0400413#define encode_free_stateid_maxsz (op_encode_hdr_maxsz + 1 + \
414 XDR_QUADLEN(NFS4_STATEID_SIZE))
Andy Adamson9f79fb42013-09-10 12:56:29 -0400415#define decode_free_stateid_maxsz (op_decode_hdr_maxsz)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400416#else /* CONFIG_NFS_V4_1 */
417#define encode_sequence_maxsz 0
418#define decode_sequence_maxsz 0
Trond Myklebustcf805162016-11-15 14:56:07 -0500419#define encode_layoutreturn_maxsz 0
420#define decode_layoutreturn_maxsz 0
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400421#endif /* CONFIG_NFS_V4_1 */
422
Linus Torvalds1da177e2005-04-16 15:20:36 -0700423#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
424#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
425#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400426 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700427 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400428 encode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700429#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400430 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700431 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400432 decode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700433#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400434 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700435 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400436 encode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700437#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400438 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700439 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400440 decode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700441#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400442 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700443 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400444 encode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700445#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400446 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700447 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400448 decode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700449#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400450 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700451 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400452 encode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400453 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400455 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400457 decode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400458 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700459#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400460 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700461 encode_putfh_maxsz + \
Trond Myklebust85827152012-04-29 10:44:42 -0400462 encode_commit_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700463#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400464 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700465 decode_putfh_maxsz + \
Trond Myklebust85827152012-04-29 10:44:42 -0400466 decode_commit_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700467#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400468 encode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400469 encode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400470 encode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400471 encode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400472 encode_getfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400473 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400475 decode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400476 decode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400477 decode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400478 decode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400479 decode_getfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400480 decode_getattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400481#define NFS4_enc_open_confirm_sz \
482 (compound_encode_hdr_maxsz + \
483 encode_putfh_maxsz + \
484 encode_open_confirm_maxsz)
485#define NFS4_dec_open_confirm_sz \
486 (compound_decode_hdr_maxsz + \
487 decode_putfh_maxsz + \
488 decode_open_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700489#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400490 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700491 encode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400492 encode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400493 encode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400494 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700495#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400496 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700497 decode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400498 decode_open_maxsz + \
Weston Andros Adamson6168f622012-09-10 14:00:46 -0400499 decode_access_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400500 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700501#define NFS4_enc_open_downgrade_sz \
502 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400503 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400504 encode_putfh_maxsz + \
Trond Myklebust3947b742016-10-27 18:27:02 -0400505 encode_open_downgrade_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700506#define NFS4_dec_open_downgrade_sz \
507 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400508 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400509 decode_putfh_maxsz + \
Trond Myklebust3947b742016-10-27 18:27:02 -0400510 decode_open_downgrade_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400511#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400512 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400513 encode_putfh_maxsz + \
Trond Myklebustcf805162016-11-15 14:56:07 -0500514 encode_layoutreturn_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400515 encode_close_maxsz + \
516 encode_getattr_maxsz)
517#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400518 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400519 decode_putfh_maxsz + \
Trond Myklebustcf805162016-11-15 14:56:07 -0500520 decode_layoutreturn_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400521 decode_close_maxsz + \
522 decode_getattr_maxsz)
523#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400524 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400525 encode_putfh_maxsz + \
526 encode_setattr_maxsz + \
527 encode_getattr_maxsz)
528#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400529 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400530 decode_putfh_maxsz + \
531 decode_setattr_maxsz + \
532 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400534 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700535 encode_putfh_maxsz + \
536 encode_fsinfo_maxsz)
537#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400538 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700539 decode_putfh_maxsz + \
540 decode_fsinfo_maxsz)
541#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
542 encode_renew_maxsz)
543#define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \
544 decode_renew_maxsz)
545#define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \
546 encode_setclientid_maxsz)
547#define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \
548 decode_setclientid_maxsz)
549#define NFS4_enc_setclientid_confirm_sz \
550 (compound_encode_hdr_maxsz + \
Chuck Lever83ca7f52013-03-16 15:55:53 -0400551 encode_setclientid_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700552#define NFS4_dec_setclientid_confirm_sz \
553 (compound_decode_hdr_maxsz + \
Chuck Lever83ca7f52013-03-16 15:55:53 -0400554 decode_setclientid_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700555#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400556 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700557 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400558 encode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700559#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400560 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700561 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400562 decode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700563#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400564 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700565 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400566 encode_lockt_maxsz)
567#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400568 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400569 decode_putfh_maxsz + \
570 decode_lockt_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700571#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400572 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700573 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400574 encode_locku_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700575#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400576 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700577 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400578 decode_locku_maxsz)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -0400579#define NFS4_enc_release_lockowner_sz \
580 (compound_encode_hdr_maxsz + \
581 encode_lockowner_maxsz)
582#define NFS4_dec_release_lockowner_sz \
583 (compound_decode_hdr_maxsz + \
584 decode_lockowner_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400586 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700587 encode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400588 encode_access_maxsz + \
589 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400591 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700592 decode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400593 decode_access_maxsz + \
594 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700595#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400596 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700597 encode_putfh_maxsz + \
Chuck Lever44c99932013-10-17 14:13:30 -0400598 encode_getattr_maxsz + \
599 encode_renew_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400601 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700602 decode_putfh_maxsz + \
Chuck Lever44c99932013-10-17 14:13:30 -0400603 decode_getattr_maxsz + \
604 decode_renew_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700605#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400606 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 encode_putfh_maxsz + \
608 encode_lookup_maxsz + \
609 encode_getattr_maxsz + \
610 encode_getfh_maxsz)
611#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400612 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700613 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400614 decode_lookup_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700615 decode_getattr_maxsz + \
616 decode_getfh_maxsz)
617#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400618 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700619 encode_putrootfh_maxsz + \
620 encode_getattr_maxsz + \
621 encode_getfh_maxsz)
622#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400623 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700624 decode_putrootfh_maxsz + \
625 decode_getattr_maxsz + \
626 decode_getfh_maxsz)
627#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400628 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700629 encode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400630 encode_remove_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700631#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400632 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700633 decode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400634 decode_remove_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700635#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400636 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700637 encode_putfh_maxsz + \
638 encode_savefh_maxsz + \
639 encode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400640 encode_rename_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700641#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400642 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700643 decode_putfh_maxsz + \
644 decode_savefh_maxsz + \
645 decode_putfh_maxsz + \
Trond Myklebust778d2812012-04-27 13:48:19 -0400646 decode_rename_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700647#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400648 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700649 encode_putfh_maxsz + \
650 encode_savefh_maxsz + \
651 encode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400652 encode_link_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400653 encode_restorefh_maxsz + \
Trond Myklebusta9f69912012-04-27 13:48:17 -0400654 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700655#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400656 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700657 decode_putfh_maxsz + \
658 decode_savefh_maxsz + \
659 decode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400660 decode_link_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400661 decode_restorefh_maxsz + \
662 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700663#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400664 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700665 encode_putfh_maxsz + \
666 encode_symlink_maxsz + \
667 encode_getattr_maxsz + \
668 encode_getfh_maxsz)
669#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400670 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700671 decode_putfh_maxsz + \
672 decode_symlink_maxsz + \
673 decode_getattr_maxsz + \
674 decode_getfh_maxsz)
675#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400676 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700677 encode_putfh_maxsz + \
678 encode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400679 encode_getfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400680 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400682 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700683 decode_putfh_maxsz + \
684 decode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400685 decode_getfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400686 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700687#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400688 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700689 encode_putfh_maxsz + \
690 encode_getattr_maxsz)
691#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400692 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693 decode_putfh_maxsz + \
694 decode_getattr_maxsz)
695#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400696 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700697 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400698 encode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400700 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400702 decode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400704 encode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800705 encode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700706 encode_getattr_maxsz)
707#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400708 decode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800709 decode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700710 decode_getattr_maxsz)
711#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400712 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700713 encode_putfh_maxsz + \
Trond Myklebust586f1c32016-11-15 15:03:33 -0500714 encode_layoutreturn_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100715 encode_delegreturn_maxsz + \
716 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700717#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400718 decode_sequence_maxsz + \
Trond Myklebustd8434d4c2016-11-16 13:54:00 -0500719 decode_putfh_maxsz + \
Trond Myklebust586f1c32016-11-15 15:03:33 -0500720 decode_layoutreturn_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100721 decode_delegreturn_maxsz + \
722 decode_getattr_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000723#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400724 encode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000725 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400726 encode_getacl_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000727#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400728 decode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000729 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400730 decode_getacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000731#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400732 encode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000733 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400734 encode_setacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000735#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400736 decode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000737 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400738 decode_setacl_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400739#define NFS4_enc_fs_locations_sz \
740 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400741 encode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400742 encode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400743 encode_lookup_maxsz + \
Chuck Leverb03d7352013-10-17 14:12:50 -0400744 encode_fs_locations_maxsz + \
745 encode_renew_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400746#define NFS4_dec_fs_locations_sz \
747 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400748 decode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400749 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400750 decode_lookup_maxsz + \
Chuck Leverb03d7352013-10-17 14:12:50 -0400751 decode_fs_locations_maxsz + \
752 decode_renew_maxsz)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +0000753#define NFS4_enc_secinfo_sz (compound_encode_hdr_maxsz + \
754 encode_sequence_maxsz + \
755 encode_putfh_maxsz + \
756 encode_secinfo_maxsz)
757#define NFS4_dec_secinfo_sz (compound_decode_hdr_maxsz + \
758 decode_sequence_maxsz + \
759 decode_putfh_maxsz + \
760 decode_secinfo_maxsz)
Chuck Lever44c99932013-10-17 14:13:30 -0400761#define NFS4_enc_fsid_present_sz \
762 (compound_encode_hdr_maxsz + \
763 encode_sequence_maxsz + \
764 encode_putfh_maxsz + \
765 encode_getfh_maxsz + \
766 encode_renew_maxsz)
767#define NFS4_dec_fsid_present_sz \
768 (compound_decode_hdr_maxsz + \
769 decode_sequence_maxsz + \
770 decode_putfh_maxsz + \
771 decode_getfh_maxsz + \
772 decode_renew_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400773#if defined(CONFIG_NFS_V4_1)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -0400774#define NFS4_enc_bind_conn_to_session_sz \
775 (compound_encode_hdr_maxsz + \
776 encode_bind_conn_to_session_maxsz)
777#define NFS4_dec_bind_conn_to_session_sz \
778 (compound_decode_hdr_maxsz + \
779 decode_bind_conn_to_session_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400780#define NFS4_enc_exchange_id_sz \
781 (compound_encode_hdr_maxsz + \
782 encode_exchange_id_maxsz)
783#define NFS4_dec_exchange_id_sz \
784 (compound_decode_hdr_maxsz + \
785 decode_exchange_id_maxsz)
Andy Adamsonfc931582009-04-01 09:22:31 -0400786#define NFS4_enc_create_session_sz \
787 (compound_encode_hdr_maxsz + \
788 encode_create_session_maxsz)
789#define NFS4_dec_create_session_sz \
790 (compound_decode_hdr_maxsz + \
791 decode_create_session_maxsz)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400792#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
793 encode_destroy_session_maxsz)
794#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
795 decode_destroy_session_maxsz)
Trond Myklebust66245532012-05-25 17:18:09 -0400796#define NFS4_enc_destroy_clientid_sz (compound_encode_hdr_maxsz + \
797 encode_destroy_clientid_maxsz)
798#define NFS4_dec_destroy_clientid_sz (compound_decode_hdr_maxsz + \
799 decode_destroy_clientid_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400800#define NFS4_enc_sequence_sz \
801 (compound_decode_hdr_maxsz + \
802 encode_sequence_maxsz)
803#define NFS4_dec_sequence_sz \
804 (compound_decode_hdr_maxsz + \
805 decode_sequence_maxsz)
Andy Adamson2050f0c2009-04-01 09:22:30 -0400806#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
807 encode_sequence_maxsz + \
808 encode_putrootfh_maxsz + \
809 encode_fsinfo_maxsz)
810#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
811 decode_sequence_maxsz + \
812 decode_putrootfh_maxsz + \
813 decode_fsinfo_maxsz)
Ricardo Labiaga180197532009-12-05 16:08:40 -0500814#define NFS4_enc_reclaim_complete_sz (compound_encode_hdr_maxsz + \
815 encode_sequence_maxsz + \
816 encode_reclaim_complete_maxsz)
817#define NFS4_dec_reclaim_complete_sz (compound_decode_hdr_maxsz + \
818 decode_sequence_maxsz + \
819 decode_reclaim_complete_maxsz)
Andy Adamsonb1f69b72010-10-20 00:18:03 -0400820#define NFS4_enc_getdeviceinfo_sz (compound_encode_hdr_maxsz + \
821 encode_sequence_maxsz +\
822 encode_getdeviceinfo_maxsz)
823#define NFS4_dec_getdeviceinfo_sz (compound_decode_hdr_maxsz + \
824 decode_sequence_maxsz + \
825 decode_getdeviceinfo_maxsz)
826#define NFS4_enc_layoutget_sz (compound_encode_hdr_maxsz + \
827 encode_sequence_maxsz + \
828 encode_putfh_maxsz + \
829 encode_layoutget_maxsz)
830#define NFS4_dec_layoutget_sz (compound_decode_hdr_maxsz + \
831 decode_sequence_maxsz + \
832 decode_putfh_maxsz + \
833 decode_layoutget_maxsz)
Andy Adamson863a3c62011-03-23 13:27:54 +0000834#define NFS4_enc_layoutcommit_sz (compound_encode_hdr_maxsz + \
835 encode_sequence_maxsz +\
836 encode_putfh_maxsz + \
837 encode_layoutcommit_maxsz + \
838 encode_getattr_maxsz)
839#define NFS4_dec_layoutcommit_sz (compound_decode_hdr_maxsz + \
840 decode_sequence_maxsz + \
841 decode_putfh_maxsz + \
842 decode_layoutcommit_maxsz + \
843 decode_getattr_maxsz)
Benny Halevycbe82602011-05-22 19:52:37 +0300844#define NFS4_enc_layoutreturn_sz (compound_encode_hdr_maxsz + \
845 encode_sequence_maxsz + \
846 encode_putfh_maxsz + \
847 encode_layoutreturn_maxsz)
848#define NFS4_dec_layoutreturn_sz (compound_decode_hdr_maxsz + \
849 decode_sequence_maxsz + \
850 decode_putfh_maxsz + \
851 decode_layoutreturn_maxsz)
Bryan Schumakerfca78d62011-06-02 14:59:07 -0400852#define NFS4_enc_secinfo_no_name_sz (compound_encode_hdr_maxsz + \
853 encode_sequence_maxsz + \
854 encode_putrootfh_maxsz +\
855 encode_secinfo_no_name_maxsz)
856#define NFS4_dec_secinfo_no_name_sz (compound_decode_hdr_maxsz + \
857 decode_sequence_maxsz + \
858 decode_putrootfh_maxsz + \
859 decode_secinfo_no_name_maxsz)
Bryan Schumaker7d974792011-06-02 14:59:08 -0400860#define NFS4_enc_test_stateid_sz (compound_encode_hdr_maxsz + \
861 encode_sequence_maxsz + \
862 encode_test_stateid_maxsz)
863#define NFS4_dec_test_stateid_sz (compound_decode_hdr_maxsz + \
864 decode_sequence_maxsz + \
865 decode_test_stateid_maxsz)
Bryan Schumaker9aeda352011-06-02 14:59:09 -0400866#define NFS4_enc_free_stateid_sz (compound_encode_hdr_maxsz + \
867 encode_sequence_maxsz + \
868 encode_free_stateid_maxsz)
869#define NFS4_dec_free_stateid_sz (compound_decode_hdr_maxsz + \
870 decode_sequence_maxsz + \
871 decode_free_stateid_maxsz)
Alexandros Batsakis2449ea22009-12-05 13:36:55 -0500872
873const u32 nfs41_maxwrite_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
874 compound_encode_hdr_maxsz +
875 encode_sequence_maxsz +
876 encode_putfh_maxsz +
877 encode_getattr_maxsz) *
878 XDR_UNIT);
879
880const u32 nfs41_maxread_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
881 compound_decode_hdr_maxsz +
882 decode_sequence_maxsz +
883 decode_putfh_maxsz) *
884 XDR_UNIT);
Andy Adamsonf1c097b2013-06-25 19:02:53 -0400885
886const u32 nfs41_maxgetdevinfo_overhead = ((RPC_MAX_REPHEADER_WITH_AUTH +
887 compound_decode_hdr_maxsz +
888 decode_sequence_maxsz) *
889 XDR_UNIT);
890EXPORT_SYMBOL_GPL(nfs41_maxgetdevinfo_overhead);
Benny Halevy99fe60d2009-04-01 09:22:29 -0400891#endif /* CONFIG_NFS_V4_1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700892
Trond Myklebustbca79472009-03-11 14:10:26 -0400893static const umode_t nfs_type2fmt[] = {
894 [NF4BAD] = 0,
895 [NF4REG] = S_IFREG,
896 [NF4DIR] = S_IFDIR,
897 [NF4BLK] = S_IFBLK,
898 [NF4CHR] = S_IFCHR,
899 [NF4LNK] = S_IFLNK,
900 [NF4SOCK] = S_IFSOCK,
901 [NF4FIFO] = S_IFIFO,
902 [NF4ATTRDIR] = 0,
903 [NF4NAMEDATTR] = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700904};
905
906struct compound_hdr {
907 int32_t status;
908 uint32_t nops;
Andy Adamsond0179312008-12-23 16:06:17 -0500909 __be32 * nops_p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700910 uint32_t taglen;
911 char * tag;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400912 uint32_t replen; /* expected reply words */
Benny Halevy66cc0422009-04-01 09:22:10 -0400913 u32 minorversion;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700914};
915
Benny Halevy13c65ce2009-08-14 17:19:25 +0300916static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
917{
918 __be32 *p = xdr_reserve_space(xdr, nbytes);
919 BUG_ON(!p);
920 return p;
921}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700922
Trond Myklebustcb17e552012-03-04 18:13:56 -0500923static void encode_opaque_fixed(struct xdr_stream *xdr, const void *buf, size_t len)
924{
925 __be32 *p;
926
927 p = xdr_reserve_space(xdr, len);
928 xdr_encode_opaque_fixed(p, buf, len);
929}
930
Linus Torvalds1da177e2005-04-16 15:20:36 -0700931static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
932{
Al Viro8687b632006-10-19 23:28:48 -0700933 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700934
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -0500935 p = reserve_space(xdr, 4 + len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 xdr_encode_opaque(p, str, len);
937}
938
Trond Myklebust4ade9822012-03-04 18:13:57 -0500939static void encode_uint32(struct xdr_stream *xdr, u32 n)
940{
941 __be32 *p;
942
943 p = reserve_space(xdr, 4);
944 *p = cpu_to_be32(n);
945}
946
Trond Myklebustff2eb682012-03-05 11:40:12 -0500947static void encode_uint64(struct xdr_stream *xdr, u64 n)
948{
949 __be32 *p;
950
951 p = reserve_space(xdr, 8);
952 xdr_encode_hyper(p, n);
953}
954
Trond Myklebust4ade9822012-03-04 18:13:57 -0500955static void encode_nfs4_seqid(struct xdr_stream *xdr,
956 const struct nfs_seqid *seqid)
957{
Trond Myklebusta6796412015-01-23 19:04:44 -0500958 if (seqid != NULL)
959 encode_uint32(xdr, seqid->sequence->counter);
960 else
961 encode_uint32(xdr, 0);
Trond Myklebust4ade9822012-03-04 18:13:57 -0500962}
963
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400964static void encode_compound_hdr(struct xdr_stream *xdr,
965 struct rpc_rqst *req,
966 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700967{
Al Viro8687b632006-10-19 23:28:48 -0700968 __be32 *p;
Trond Myklebusta17c2152010-07-31 14:29:08 -0400969 struct rpc_auth *auth = req->rq_cred->cr_auth;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400970
971 /* initialize running count of expected bytes in reply.
972 * NOTE: the replied tag SHOULD be the same is the one sent,
973 * but this is not required as a MUST for the server to do so. */
974 hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700975
Trond Myklebust7fc38842012-10-15 11:51:21 -0400976 WARN_ON_ONCE(hdr->taglen > NFS4_MAXTAGLEN);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -0500977 encode_string(xdr, hdr->taglen, hdr->tag);
978 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300979 *p++ = cpu_to_be32(hdr->minorversion);
Andy Adamsond0179312008-12-23 16:06:17 -0500980 hdr->nops_p = p;
Benny Halevy34558512009-08-14 17:19:30 +0300981 *p = cpu_to_be32(hdr->nops);
Andy Adamsond0179312008-12-23 16:06:17 -0500982}
983
Trond Myklebustab19b482012-03-04 18:13:57 -0500984static void encode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 op,
985 uint32_t replen,
986 struct compound_hdr *hdr)
987{
988 encode_uint32(xdr, op);
989 hdr->nops++;
990 hdr->replen += replen;
991}
992
Andy Adamsond0179312008-12-23 16:06:17 -0500993static void encode_nops(struct compound_hdr *hdr)
994{
Trond Myklebust7fc38842012-10-15 11:51:21 -0400995 WARN_ON_ONCE(hdr->nops > NFS4_MAX_OPS);
Andy Adamsond0179312008-12-23 16:06:17 -0500996 *hdr->nops_p = htonl(hdr->nops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997}
998
Trond Myklebustea9d23f2012-03-04 18:13:56 -0500999static void encode_nfs4_stateid(struct xdr_stream *xdr, const nfs4_stateid *stateid)
1000{
Trond Myklebust2d2f24a2012-03-04 18:13:57 -05001001 encode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001002}
1003
Linus Torvalds1da177e2005-04-16 15:20:36 -07001004static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
1005{
Trond Myklebustcb17e552012-03-04 18:13:56 -05001006 encode_opaque_fixed(xdr, verf->data, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007}
1008
David Quigleyaa9c2662013-05-22 12:50:44 -04001009static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap,
1010 const struct nfs4_label *label,
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001011 const struct nfs_server *server,
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001012 bool excl_check, const umode_t *umask)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001013{
1014 char owner_name[IDMAP_NAMESZ];
1015 char owner_group[IDMAP_NAMESZ];
1016 int owner_namelen = 0;
1017 int owner_grouplen = 0;
Al Viro8687b632006-10-19 23:28:48 -07001018 __be32 *p;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001019 unsigned i;
1020 uint32_t len = 0;
1021 uint32_t bmval_len;
1022 uint32_t bmval[3] = { 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001023
1024 /*
1025 * We reserve enough space to write the entire attribute buffer at once.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001026 */
Trond Myklebustd7067b22013-07-17 17:09:01 -04001027 if (iap->ia_valid & ATTR_SIZE) {
1028 bmval[0] |= FATTR4_WORD0_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 len += 8;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001030 }
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001031 if (!(server->attr_bitmask[2] & FATTR4_WORD2_MODE_UMASK))
1032 umask = NULL;
Trond Myklebustd7067b22013-07-17 17:09:01 -04001033 if (iap->ia_valid & ATTR_MODE) {
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001034 if (umask) {
1035 bmval[2] |= FATTR4_WORD2_MODE_UMASK;
1036 len += 8;
1037 } else {
1038 bmval[1] |= FATTR4_WORD1_MODE;
1039 len += 4;
1040 }
Trond Myklebustd7067b22013-07-17 17:09:01 -04001041 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001042 if (iap->ia_valid & ATTR_UID) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08001043 owner_namelen = nfs_map_uid_to_name(server, iap->ia_uid, owner_name, IDMAP_NAMESZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001044 if (owner_namelen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04001045 dprintk("nfs: couldn't resolve uid %d to string\n",
Eric W. Biedermane5782072013-02-01 14:22:02 -08001046 from_kuid(&init_user_ns, iap->ia_uid));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001047 /* XXX */
1048 strcpy(owner_name, "nobody");
1049 owner_namelen = sizeof("nobody") - 1;
1050 /* goto out; */
1051 }
Trond Myklebustd7067b22013-07-17 17:09:01 -04001052 bmval[1] |= FATTR4_WORD1_OWNER;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
1054 }
1055 if (iap->ia_valid & ATTR_GID) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08001056 owner_grouplen = nfs_map_gid_to_group(server, iap->ia_gid, owner_group, IDMAP_NAMESZ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001057 if (owner_grouplen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04001058 dprintk("nfs: couldn't resolve gid %d to string\n",
Eric W. Biedermane5782072013-02-01 14:22:02 -08001059 from_kgid(&init_user_ns, iap->ia_gid));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001060 strcpy(owner_group, "nobody");
1061 owner_grouplen = sizeof("nobody") - 1;
1062 /* goto out; */
1063 }
Trond Myklebustd7067b22013-07-17 17:09:01 -04001064 bmval[1] |= FATTR4_WORD1_OWNER_GROUP;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
1066 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067 if (iap->ia_valid & ATTR_ATIME_SET) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001068 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1069 len += 16;
1070 } else if (iap->ia_valid & ATTR_ATIME) {
1071 bmval[1] |= FATTR4_WORD1_TIME_ACCESS_SET;
1072 len += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001073 }
1074 if (iap->ia_valid & ATTR_MTIME_SET) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001075 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1076 len += 16;
1077 } else if (iap->ia_valid & ATTR_MTIME) {
1078 bmval[1] |= FATTR4_WORD1_TIME_MODIFY_SET;
1079 len += 4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001080 }
Kinglong Mee5334c5b2015-08-26 21:13:37 +08001081
1082 if (excl_check) {
1083 const u32 *excl_bmval = server->exclcreat_bitmask;
1084 bmval[0] &= excl_bmval[0];
1085 bmval[1] &= excl_bmval[1];
1086 bmval[2] &= excl_bmval[2];
1087
1088 if (!(excl_bmval[2] & FATTR4_WORD2_SECURITY_LABEL))
1089 label = NULL;
1090 }
1091
David Quigleyaa9c2662013-05-22 12:50:44 -04001092 if (label) {
Trond Myklebustd7067b22013-07-17 17:09:01 -04001093 len += 4 + 4 + 4 + (XDR_QUADLEN(label->len) << 2);
1094 bmval[2] |= FATTR4_WORD2_SECURITY_LABEL;
1095 }
1096
1097 if (bmval[2] != 0)
1098 bmval_len = 3;
1099 else if (bmval[1] != 0)
1100 bmval_len = 2;
1101 else
1102 bmval_len = 1;
1103
1104 p = reserve_space(xdr, 4 + (bmval_len << 2) + 4 + len);
1105
1106 *p++ = cpu_to_be32(bmval_len);
1107 for (i = 0; i < bmval_len; i++)
1108 *p++ = cpu_to_be32(bmval[i]);
1109 *p++ = cpu_to_be32(len);
1110
1111 if (bmval[0] & FATTR4_WORD0_SIZE)
1112 p = xdr_encode_hyper(p, iap->ia_size);
1113 if (bmval[1] & FATTR4_WORD1_MODE)
1114 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1115 if (bmval[1] & FATTR4_WORD1_OWNER)
1116 p = xdr_encode_opaque(p, owner_name, owner_namelen);
1117 if (bmval[1] & FATTR4_WORD1_OWNER_GROUP)
1118 p = xdr_encode_opaque(p, owner_group, owner_grouplen);
1119 if (bmval[1] & FATTR4_WORD1_TIME_ACCESS_SET) {
1120 if (iap->ia_valid & ATTR_ATIME_SET) {
1121 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1122 p = xdr_encode_hyper(p, (s64)iap->ia_atime.tv_sec);
1123 *p++ = cpu_to_be32(iap->ia_atime.tv_nsec);
1124 } else
1125 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1126 }
1127 if (bmval[1] & FATTR4_WORD1_TIME_MODIFY_SET) {
1128 if (iap->ia_valid & ATTR_MTIME_SET) {
1129 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
1130 p = xdr_encode_hyper(p, (s64)iap->ia_mtime.tv_sec);
1131 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
1132 } else
1133 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
1134 }
1135 if (bmval[2] & FATTR4_WORD2_SECURITY_LABEL) {
David Quigleyaa9c2662013-05-22 12:50:44 -04001136 *p++ = cpu_to_be32(label->lfs);
1137 *p++ = cpu_to_be32(label->pi);
1138 *p++ = cpu_to_be32(label->len);
1139 p = xdr_encode_opaque_fixed(p, label->label, label->len);
1140 }
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001141 if (bmval[2] & FATTR4_WORD2_MODE_UMASK) {
1142 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
1143 *p++ = cpu_to_be32(*umask);
1144 }
Andy Adamson6c0195a2008-12-23 16:06:15 -05001145
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146/* out: */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001147}
1148
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001149static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001150{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001151 encode_op_hdr(xdr, OP_ACCESS, decode_access_maxsz, hdr);
1152 encode_uint32(xdr, access);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153}
1154
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001155static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001156{
Trond Myklebustab19b482012-03-04 18:13:57 -05001157 encode_op_hdr(xdr, OP_CLOSE, decode_close_maxsz, hdr);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001158 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust566fcec2015-01-23 15:32:46 -05001159 encode_nfs4_stateid(xdr, &arg->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001160}
1161
Fred Isaman0b7c0152012-04-20 14:47:39 -04001162static void encode_commit(struct xdr_stream *xdr, const struct nfs_commitargs *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001163{
Al Viro8687b632006-10-19 23:28:48 -07001164 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001165
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001166 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
1167 p = reserve_space(xdr, 12);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001168 p = xdr_encode_hyper(p, args->offset);
Benny Halevy34558512009-08-14 17:19:30 +03001169 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001170}
1171
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001172static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001173{
Al Viro8687b632006-10-19 23:28:48 -07001174 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001175
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001176 encode_op_hdr(xdr, OP_CREATE, decode_create_maxsz, hdr);
1177 encode_uint32(xdr, create->ftype);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001178
1179 switch (create->ftype) {
1180 case NF4LNK:
Benny Halevy13c65ce2009-08-14 17:19:25 +03001181 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001182 *p = cpu_to_be32(create->u.symlink.len);
Chuck Lever2fcc2132015-08-03 13:04:26 -04001183 xdr_write_pages(xdr, create->u.symlink.pages, 0,
1184 create->u.symlink.len);
1185 xdr->buf->flags |= XDRBUF_WRITE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001186 break;
1187
1188 case NF4BLK: case NF4CHR:
Benny Halevy13c65ce2009-08-14 17:19:25 +03001189 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001190 *p++ = cpu_to_be32(create->u.device.specdata1);
Benny Halevy34558512009-08-14 17:19:30 +03001191 *p = cpu_to_be32(create->u.device.specdata2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001192 break;
1193
1194 default:
1195 break;
1196 }
1197
Benny Halevy811652b2009-08-14 17:19:34 +03001198 encode_string(xdr, create->name->len, create->name->name);
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001199 encode_attrs(xdr, create->attrs, create->label, create->server, false,
1200 &create->umask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001201}
1202
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001203static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001204{
Andy Adamson05d564f2008-12-23 16:06:15 -05001205 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001207 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
1208 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001209 *p++ = cpu_to_be32(1);
Benny Halevy34558512009-08-14 17:19:30 +03001210 *p = cpu_to_be32(bitmap);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001211}
1212
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001213static 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 -07001214{
Andy Adamson05d564f2008-12-23 16:06:15 -05001215 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001216
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001217 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
1218 p = reserve_space(xdr, 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001219 *p++ = cpu_to_be32(2);
1220 *p++ = cpu_to_be32(bm0);
Benny Halevy34558512009-08-14 17:19:30 +03001221 *p = cpu_to_be32(bm1);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001222}
1223
Fred Isamandae100c2011-07-30 20:52:37 -04001224static void
1225encode_getattr_three(struct xdr_stream *xdr,
1226 uint32_t bm0, uint32_t bm1, uint32_t bm2,
1227 struct compound_hdr *hdr)
1228{
1229 __be32 *p;
1230
Trond Myklebustab19b482012-03-04 18:13:57 -05001231 encode_op_hdr(xdr, OP_GETATTR, decode_getattr_maxsz, hdr);
Fred Isamandae100c2011-07-30 20:52:37 -04001232 if (bm2) {
1233 p = reserve_space(xdr, 16);
1234 *p++ = cpu_to_be32(3);
1235 *p++ = cpu_to_be32(bm0);
1236 *p++ = cpu_to_be32(bm1);
1237 *p = cpu_to_be32(bm2);
1238 } else if (bm1) {
1239 p = reserve_space(xdr, 12);
1240 *p++ = cpu_to_be32(2);
1241 *p++ = cpu_to_be32(bm0);
1242 *p = cpu_to_be32(bm1);
1243 } else {
1244 p = reserve_space(xdr, 8);
1245 *p++ = cpu_to_be32(1);
1246 *p = cpu_to_be32(bm0);
1247 }
Fred Isamandae100c2011-07-30 20:52:37 -04001248}
1249
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001250static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001251{
David Quigleya09df2c2013-05-22 12:50:41 -04001252 encode_getattr_three(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
1253 bitmask[1] & nfs4_fattr_bitmap[1],
1254 bitmask[2] & nfs4_fattr_bitmap[2],
1255 hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001256}
1257
Andy Adamson88034c32012-05-23 05:02:34 -04001258static void encode_getfattr_open(struct xdr_stream *xdr, const u32 *bitmask,
Trond Myklebust1549210f2012-06-05 09:16:47 -04001259 const u32 *open_bitmap,
Andy Adamson88034c32012-05-23 05:02:34 -04001260 struct compound_hdr *hdr)
1261{
1262 encode_getattr_three(xdr,
Trond Myklebust1549210f2012-06-05 09:16:47 -04001263 bitmask[0] & open_bitmap[0],
1264 bitmask[1] & open_bitmap[1],
1265 bitmask[2] & open_bitmap[2],
Andy Adamson88034c32012-05-23 05:02:34 -04001266 hdr);
1267}
1268
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001269static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001270{
Fred Isamandae100c2011-07-30 20:52:37 -04001271 encode_getattr_three(xdr,
1272 bitmask[0] & nfs4_fsinfo_bitmap[0],
1273 bitmask[1] & nfs4_fsinfo_bitmap[1],
1274 bitmask[2] & nfs4_fsinfo_bitmap[2],
1275 hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276}
1277
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001278static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Manoj Naik830b8e32006-06-09 09:34:25 -04001279{
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001280 encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0],
1281 bitmask[1] & nfs4_fs_locations_bitmap[1], hdr);
Manoj Naik830b8e32006-06-09 09:34:25 -04001282}
1283
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001284static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001285{
Trond Myklebustab19b482012-03-04 18:13:57 -05001286 encode_op_hdr(xdr, OP_GETFH, decode_getfh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001287}
1288
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001289static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001290{
Trond Myklebustab19b482012-03-04 18:13:57 -05001291 encode_op_hdr(xdr, OP_LINK, decode_link_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001292 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001293}
1294
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001295static inline int nfs4_lock_type(struct file_lock *fl, int block)
1296{
Jeff Laytonf44106e2012-07-23 15:49:56 -04001297 if (fl->fl_type == F_RDLCK)
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001298 return block ? NFS4_READW_LT : NFS4_READ_LT;
1299 return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
1300}
1301
1302static inline uint64_t nfs4_lock_length(struct file_lock *fl)
1303{
1304 if (fl->fl_end == OFFSET_MAX)
1305 return ~(uint64_t)0;
1306 return fl->fl_end - fl->fl_start + 1;
1307}
1308
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001309static void encode_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner)
1310{
1311 __be32 *p;
1312
Trond Myklebustd035c362010-12-21 10:45:27 -05001313 p = reserve_space(xdr, 32);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001314 p = xdr_encode_hyper(p, lowner->clientid);
Trond Myklebustd035c362010-12-21 10:45:27 -05001315 *p++ = cpu_to_be32(20);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001316 p = xdr_encode_opaque_fixed(p, "lock id:", 8);
Trond Myklebustd035c362010-12-21 10:45:27 -05001317 *p++ = cpu_to_be32(lowner->s_dev);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001318 xdr_encode_hyper(p, lowner->id);
1319}
1320
Linus Torvalds1da177e2005-04-16 15:20:36 -07001321/*
1322 * opcode,type,reclaim,offset,length,new_lock_owner = 32
1323 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
1324 */
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001325static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001326{
Al Viro8687b632006-10-19 23:28:48 -07001327 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001328
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001329 encode_op_hdr(xdr, OP_LOCK, decode_lock_maxsz, hdr);
1330 p = reserve_space(xdr, 28);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001331 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
1332 *p++ = cpu_to_be32(args->reclaim);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001333 p = xdr_encode_hyper(p, args->fl->fl_start);
1334 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Benny Halevy34558512009-08-14 17:19:30 +03001335 *p = cpu_to_be32(args->new_lock_owner);
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001336 if (args->new_lock_owner){
Trond Myklebust4ade9822012-03-04 18:13:57 -05001337 encode_nfs4_seqid(xdr, args->open_seqid);
Trond Myklebust425c1d42015-01-24 14:57:53 -05001338 encode_nfs4_stateid(xdr, &args->open_stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001339 encode_nfs4_seqid(xdr, args->lock_seqid);
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001340 encode_lockowner(xdr, &args->lock_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001341 }
1342 else {
Trond Myklebust425c1d42015-01-24 14:57:53 -05001343 encode_nfs4_stateid(xdr, &args->lock_stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001344 encode_nfs4_seqid(xdr, args->lock_seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001345 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001346}
1347
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001348static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001349{
Al Viro8687b632006-10-19 23:28:48 -07001350 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001351
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001352 encode_op_hdr(xdr, OP_LOCKT, decode_lockt_maxsz, hdr);
1353 p = reserve_space(xdr, 20);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001354 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
Benny Halevyb95be5a2009-08-14 17:19:01 +03001355 p = xdr_encode_hyper(p, args->fl->fl_start);
1356 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Trond Myklebustdaccbde2010-06-25 18:11:43 -04001357 encode_lockowner(xdr, &args->lock_owner);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358}
1359
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001360static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001361{
Al Viro8687b632006-10-19 23:28:48 -07001362 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001364 encode_op_hdr(xdr, OP_LOCKU, decode_locku_maxsz, hdr);
1365 encode_uint32(xdr, nfs4_lock_type(args->fl, 0));
Trond Myklebust4ade9822012-03-04 18:13:57 -05001366 encode_nfs4_seqid(xdr, args->seqid);
Trond Myklebust425c1d42015-01-24 14:57:53 -05001367 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001368 p = reserve_space(xdr, 16);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001369 p = xdr_encode_hyper(p, args->fl->fl_start);
Benny Halevy34558512009-08-14 17:19:30 +03001370 xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371}
1372
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001373static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr)
1374{
Trond Myklebustab19b482012-03-04 18:13:57 -05001375 encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001376 encode_lockowner(xdr, lowner);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04001377}
1378
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001379static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380{
Trond Myklebustab19b482012-03-04 18:13:57 -05001381 encode_op_hdr(xdr, OP_LOOKUP, decode_lookup_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001382 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001383}
1384
Trond Myklebust6ae37332015-01-30 14:21:14 -05001385static void encode_share_access(struct xdr_stream *xdr, u32 share_access)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001386{
Al Viro8687b632006-10-19 23:28:48 -07001387 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001388
Benny Halevy13c65ce2009-08-14 17:19:25 +03001389 p = reserve_space(xdr, 8);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001390 *p++ = cpu_to_be32(share_access);
Benny Halevy34558512009-08-14 17:19:30 +03001391 *p = cpu_to_be32(0); /* for linux, share_deny = 0 always */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001392}
1393
1394static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1395{
Al Viro8687b632006-10-19 23:28:48 -07001396 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001397 /*
1398 * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
1399 * owner 4 = 32
1400 */
Trond Myklebust4ade9822012-03-04 18:13:57 -05001401 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001402 encode_share_access(xdr, arg->share_access);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001403 p = reserve_space(xdr, 36);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001404 p = xdr_encode_hyper(p, arg->clientid);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001405 *p++ = cpu_to_be32(24);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001406 p = xdr_encode_opaque_fixed(p, "open id:", 8);
Trond Myklebustd035c362010-12-21 10:45:27 -05001407 *p++ = cpu_to_be32(arg->server->s_dev);
Trond Myklebust95b72eb2012-04-20 19:24:51 -04001408 *p++ = cpu_to_be32(arg->id.uniquifier);
1409 xdr_encode_hyper(p, arg->id.create_time);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001410}
1411
1412static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1413{
Al Viro8687b632006-10-19 23:28:48 -07001414 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001415
Benny Halevy13c65ce2009-08-14 17:19:25 +03001416 p = reserve_space(xdr, 4);
Trond Myklebust549b19c2013-04-16 18:42:34 -04001417 switch(arg->createmode) {
1418 case NFS4_CREATE_UNCHECKED:
Benny Halevy34558512009-08-14 17:19:30 +03001419 *p = cpu_to_be32(NFS4_CREATE_UNCHECKED);
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001420 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
1421 &arg->umask);
Andy Adamson05d564f2008-12-23 16:06:15 -05001422 break;
Trond Myklebust549b19c2013-04-16 18:42:34 -04001423 case NFS4_CREATE_GUARDED:
1424 *p = cpu_to_be32(NFS4_CREATE_GUARDED);
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001425 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, false,
1426 &arg->umask);
Trond Myklebust549b19c2013-04-16 18:42:34 -04001427 break;
1428 case NFS4_CREATE_EXCLUSIVE:
1429 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
1430 encode_nfs4_verifier(xdr, &arg->u.verifier);
1431 break;
1432 case NFS4_CREATE_EXCLUSIVE4_1:
1433 *p = cpu_to_be32(NFS4_CREATE_EXCLUSIVE4_1);
1434 encode_nfs4_verifier(xdr, &arg->u.verifier);
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001435 encode_attrs(xdr, arg->u.attrs, arg->label, arg->server, true,
1436 &arg->umask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001437 }
1438}
1439
1440static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1441{
Al Viro8687b632006-10-19 23:28:48 -07001442 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443
Benny Halevy13c65ce2009-08-14 17:19:25 +03001444 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445 switch (arg->open_flags & O_CREAT) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001446 case 0:
Benny Halevy34558512009-08-14 17:19:30 +03001447 *p = cpu_to_be32(NFS4_OPEN_NOCREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001448 break;
1449 default:
Benny Halevy34558512009-08-14 17:19:30 +03001450 *p = cpu_to_be32(NFS4_OPEN_CREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001451 encode_createmode(xdr, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001452 }
1453}
1454
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001455static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001456{
Al Viro8687b632006-10-19 23:28:48 -07001457 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001458
Benny Halevy13c65ce2009-08-14 17:19:25 +03001459 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001460 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001461 case 0:
Benny Halevy34558512009-08-14 17:19:30 +03001462 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001463 break;
1464 case FMODE_READ:
Benny Halevy34558512009-08-14 17:19:30 +03001465 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
Andy Adamson05d564f2008-12-23 16:06:15 -05001466 break;
1467 case FMODE_WRITE|FMODE_READ:
Benny Halevy34558512009-08-14 17:19:30 +03001468 *p = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001469 break;
1470 default:
1471 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001472 }
1473}
1474
1475static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
1476{
Al Viro8687b632006-10-19 23:28:48 -07001477 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001478
Benny Halevy13c65ce2009-08-14 17:19:25 +03001479 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001480 *p = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481 encode_string(xdr, name->len, name->name);
1482}
1483
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001484static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001485{
Al Viro8687b632006-10-19 23:28:48 -07001486 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001487
Benny Halevy13c65ce2009-08-14 17:19:25 +03001488 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001489 *p = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001490 encode_delegation_type(xdr, type);
1491}
1492
1493static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
1494{
Al Viro8687b632006-10-19 23:28:48 -07001495 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001497 p = reserve_space(xdr, 4);
1498 *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
1499 encode_nfs4_stateid(xdr, stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001500 encode_string(xdr, name->len, name->name);
1501}
1502
Trond Myklebustd9fc6612013-03-15 15:39:06 -04001503static inline void encode_claim_fh(struct xdr_stream *xdr)
1504{
1505 __be32 *p;
1506
1507 p = reserve_space(xdr, 4);
1508 *p = cpu_to_be32(NFS4_OPEN_CLAIM_FH);
1509}
1510
1511static inline void encode_claim_delegate_cur_fh(struct xdr_stream *xdr, const nfs4_stateid *stateid)
1512{
1513 __be32 *p;
1514
1515 p = reserve_space(xdr, 4);
1516 *p = cpu_to_be32(NFS4_OPEN_CLAIM_DELEG_CUR_FH);
1517 encode_nfs4_stateid(xdr, stateid);
1518}
1519
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001520static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001521{
Trond Myklebustab19b482012-03-04 18:13:57 -05001522 encode_op_hdr(xdr, OP_OPEN, decode_open_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001523 encode_openhdr(xdr, arg);
1524 encode_opentype(xdr, arg);
1525 switch (arg->claim) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001526 case NFS4_OPEN_CLAIM_NULL:
1527 encode_claim_null(xdr, arg->name);
1528 break;
1529 case NFS4_OPEN_CLAIM_PREVIOUS:
1530 encode_claim_previous(xdr, arg->u.delegation_type);
1531 break;
1532 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
1533 encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
1534 break;
Trond Myklebustd9fc6612013-03-15 15:39:06 -04001535 case NFS4_OPEN_CLAIM_FH:
1536 encode_claim_fh(xdr);
1537 break;
1538 case NFS4_OPEN_CLAIM_DELEG_CUR_FH:
1539 encode_claim_delegate_cur_fh(xdr, &arg->u.delegation);
1540 break;
Andy Adamson05d564f2008-12-23 16:06:15 -05001541 default:
1542 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001543 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001544}
1545
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001546static 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 -07001547{
Trond Myklebustab19b482012-03-04 18:13:57 -05001548 encode_op_hdr(xdr, OP_OPEN_CONFIRM, decode_open_confirm_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001549 encode_nfs4_stateid(xdr, arg->stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001550 encode_nfs4_seqid(xdr, arg->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001551}
1552
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001553static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001554{
Trond Myklebustab19b482012-03-04 18:13:57 -05001555 encode_op_hdr(xdr, OP_OPEN_DOWNGRADE, decode_open_downgrade_maxsz, hdr);
Trond Myklebust566fcec2015-01-23 15:32:46 -05001556 encode_nfs4_stateid(xdr, &arg->stateid);
Trond Myklebust4ade9822012-03-04 18:13:57 -05001557 encode_nfs4_seqid(xdr, arg->seqid);
Trond Myklebust6ae37332015-01-30 14:21:14 -05001558 encode_share_access(xdr, arg->share_access);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001559}
1560
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001561static void
Andy Adamsond0179312008-12-23 16:06:17 -05001562encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001563{
Trond Myklebustab19b482012-03-04 18:13:57 -05001564 encode_op_hdr(xdr, OP_PUTFH, decode_putfh_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001565 encode_string(xdr, fh->size, fh->data);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001566}
1567
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001568static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001569{
Trond Myklebustab19b482012-03-04 18:13:57 -05001570 encode_op_hdr(xdr, OP_PUTROOTFH, decode_putrootfh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001571}
1572
Anna Schumaker3c6b8992014-05-06 09:12:24 -04001573static void encode_read(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
1574 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001575{
Al Viro8687b632006-10-19 23:28:48 -07001576 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001577
Trond Myklebustab19b482012-03-04 18:13:57 -05001578 encode_op_hdr(xdr, OP_READ, decode_read_maxsz, hdr);
Trond Myklebust9b206142013-03-17 15:52:00 -04001579 encode_nfs4_stateid(xdr, &args->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001580
Benny Halevy13c65ce2009-08-14 17:19:25 +03001581 p = reserve_space(xdr, 12);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001582 p = xdr_encode_hyper(p, args->offset);
Benny Halevy34558512009-08-14 17:19:30 +03001583 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001584}
1585
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001586static 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 -07001587{
David Quigleyaa9c2662013-05-22 12:50:44 -04001588 uint32_t attrs[3] = {
Trond Myklebust28331a42011-04-27 13:47:52 -04001589 FATTR4_WORD0_RDATTR_ERROR,
1590 FATTR4_WORD1_MOUNTED_ON_FILEID,
1591 };
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001592 uint32_t dircount = readdir->count >> 1;
Chuck Levercd937102012-03-02 17:14:31 -05001593 __be32 *p, verf[2];
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001594 uint32_t attrlen = 0;
1595 unsigned int i;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001596
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001597 if (readdir->plus) {
1598 attrs[0] |= FATTR4_WORD0_TYPE|FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE|
Trond Myklebust28331a42011-04-27 13:47:52 -04001599 FATTR4_WORD0_FSID|FATTR4_WORD0_FILEHANDLE|FATTR4_WORD0_FILEID;
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001600 attrs[1] |= FATTR4_WORD1_MODE|FATTR4_WORD1_NUMLINKS|FATTR4_WORD1_OWNER|
1601 FATTR4_WORD1_OWNER_GROUP|FATTR4_WORD1_RAWDEV|
1602 FATTR4_WORD1_SPACE_USED|FATTR4_WORD1_TIME_ACCESS|
1603 FATTR4_WORD1_TIME_METADATA|FATTR4_WORD1_TIME_MODIFY;
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001604 attrs[2] |= FATTR4_WORD2_SECURITY_LABEL;
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001605 dircount >>= 1;
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001606 }
Trond Myklebust28331a42011-04-27 13:47:52 -04001607 /* Use mounted_on_fileid only if the server supports it */
1608 if (!(readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID))
1609 attrs[0] |= FATTR4_WORD0_FILEID;
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001610 for (i = 0; i < ARRAY_SIZE(attrs); i++) {
1611 attrs[i] &= readdir->bitmask[i];
1612 if (attrs[i] != 0)
1613 attrlen = i+1;
1614 }
Bryan Schumaker82f2e542010-10-21 16:33:18 -04001615
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001616 encode_op_hdr(xdr, OP_READDIR, decode_readdir_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001617 encode_uint64(xdr, readdir->cookie);
Chuck Levercd937102012-03-02 17:14:31 -05001618 encode_nfs4_verifier(xdr, &readdir->verifier);
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001619 p = reserve_space(xdr, 12 + (attrlen << 2));
Trond Myklebust6f7a35b2010-10-24 12:11:42 -04001620 *p++ = cpu_to_be32(dircount);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001621 *p++ = cpu_to_be32(readdir->count);
Trond Myklebustd204c5d2013-11-04 13:23:59 -05001622 *p++ = cpu_to_be32(attrlen);
1623 for (i = 0; i < attrlen; i++)
1624 *p++ = cpu_to_be32(attrs[i]);
Chuck Levercd937102012-03-02 17:14:31 -05001625 memcpy(verf, readdir->verifier.data, sizeof(verf));
David Quigleyaa9c2662013-05-22 12:50:44 -04001626
1627 dprintk("%s: cookie = %llu, verifier = %08x:%08x, bitmap = %08x:%08x:%08x\n",
Fred Isaman44109242008-04-02 15:21:15 +03001628 __func__,
Trond Myklebusteadf4592005-06-22 17:16:39 +00001629 (unsigned long long)readdir->cookie,
Chuck Levercd937102012-03-02 17:14:31 -05001630 verf[0], verf[1],
Trond Myklebusteadf4592005-06-22 17:16:39 +00001631 attrs[0] & readdir->bitmask[0],
David Quigleyaa9c2662013-05-22 12:50:44 -04001632 attrs[1] & readdir->bitmask[1],
1633 attrs[2] & readdir->bitmask[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001634}
1635
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001636static 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 -07001637{
Trond Myklebustab19b482012-03-04 18:13:57 -05001638 encode_op_hdr(xdr, OP_READLINK, decode_readlink_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001639}
1640
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001641static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001642{
Trond Myklebustab19b482012-03-04 18:13:57 -05001643 encode_op_hdr(xdr, OP_REMOVE, decode_remove_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001644 encode_string(xdr, name->len, name->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001645}
1646
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001647static 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 -07001648{
Trond Myklebustab19b482012-03-04 18:13:57 -05001649 encode_op_hdr(xdr, OP_RENAME, decode_rename_maxsz, hdr);
Benny Halevy811652b2009-08-14 17:19:34 +03001650 encode_string(xdr, oldname->len, oldname->name);
1651 encode_string(xdr, newname->len, newname->name);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001652}
1653
Chuck Leverbb4dae52012-03-01 17:01:48 -05001654static void encode_renew(struct xdr_stream *xdr, clientid4 clid,
1655 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001656{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001657 encode_op_hdr(xdr, OP_RENEW, decode_renew_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001658 encode_uint64(xdr, clid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001659}
1660
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001661static void
Andy Adamsond0179312008-12-23 16:06:17 -05001662encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001663{
Trond Myklebustab19b482012-03-04 18:13:57 -05001664 encode_op_hdr(xdr, OP_RESTOREFH, decode_restorefh_maxsz, hdr);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001665}
1666
Chuck Lever9f06c712010-12-14 14:59:18 +00001667static void
Andy Adamsond0179312008-12-23 16:06:17 -05001668encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001669{
Al Viro8687b632006-10-19 23:28:48 -07001670 __be32 *p;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001671
Trond Myklebustab19b482012-03-04 18:13:57 -05001672 encode_op_hdr(xdr, OP_SETATTR, decode_setacl_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001673 encode_nfs4_stateid(xdr, &zero_stateid);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001674 p = reserve_space(xdr, 2*4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001675 *p++ = cpu_to_be32(1);
Benny Halevy34558512009-08-14 17:19:30 +03001676 *p = cpu_to_be32(FATTR4_WORD0_ACL);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001677 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001678 *p = cpu_to_be32(arg->acl_len);
Andreas Gruenbacher8fbcf232015-11-03 18:25:34 +01001679 xdr_write_pages(xdr, arg->acl_pages, 0, arg->acl_len);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001680}
1681
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001682static void
Andy Adamsond0179312008-12-23 16:06:17 -05001683encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001684{
Trond Myklebustab19b482012-03-04 18:13:57 -05001685 encode_op_hdr(xdr, OP_SAVEFH, decode_savefh_maxsz, hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686}
1687
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001688static 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 -07001689{
Trond Myklebustab19b482012-03-04 18:13:57 -05001690 encode_op_hdr(xdr, OP_SETATTR, decode_setattr_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001691 encode_nfs4_stateid(xdr, &arg->stateid);
Andreas Gruenbacherdff25dd2016-12-02 22:53:30 -05001692 encode_attrs(xdr, arg->iap, arg->label, server, false, NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001693}
1694
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001695static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696{
Al Viro8687b632006-10-19 23:28:48 -07001697 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001698
Trond Myklebust70019512012-03-04 20:49:32 -05001699 encode_op_hdr(xdr, OP_SETCLIENTID, decode_setclientid_maxsz, hdr);
Chuck Levercd937102012-03-02 17:14:31 -05001700 encode_nfs4_verifier(xdr, setclientid->sc_verifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001701
Jeff Layton3a6bb732015-06-09 19:43:57 -04001702 encode_string(xdr, strlen(setclientid->sc_clnt->cl_owner_id),
1703 setclientid->sc_clnt->cl_owner_id);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001704 p = reserve_space(xdr, 4);
Benny Halevy34558512009-08-14 17:19:30 +03001705 *p = cpu_to_be32(setclientid->sc_prog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001706 encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
1707 encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001708 p = reserve_space(xdr, 4);
Jeff Layton3a6bb732015-06-09 19:43:57 -04001709 *p = cpu_to_be32(setclientid->sc_clnt->cl_cb_ident);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001710}
1711
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04001712static 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 -07001713{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001714 encode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM,
1715 decode_setclientid_confirm_maxsz, hdr);
Trond Myklebustff2eb682012-03-05 11:40:12 -05001716 encode_uint64(xdr, arg->clientid);
Chuck Levercd937102012-03-02 17:14:31 -05001717 encode_nfs4_verifier(xdr, &arg->confirm);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718}
1719
Anna Schumaker3c6b8992014-05-06 09:12:24 -04001720static void encode_write(struct xdr_stream *xdr, const struct nfs_pgio_args *args,
1721 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001722{
Al Viro8687b632006-10-19 23:28:48 -07001723 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001724
Trond Myklebustab19b482012-03-04 18:13:57 -05001725 encode_op_hdr(xdr, OP_WRITE, decode_write_maxsz, hdr);
Trond Myklebust9b206142013-03-17 15:52:00 -04001726 encode_nfs4_stateid(xdr, &args->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727
Benny Halevy13c65ce2009-08-14 17:19:25 +03001728 p = reserve_space(xdr, 16);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001729 p = xdr_encode_hyper(p, args->offset);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001730 *p++ = cpu_to_be32(args->stable);
Benny Halevy34558512009-08-14 17:19:30 +03001731 *p = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001732
1733 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001734}
1735
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001736static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737{
Trond Myklebustab19b482012-03-04 18:13:57 -05001738 encode_op_hdr(xdr, OP_DELEGRETURN, decode_delegreturn_maxsz, hdr);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001739 encode_nfs4_stateid(xdr, stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001740}
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001741
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00001742static void encode_secinfo(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
1743{
Trond Myklebustab19b482012-03-04 18:13:57 -05001744 encode_op_hdr(xdr, OP_SECINFO, decode_secinfo_maxsz, hdr);
Trond Myklebust6fdfb0bc2012-03-04 18:13:57 -05001745 encode_string(xdr, name->len, name->name);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00001746}
1747
Benny Halevy99fe60d2009-04-01 09:22:29 -04001748#if defined(CONFIG_NFS_V4_1)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001749/* NFSv4.1 operations */
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001750static void encode_bind_conn_to_session(struct xdr_stream *xdr,
Trond Myklebust71a097c2015-02-18 09:27:18 -08001751 struct nfs41_bind_conn_to_session_args *args,
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001752 struct compound_hdr *hdr)
1753{
1754 __be32 *p;
1755
1756 encode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION,
1757 decode_bind_conn_to_session_maxsz, hdr);
Trond Myklebust71a097c2015-02-18 09:27:18 -08001758 encode_opaque_fixed(xdr, args->sessionid.data, NFS4_MAX_SESSIONID_LEN);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001759 p = xdr_reserve_space(xdr, 8);
Trond Myklebust71a097c2015-02-18 09:27:18 -08001760 *p++ = cpu_to_be32(args->dir);
1761 *p = (args->use_conn_in_rdma_mode) ? cpu_to_be32(1) : cpu_to_be32(0);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04001762}
1763
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001764static void encode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
1765{
1766 unsigned int i;
1767 encode_uint32(xdr, NFS4_OP_MAP_NUM_WORDS);
1768 for (i = 0; i < NFS4_OP_MAP_NUM_WORDS; i++)
1769 encode_uint32(xdr, op_map->u.words[i]);
1770}
1771
Benny Halevy99fe60d2009-04-01 09:22:29 -04001772static void encode_exchange_id(struct xdr_stream *xdr,
1773 struct nfs41_exchange_id_args *args,
1774 struct compound_hdr *hdr)
1775{
1776 __be32 *p;
Jim Reesd751f742012-11-16 18:12:06 -05001777 char impl_name[IMPL_NAME_LIMIT];
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001778 int len = 0;
Benny Halevy99fe60d2009-04-01 09:22:29 -04001779
Trond Myklebust70019512012-03-04 20:49:32 -05001780 encode_op_hdr(xdr, OP_EXCHANGE_ID, decode_exchange_id_maxsz, hdr);
Chuck Levercd937102012-03-02 17:14:31 -05001781 encode_nfs4_verifier(xdr, args->verifier);
Benny Halevy99fe60d2009-04-01 09:22:29 -04001782
Jeff Layton3a6bb732015-06-09 19:43:57 -04001783 encode_string(xdr, strlen(args->client->cl_owner_id),
1784 args->client->cl_owner_id);
Benny Halevy99fe60d2009-04-01 09:22:29 -04001785
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001786 encode_uint32(xdr, args->flags);
1787 encode_uint32(xdr, args->state_protect.how);
1788
1789 switch (args->state_protect.how) {
1790 case SP4_NONE:
1791 break;
1792 case SP4_MACH_CRED:
1793 encode_op_map(xdr, &args->state_protect.enforce);
1794 encode_op_map(xdr, &args->state_protect.allow);
1795 break;
1796 default:
1797 WARN_ON_ONCE(1);
1798 break;
1799 }
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001800
1801 if (send_implementation_id &&
1802 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) > 1 &&
1803 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN)
Jim Reesd751f742012-11-16 18:12:06 -05001804 <= sizeof(impl_name) + 1)
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001805 len = snprintf(impl_name, sizeof(impl_name), "%s %s %s %s",
1806 utsname()->sysname, utsname()->release,
1807 utsname()->version, utsname()->machine);
1808
1809 if (len > 0) {
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001810 encode_uint32(xdr, 1); /* implementation id array length=1 */
Weston Andros Adamsondb8ac8b2012-02-17 15:20:24 -05001811
1812 encode_string(xdr,
1813 sizeof(CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN) - 1,
1814 CONFIG_NFS_V4_1_IMPLEMENTATION_ID_DOMAIN);
1815 encode_string(xdr, len, impl_name);
1816 /* just send zeros for nii_date - the date is in nii_name */
1817 p = reserve_space(xdr, 12);
1818 p = xdr_encode_hyper(p, 0);
1819 *p = cpu_to_be32(0);
1820 } else
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04001821 encode_uint32(xdr, 0); /* implementation id array length=0 */
Benny Halevy99fe60d2009-04-01 09:22:29 -04001822}
Andy Adamsonfc931582009-04-01 09:22:31 -04001823
1824static void encode_create_session(struct xdr_stream *xdr,
1825 struct nfs41_create_session_args *args,
1826 struct compound_hdr *hdr)
1827{
1828 __be32 *p;
Andy Adamsonfc931582009-04-01 09:22:31 -04001829 struct nfs_client *clp = args->client;
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001830 struct rpc_clnt *clnt = clp->cl_rpcclient;
Chuck Leverf0920752012-05-21 22:45:41 -04001831 struct nfs_net *nn = net_generic(clp->cl_net, nfs_net_id);
Mike Sager8e0d46e2009-12-17 12:06:26 -05001832 u32 max_resp_sz_cached;
1833
1834 /*
1835 * Assumes OPEN is the biggest non-idempotent compound.
1836 * 2 is the verifier.
1837 */
1838 max_resp_sz_cached = (NFS4_dec_open_sz + RPC_REPHDRSIZE +
1839 RPC_MAX_AUTH_SIZE + 2) * XDR_UNIT;
Andy Adamsonfc931582009-04-01 09:22:31 -04001840
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001841 encode_op_hdr(xdr, OP_CREATE_SESSION, decode_create_session_maxsz, hdr);
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001842 p = reserve_space(xdr, 16 + 2*28 + 20 + clnt->cl_nodelen + 12);
Trond Myklebust79969dd2015-02-18 11:30:18 -08001843 p = xdr_encode_hyper(p, args->clientid);
1844 *p++ = cpu_to_be32(args->seqid); /*Sequence id */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001845 *p++ = cpu_to_be32(args->flags); /*flags */
Andy Adamsonfc931582009-04-01 09:22:31 -04001846
Andy Adamsonfc931582009-04-01 09:22:31 -04001847 /* Fore Channel */
Benny Halevyc9c30dd2011-06-11 17:08:39 -04001848 *p++ = cpu_to_be32(0); /* header padding size */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001849 *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
1850 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
Mike Sager8e0d46e2009-12-17 12:06:26 -05001851 *p++ = cpu_to_be32(max_resp_sz_cached); /* Max resp sz cached */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001852 *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */
1853 *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */
1854 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001855
1856 /* Back Channel */
Benny Halevyc9c30dd2011-06-11 17:08:39 -04001857 *p++ = cpu_to_be32(0); /* header padding size */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001858 *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
1859 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
1860 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1861 *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */
1862 *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */
1863 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001864
Benny Halevye75bc1c2009-08-14 17:18:54 +03001865 *p++ = cpu_to_be32(args->cb_program); /* cb_program */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001866 *p++ = cpu_to_be32(1);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001867 *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */
Andy Adamsonfc931582009-04-01 09:22:31 -04001868
1869 /* authsys_parms rfc1831 */
Deepa Dinamani2f86e092016-10-01 16:46:26 -07001870 *p++ = cpu_to_be32(ktime_to_ns(nn->boot_time)); /* stamp */
Trond Myklebust89f0ff32015-01-03 14:47:43 -05001871 p = xdr_encode_array(p, clnt->cl_nodename, clnt->cl_nodelen);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001872 *p++ = cpu_to_be32(0); /* UID */
1873 *p++ = cpu_to_be32(0); /* GID */
Benny Halevy34558512009-08-14 17:19:30 +03001874 *p = cpu_to_be32(0); /* No more gids */
Andy Adamsonfc931582009-04-01 09:22:31 -04001875}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001876
1877static void encode_destroy_session(struct xdr_stream *xdr,
1878 struct nfs4_session *session,
1879 struct compound_hdr *hdr)
1880{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001881 encode_op_hdr(xdr, OP_DESTROY_SESSION, decode_destroy_session_maxsz, hdr);
1882 encode_opaque_fixed(xdr, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001883}
Ricardo Labiaga180197532009-12-05 16:08:40 -05001884
Trond Myklebust66245532012-05-25 17:18:09 -04001885static void encode_destroy_clientid(struct xdr_stream *xdr,
1886 uint64_t clientid,
1887 struct compound_hdr *hdr)
1888{
1889 encode_op_hdr(xdr, OP_DESTROY_CLIENTID, decode_destroy_clientid_maxsz, hdr);
1890 encode_uint64(xdr, clientid);
1891}
1892
Ricardo Labiaga180197532009-12-05 16:08:40 -05001893static void encode_reclaim_complete(struct xdr_stream *xdr,
1894 struct nfs41_reclaim_complete_args *args,
1895 struct compound_hdr *hdr)
1896{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001897 encode_op_hdr(xdr, OP_RECLAIM_COMPLETE, decode_reclaim_complete_maxsz, hdr);
1898 encode_uint32(xdr, args->one_fs);
Ricardo Labiaga180197532009-12-05 16:08:40 -05001899}
Benny Halevy99fe60d2009-04-01 09:22:29 -04001900#endif /* CONFIG_NFS_V4_1 */
1901
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001902static void encode_sequence(struct xdr_stream *xdr,
1903 const struct nfs4_sequence_args *args,
1904 struct compound_hdr *hdr)
1905{
1906#if defined(CONFIG_NFS_V4_1)
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001907 struct nfs4_session *session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001908 struct nfs4_slot_table *tp;
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001909 struct nfs4_slot *slot = args->sa_slot;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001910 __be32 *p;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001911
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001912 tp = slot->table;
1913 session = tp->session;
Chuck Lever3bd23842013-08-09 12:49:19 -04001914 if (!session)
1915 return;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001916
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001917 encode_op_hdr(xdr, OP_SEQUENCE, decode_sequence_maxsz, hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001918
1919 /*
1920 * Sessionid + seqid + slotid + max slotid + cache_this
1921 */
1922 dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1923 "max_slotid=%d cache_this=%d\n",
1924 __func__,
1925 ((u32 *)session->sess_id.data)[0],
1926 ((u32 *)session->sess_id.data)[1],
1927 ((u32 *)session->sess_id.data)[2],
1928 ((u32 *)session->sess_id.data)[3],
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001929 slot->seq_nr, slot->slot_nr,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001930 tp->highest_used_slotid, args->sa_cache_this);
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001931 p = reserve_space(xdr, NFS4_MAX_SESSIONID_LEN + 16);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001932 p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001933 *p++ = cpu_to_be32(slot->seq_nr);
Trond Myklebust2b2fa712012-11-16 12:58:36 -05001934 *p++ = cpu_to_be32(slot->slot_nr);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001935 *p++ = cpu_to_be32(tp->highest_used_slotid);
Benny Halevy34558512009-08-14 17:19:30 +03001936 *p = cpu_to_be32(args->sa_cache_this);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001937#endif /* CONFIG_NFS_V4_1 */
1938}
1939
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001940#ifdef CONFIG_NFS_V4_1
1941static void
1942encode_getdeviceinfo(struct xdr_stream *xdr,
1943 const struct nfs4_getdeviceinfo_args *args,
1944 struct compound_hdr *hdr)
1945{
1946 __be32 *p;
1947
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001948 encode_op_hdr(xdr, OP_GETDEVICEINFO, decode_getdeviceinfo_maxsz, hdr);
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07001949 p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 4 + 4);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001950 p = xdr_encode_opaque_fixed(p, args->pdev->dev_id.data,
1951 NFS4_DEVICEID4_SIZE);
1952 *p++ = cpu_to_be32(args->pdev->layout_type);
Andy Adamsonf1c097b2013-06-25 19:02:53 -04001953 *p++ = cpu_to_be32(args->pdev->maxcount); /* gdia_maxcount */
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07001954
1955 p = reserve_space(xdr, 4 + 4);
1956 *p++ = cpu_to_be32(1); /* bitmap length */
Trond Myklebust4e590802015-03-09 14:01:25 -04001957 *p++ = cpu_to_be32(args->notify_types);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001958}
1959
1960static void
1961encode_layoutget(struct xdr_stream *xdr,
1962 const struct nfs4_layoutget_args *args,
1963 struct compound_hdr *hdr)
1964{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001965 __be32 *p;
1966
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001967 encode_op_hdr(xdr, OP_LAYOUTGET, decode_layoutget_maxsz, hdr);
1968 p = reserve_space(xdr, 36);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001969 *p++ = cpu_to_be32(0); /* Signal layout available */
1970 *p++ = cpu_to_be32(args->type);
1971 *p++ = cpu_to_be32(args->range.iomode);
1972 p = xdr_encode_hyper(p, args->range.offset);
1973 p = xdr_encode_hyper(p, args->range.length);
1974 p = xdr_encode_hyper(p, args->minlength);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05001975 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001976 encode_uint32(xdr, args->maxcount);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001977
1978 dprintk("%s: 1st type:0x%x iomode:%d off:%lu len:%lu mc:%d\n",
1979 __func__,
1980 args->type,
1981 args->range.iomode,
1982 (unsigned long)args->range.offset,
1983 (unsigned long)args->range.length,
1984 args->maxcount);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04001985}
Andy Adamson863a3c62011-03-23 13:27:54 +00001986
1987static int
1988encode_layoutcommit(struct xdr_stream *xdr,
Benny Halevyac7db722011-05-22 19:53:48 +03001989 struct inode *inode,
Christoph Hellwig5f919c92014-08-21 11:09:25 -05001990 struct nfs4_layoutcommit_args *args,
Andy Adamson863a3c62011-03-23 13:27:54 +00001991 struct compound_hdr *hdr)
1992{
1993 __be32 *p;
1994
1995 dprintk("%s: lbw: %llu type: %d\n", __func__, args->lastbytewritten,
1996 NFS_SERVER(args->inode)->pnfs_curr_ld->id);
1997
Trond Myklebust475d4ba2012-03-05 11:27:16 -05001998 encode_op_hdr(xdr, OP_LAYOUTCOMMIT, decode_layoutcommit_maxsz, hdr);
1999 p = reserve_space(xdr, 20);
Andy Adamson863a3c62011-03-23 13:27:54 +00002000 /* Only whole file layouts */
2001 p = xdr_encode_hyper(p, 0); /* offset */
Peng Tao3557c6c2011-07-30 20:52:34 -04002002 p = xdr_encode_hyper(p, args->lastbytewritten + 1); /* length */
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002003 *p = cpu_to_be32(0); /* reclaim */
2004 encode_nfs4_stateid(xdr, &args->stateid);
Trond Myklebust2e18d4d2016-06-26 18:54:58 -04002005 if (args->lastbytewritten != U64_MAX) {
2006 p = reserve_space(xdr, 20);
2007 *p++ = cpu_to_be32(1); /* newoffset = TRUE */
2008 p = xdr_encode_hyper(p, args->lastbytewritten);
2009 } else {
2010 p = reserve_space(xdr, 12);
2011 *p++ = cpu_to_be32(0); /* newoffset = FALSE */
2012 }
Andy Adamson863a3c62011-03-23 13:27:54 +00002013 *p++ = cpu_to_be32(0); /* Never send time_modify_changed */
2014 *p++ = cpu_to_be32(NFS_SERVER(args->inode)->pnfs_curr_ld->id);/* type */
Benny Halevyac7db722011-05-22 19:53:48 +03002015
Christoph Hellwig5f919c92014-08-21 11:09:25 -05002016 if (NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit) {
Benny Halevyac7db722011-05-22 19:53:48 +03002017 NFS_SERVER(inode)->pnfs_curr_ld->encode_layoutcommit(
2018 NFS_I(inode)->layout, xdr, args);
Christoph Hellwig5f919c92014-08-21 11:09:25 -05002019 } else {
2020 encode_uint32(xdr, args->layoutupdate_len);
2021 if (args->layoutupdate_pages) {
2022 xdr_write_pages(xdr, args->layoutupdate_pages, 0,
2023 args->layoutupdate_len);
2024 }
2025 }
Andy Adamson863a3c62011-03-23 13:27:54 +00002026
Andy Adamson863a3c62011-03-23 13:27:54 +00002027 return 0;
2028}
Benny Halevycbe82602011-05-22 19:52:37 +03002029
2030static void
2031encode_layoutreturn(struct xdr_stream *xdr,
2032 const struct nfs4_layoutreturn_args *args,
2033 struct compound_hdr *hdr)
2034{
Trond Myklebust94e5c572016-09-15 18:49:52 -04002035 const struct pnfs_layoutdriver_type *lr_ops = NFS_SERVER(args->inode)->pnfs_curr_ld;
Benny Halevycbe82602011-05-22 19:52:37 +03002036 __be32 *p;
2037
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002038 encode_op_hdr(xdr, OP_LAYOUTRETURN, decode_layoutreturn_maxsz, hdr);
2039 p = reserve_space(xdr, 16);
Benny Halevycbe82602011-05-22 19:52:37 +03002040 *p++ = cpu_to_be32(0); /* reclaim. always 0 for now */
2041 *p++ = cpu_to_be32(args->layout_type);
Peng Tao15eb67c2014-11-17 09:30:36 +08002042 *p++ = cpu_to_be32(args->range.iomode);
Benny Halevycbe82602011-05-22 19:52:37 +03002043 *p = cpu_to_be32(RETURN_FILE);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002044 p = reserve_space(xdr, 16);
Peng Tao15eb67c2014-11-17 09:30:36 +08002045 p = xdr_encode_hyper(p, args->range.offset);
2046 p = xdr_encode_hyper(p, args->range.length);
Benny Halevycbe82602011-05-22 19:52:37 +03002047 spin_lock(&args->inode->i_lock);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002048 encode_nfs4_stateid(xdr, &args->stateid);
Benny Halevycbe82602011-05-22 19:52:37 +03002049 spin_unlock(&args->inode->i_lock);
Trond Myklebust4d796d72016-09-23 11:38:08 -04002050 if (args->ld_private->ops && args->ld_private->ops->encode)
2051 args->ld_private->ops->encode(xdr, args, args->ld_private);
2052 else if (lr_ops->encode_layoutreturn)
Trond Myklebust94e5c572016-09-15 18:49:52 -04002053 lr_ops->encode_layoutreturn(xdr, args);
2054 else
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002055 encode_uint32(xdr, 0);
Benny Halevycbe82602011-05-22 19:52:37 +03002056}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002057
2058static int
2059encode_secinfo_no_name(struct xdr_stream *xdr,
2060 const struct nfs41_secinfo_no_name_args *args,
2061 struct compound_hdr *hdr)
2062{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002063 encode_op_hdr(xdr, OP_SECINFO_NO_NAME, decode_secinfo_no_name_maxsz, hdr);
2064 encode_uint32(xdr, args->style);
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002065 return 0;
2066}
Bryan Schumaker7d974792011-06-02 14:59:08 -04002067
2068static void encode_test_stateid(struct xdr_stream *xdr,
2069 struct nfs41_test_stateid_args *args,
2070 struct compound_hdr *hdr)
2071{
Trond Myklebust475d4ba2012-03-05 11:27:16 -05002072 encode_op_hdr(xdr, OP_TEST_STATEID, decode_test_stateid_maxsz, hdr);
2073 encode_uint32(xdr, 1);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05002074 encode_nfs4_stateid(xdr, args->stateid);
Bryan Schumaker7d974792011-06-02 14:59:08 -04002075}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04002076
2077static void encode_free_stateid(struct xdr_stream *xdr,
2078 struct nfs41_free_stateid_args *args,
2079 struct compound_hdr *hdr)
2080{
Trond Myklebustab19b482012-03-04 18:13:57 -05002081 encode_op_hdr(xdr, OP_FREE_STATEID, decode_free_stateid_maxsz, hdr);
Trond Myklebust7c1d5fa2013-05-03 14:40:01 -04002082 encode_nfs4_stateid(xdr, &args->stateid);
Bryan Schumaker9aeda352011-06-02 14:59:09 -04002083}
Trond Myklebustcf805162016-11-15 14:56:07 -05002084#else
2085static inline void
2086encode_layoutreturn(struct xdr_stream *xdr,
2087 const struct nfs4_layoutreturn_args *args,
2088 struct compound_hdr *hdr)
2089{
2090}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002091#endif /* CONFIG_NFS_V4_1 */
2092
Linus Torvalds1da177e2005-04-16 15:20:36 -07002093/*
2094 * END OF "GENERIC" ENCODE ROUTINES.
2095 */
2096
Benny Halevy66cc0422009-04-01 09:22:10 -04002097static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
2098{
2099#if defined(CONFIG_NFS_V4_1)
Chuck Lever3bd23842013-08-09 12:49:19 -04002100 struct nfs4_session *session = args->sa_slot->table->session;
2101 if (session)
2102 return session->clp->cl_mvops->minor_version;
Benny Halevy66cc0422009-04-01 09:22:10 -04002103#endif /* CONFIG_NFS_V4_1 */
2104 return 0;
2105}
2106
Linus Torvalds1da177e2005-04-16 15:20:36 -07002107/*
2108 * Encode an ACCESS request
2109 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002110static void nfs4_xdr_enc_access(struct rpc_rqst *req, struct xdr_stream *xdr,
2111 const struct nfs4_accessargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002112{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002113 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002114 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002115 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002116
Chuck Lever9f06c712010-12-14 14:59:18 +00002117 encode_compound_hdr(xdr, req, &hdr);
2118 encode_sequence(xdr, &args->seq_args, &hdr);
2119 encode_putfh(xdr, args->fh, &hdr);
2120 encode_access(xdr, args->access, &hdr);
2121 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002122 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002123}
2124
2125/*
2126 * Encode LOOKUP request
2127 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002128static void nfs4_xdr_enc_lookup(struct rpc_rqst *req, struct xdr_stream *xdr,
2129 const struct nfs4_lookup_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002130{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002132 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002133 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002134
Chuck Lever9f06c712010-12-14 14:59:18 +00002135 encode_compound_hdr(xdr, req, &hdr);
2136 encode_sequence(xdr, &args->seq_args, &hdr);
2137 encode_putfh(xdr, args->dir_fh, &hdr);
2138 encode_lookup(xdr, args->name, &hdr);
2139 encode_getfh(xdr, &hdr);
2140 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002141 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
2144/*
2145 * Encode LOOKUP_ROOT request
2146 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002147static void nfs4_xdr_enc_lookup_root(struct rpc_rqst *req,
2148 struct xdr_stream *xdr,
2149 const struct nfs4_lookup_root_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002150{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002151 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002152 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002154
Chuck Lever9f06c712010-12-14 14:59:18 +00002155 encode_compound_hdr(xdr, req, &hdr);
2156 encode_sequence(xdr, &args->seq_args, &hdr);
2157 encode_putrootfh(xdr, &hdr);
2158 encode_getfh(xdr, &hdr);
2159 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002160 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002161}
2162
2163/*
2164 * Encode REMOVE request
2165 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002166static void nfs4_xdr_enc_remove(struct rpc_rqst *req, struct xdr_stream *xdr,
2167 const struct nfs_removeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002169 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002170 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002171 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172
Chuck Lever9f06c712010-12-14 14:59:18 +00002173 encode_compound_hdr(xdr, req, &hdr);
2174 encode_sequence(xdr, &args->seq_args, &hdr);
2175 encode_putfh(xdr, args->fh, &hdr);
2176 encode_remove(xdr, &args->name, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002177 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002178}
2179
2180/*
2181 * Encode RENAME request
2182 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002183static void nfs4_xdr_enc_rename(struct rpc_rqst *req, struct xdr_stream *xdr,
2184 const struct nfs_renameargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002185{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002186 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002187 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002189
Chuck Lever9f06c712010-12-14 14:59:18 +00002190 encode_compound_hdr(xdr, req, &hdr);
2191 encode_sequence(xdr, &args->seq_args, &hdr);
2192 encode_putfh(xdr, args->old_dir, &hdr);
2193 encode_savefh(xdr, &hdr);
2194 encode_putfh(xdr, args->new_dir, &hdr);
2195 encode_rename(xdr, args->old_name, args->new_name, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002196 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002197}
2198
2199/*
2200 * Encode LINK request
2201 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002202static void nfs4_xdr_enc_link(struct rpc_rqst *req, struct xdr_stream *xdr,
2203 const struct nfs4_link_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002204{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002205 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002206 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208
Chuck Lever9f06c712010-12-14 14:59:18 +00002209 encode_compound_hdr(xdr, req, &hdr);
2210 encode_sequence(xdr, &args->seq_args, &hdr);
2211 encode_putfh(xdr, args->fh, &hdr);
2212 encode_savefh(xdr, &hdr);
2213 encode_putfh(xdr, args->dir_fh, &hdr);
2214 encode_link(xdr, args->name, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002215 encode_restorefh(xdr, &hdr);
2216 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002217 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002218}
2219
2220/*
2221 * Encode CREATE request
2222 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002223static void nfs4_xdr_enc_create(struct rpc_rqst *req, struct xdr_stream *xdr,
2224 const struct nfs4_create_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->dir_fh, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002233 encode_create(xdr, args, &hdr);
2234 encode_getfh(xdr, &hdr);
2235 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002236 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002237}
2238
2239/*
2240 * Encode SYMLINK request
2241 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002242static void nfs4_xdr_enc_symlink(struct rpc_rqst *req, struct xdr_stream *xdr,
2243 const struct nfs4_create_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244{
Chuck Lever9f06c712010-12-14 14:59:18 +00002245 nfs4_xdr_enc_create(req, xdr, args);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002246}
2247
2248/*
2249 * Encode GETATTR request
2250 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002251static void nfs4_xdr_enc_getattr(struct rpc_rqst *req, struct xdr_stream *xdr,
2252 const struct nfs4_getattr_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002253{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002255 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002256 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002257
Chuck Lever9f06c712010-12-14 14:59:18 +00002258 encode_compound_hdr(xdr, req, &hdr);
2259 encode_sequence(xdr, &args->seq_args, &hdr);
2260 encode_putfh(xdr, args->fh, &hdr);
2261 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002262 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002263}
2264
2265/*
2266 * Encode a CLOSE request
2267 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002268static void nfs4_xdr_enc_close(struct rpc_rqst *req, struct xdr_stream *xdr,
2269 struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002270{
Andy Adamson05d564f2008-12-23 16:06:15 -05002271 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002272 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05002273 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002274
Chuck Lever9f06c712010-12-14 14:59:18 +00002275 encode_compound_hdr(xdr, req, &hdr);
2276 encode_sequence(xdr, &args->seq_args, &hdr);
2277 encode_putfh(xdr, args->fh, &hdr);
Trond Myklebustcf805162016-11-15 14:56:07 -05002278 if (args->lr_args)
2279 encode_layoutreturn(xdr, args->lr_args, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002280 encode_close(xdr, args, &hdr);
Trond Myklebust3ecefc92016-10-27 18:25:04 -04002281 if (args->bitmask != NULL)
2282 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002283 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284}
2285
2286/*
2287 * Encode an OPEN request
2288 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002289static void nfs4_xdr_enc_open(struct rpc_rqst *req, struct xdr_stream *xdr,
2290 struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002291{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002292 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002293 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002294 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002295
Chuck Lever9f06c712010-12-14 14:59:18 +00002296 encode_compound_hdr(xdr, req, &hdr);
2297 encode_sequence(xdr, &args->seq_args, &hdr);
2298 encode_putfh(xdr, args->fh, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002299 encode_open(xdr, args, &hdr);
2300 encode_getfh(xdr, &hdr);
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07002301 if (args->access)
2302 encode_access(xdr, args->access, &hdr);
Trond Myklebust1549210f2012-06-05 09:16:47 -04002303 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002304 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002305}
2306
2307/*
2308 * Encode an OPEN_CONFIRM request
2309 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002310static void nfs4_xdr_enc_open_confirm(struct rpc_rqst *req,
2311 struct xdr_stream *xdr,
2312 struct nfs_open_confirmargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002313{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002314 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002315 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002316 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002317
Chuck Lever9f06c712010-12-14 14:59:18 +00002318 encode_compound_hdr(xdr, req, &hdr);
2319 encode_putfh(xdr, args->fh, &hdr);
2320 encode_open_confirm(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002321 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002322}
2323
2324/*
2325 * Encode an OPEN request with no attributes.
2326 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002327static void nfs4_xdr_enc_open_noattr(struct rpc_rqst *req,
2328 struct xdr_stream *xdr,
2329 struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002330{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002331 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002332 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002333 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002334
Chuck Lever9f06c712010-12-14 14:59:18 +00002335 encode_compound_hdr(xdr, req, &hdr);
2336 encode_sequence(xdr, &args->seq_args, &hdr);
2337 encode_putfh(xdr, args->fh, &hdr);
2338 encode_open(xdr, args, &hdr);
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07002339 if (args->access)
2340 encode_access(xdr, args->access, &hdr);
Andy Adamsone23008e2012-10-02 21:07:32 -04002341 encode_getfattr_open(xdr, args->bitmask, args->open_bitmap, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002342 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002343}
2344
2345/*
2346 * Encode an OPEN_DOWNGRADE request
2347 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002348static void nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req,
2349 struct xdr_stream *xdr,
2350 struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002351{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002352 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002353 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002354 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002355
Chuck Lever9f06c712010-12-14 14:59:18 +00002356 encode_compound_hdr(xdr, req, &hdr);
2357 encode_sequence(xdr, &args->seq_args, &hdr);
2358 encode_putfh(xdr, args->fh, &hdr);
2359 encode_open_downgrade(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002360 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002361}
2362
2363/*
2364 * Encode a LOCK request
2365 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002366static void nfs4_xdr_enc_lock(struct rpc_rqst *req, struct xdr_stream *xdr,
2367 struct nfs_lock_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002368{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002369 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002370 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002371 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002372
Chuck Lever9f06c712010-12-14 14:59:18 +00002373 encode_compound_hdr(xdr, req, &hdr);
2374 encode_sequence(xdr, &args->seq_args, &hdr);
2375 encode_putfh(xdr, args->fh, &hdr);
2376 encode_lock(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002377 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002378}
2379
2380/*
2381 * Encode a LOCKT request
2382 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002383static void nfs4_xdr_enc_lockt(struct rpc_rqst *req, struct xdr_stream *xdr,
2384 struct nfs_lockt_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002385{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002386 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002387 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002388 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002389
Chuck Lever9f06c712010-12-14 14:59:18 +00002390 encode_compound_hdr(xdr, req, &hdr);
2391 encode_sequence(xdr, &args->seq_args, &hdr);
2392 encode_putfh(xdr, args->fh, &hdr);
2393 encode_lockt(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002394 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002395}
2396
2397/*
2398 * Encode a LOCKU request
2399 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002400static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr,
2401 struct nfs_locku_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002402{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002403 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002404 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002405 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002406
Chuck Lever9f06c712010-12-14 14:59:18 +00002407 encode_compound_hdr(xdr, req, &hdr);
2408 encode_sequence(xdr, &args->seq_args, &hdr);
2409 encode_putfh(xdr, args->fh, &hdr);
2410 encode_locku(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002411 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002412}
2413
Chuck Lever9f06c712010-12-14 14:59:18 +00002414static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req,
2415 struct xdr_stream *xdr,
2416 struct nfs_release_lockowner_args *args)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002417{
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002418 struct compound_hdr hdr = {
2419 .minorversion = 0,
2420 };
2421
Chuck Lever9f06c712010-12-14 14:59:18 +00002422 encode_compound_hdr(xdr, req, &hdr);
2423 encode_release_lockowner(xdr, &args->lock_owner, &hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002424 encode_nops(&hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04002425}
2426
Linus Torvalds1da177e2005-04-16 15:20:36 -07002427/*
2428 * Encode a READLINK request
2429 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002430static void nfs4_xdr_enc_readlink(struct rpc_rqst *req, struct xdr_stream *xdr,
2431 const struct nfs4_readlink *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002432{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002433 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002434 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002435 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002436
Chuck Lever9f06c712010-12-14 14:59:18 +00002437 encode_compound_hdr(xdr, req, &hdr);
2438 encode_sequence(xdr, &args->seq_args, &hdr);
2439 encode_putfh(xdr, args->fh, &hdr);
2440 encode_readlink(xdr, args, req, &hdr);
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002441
Benny Halevy28f56692009-04-01 09:22:09 -04002442 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002443 args->pgbase, args->pglen);
Andy Adamsond0179312008-12-23 16:06:17 -05002444 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002445}
2446
2447/*
2448 * Encode a READDIR request
2449 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002450static void nfs4_xdr_enc_readdir(struct rpc_rqst *req, struct xdr_stream *xdr,
2451 const struct nfs4_readdir_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002452{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002453 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002454 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002455 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002456
Chuck Lever9f06c712010-12-14 14:59:18 +00002457 encode_compound_hdr(xdr, req, &hdr);
2458 encode_sequence(xdr, &args->seq_args, &hdr);
2459 encode_putfh(xdr, args->fh, &hdr);
2460 encode_readdir(xdr, args, req, &hdr);
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002461
Benny Halevy28f56692009-04-01 09:22:09 -04002462 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002463 args->pgbase, args->count);
2464 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
Benny Halevy28f56692009-04-01 09:22:09 -04002465 __func__, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002466 args->pgbase, args->count);
Andy Adamsond0179312008-12-23 16:06:17 -05002467 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002468}
2469
2470/*
2471 * Encode a READ request
2472 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002473static void nfs4_xdr_enc_read(struct rpc_rqst *req, struct xdr_stream *xdr,
Anna Schumaker3c6b8992014-05-06 09:12:24 -04002474 struct nfs_pgio_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002475{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002476 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002477 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002478 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
Chuck Lever9f06c712010-12-14 14:59:18 +00002480 encode_compound_hdr(xdr, req, &hdr);
2481 encode_sequence(xdr, &args->seq_args, &hdr);
2482 encode_putfh(xdr, args->fh, &hdr);
2483 encode_read(xdr, args, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002484
Benny Halevy28f56692009-04-01 09:22:09 -04002485 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002486 args->pages, args->pgbase, args->count);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002487 req->rq_rcv_buf.flags |= XDRBUF_READ;
Andy Adamsond0179312008-12-23 16:06:17 -05002488 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002489}
2490
2491/*
2492 * Encode an SETATTR request
2493 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002494static void nfs4_xdr_enc_setattr(struct rpc_rqst *req, struct xdr_stream *xdr,
2495 struct nfs_setattrargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002496{
Andy Adamson05d564f2008-12-23 16:06:15 -05002497 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002498 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05002499 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002500
Chuck Lever9f06c712010-12-14 14:59:18 +00002501 encode_compound_hdr(xdr, req, &hdr);
2502 encode_sequence(xdr, &args->seq_args, &hdr);
2503 encode_putfh(xdr, args->fh, &hdr);
2504 encode_setattr(xdr, args, args->server, &hdr);
2505 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002506 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507}
2508
2509/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00002510 * Encode a GETACL request
2511 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002512static void nfs4_xdr_enc_getacl(struct rpc_rqst *req, struct xdr_stream *xdr,
2513 struct nfs_getaclargs *args)
J. Bruce Fields029d1052005-06-22 17:16:22 +00002514{
J. Bruce Fields029d1052005-06-22 17:16:22 +00002515 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002516 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
J. Bruce Fields029d1052005-06-22 17:16:22 +00002517 };
Benny Halevy28f56692009-04-01 09:22:09 -04002518 uint32_t replen;
J. Bruce Fields029d1052005-06-22 17:16:22 +00002519
Chuck Lever9f06c712010-12-14 14:59:18 +00002520 encode_compound_hdr(xdr, req, &hdr);
2521 encode_sequence(xdr, &args->seq_args, &hdr);
2522 encode_putfh(xdr, args->fh, &hdr);
Andy Adamsonbf118a32011-12-07 11:55:27 -05002523 replen = hdr.replen + op_decode_hdr_maxsz + 1;
Chuck Lever9f06c712010-12-14 14:59:18 +00002524 encode_getattr_two(xdr, FATTR4_WORD0_ACL, 0, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002525
Benny Halevy28f56692009-04-01 09:22:09 -04002526 xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
Andreas Gruenbacher8fbcf232015-11-03 18:25:34 +01002527 args->acl_pages, 0, args->acl_len);
Andy Adamsonbf118a32011-12-07 11:55:27 -05002528
Andy Adamsond0179312008-12-23 16:06:17 -05002529 encode_nops(&hdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00002530}
2531
2532/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002533 * Encode a WRITE request
2534 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002535static void nfs4_xdr_enc_write(struct rpc_rqst *req, struct xdr_stream *xdr,
Anna Schumaker3c6b8992014-05-06 09:12:24 -04002536 struct nfs_pgio_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002537{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002538 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002539 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002541
Chuck Lever9f06c712010-12-14 14:59:18 +00002542 encode_compound_hdr(xdr, req, &hdr);
2543 encode_sequence(xdr, &args->seq_args, &hdr);
2544 encode_putfh(xdr, args->fh, &hdr);
2545 encode_write(xdr, args, &hdr);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002546 req->rq_snd_buf.flags |= XDRBUF_WRITE;
Fred Isaman7ffd1062011-03-03 15:13:46 +00002547 if (args->bitmask)
2548 encode_getfattr(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002549 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002550}
2551
2552/*
2553 * a COMMIT request
2554 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002555static void nfs4_xdr_enc_commit(struct rpc_rqst *req, struct xdr_stream *xdr,
Fred Isaman0b7c0152012-04-20 14:47:39 -04002556 struct nfs_commitargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002557{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002558 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002559 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002560 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002561
Chuck Lever9f06c712010-12-14 14:59:18 +00002562 encode_compound_hdr(xdr, req, &hdr);
2563 encode_sequence(xdr, &args->seq_args, &hdr);
2564 encode_putfh(xdr, args->fh, &hdr);
2565 encode_commit(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002566 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002567}
2568
2569/*
2570 * FSINFO request
2571 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002572static void nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
2573 struct nfs4_fsinfo_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002574{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002575 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002576 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002577 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
Chuck Lever9f06c712010-12-14 14:59:18 +00002579 encode_compound_hdr(xdr, req, &hdr);
2580 encode_sequence(xdr, &args->seq_args, &hdr);
2581 encode_putfh(xdr, args->fh, &hdr);
2582 encode_fsinfo(xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002583 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002584}
2585
2586/*
2587 * a PATHCONF request
2588 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002589static void nfs4_xdr_enc_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
2590 const struct nfs4_pathconf_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002592 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002593 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002595
Chuck Lever9f06c712010-12-14 14:59:18 +00002596 encode_compound_hdr(xdr, req, &hdr);
2597 encode_sequence(xdr, &args->seq_args, &hdr);
2598 encode_putfh(xdr, args->fh, &hdr);
2599 encode_getattr_one(xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002600 &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002601 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002602}
2603
2604/*
2605 * a STATFS request
2606 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002607static void nfs4_xdr_enc_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
2608 const struct nfs4_statfs_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002610 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002611 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002612 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613
Chuck Lever9f06c712010-12-14 14:59:18 +00002614 encode_compound_hdr(xdr, req, &hdr);
2615 encode_sequence(xdr, &args->seq_args, &hdr);
2616 encode_putfh(xdr, args->fh, &hdr);
2617 encode_getattr_two(xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002618 args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002619 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002620}
2621
2622/*
2623 * GETATTR_BITMAP request
2624 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002625static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req,
2626 struct xdr_stream *xdr,
2627 struct nfs4_server_caps_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628{
Kinglong Mee8c612822015-08-26 21:12:58 +08002629 const u32 *bitmask = args->bitmask;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002630 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002631 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002632 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002633
Chuck Lever9f06c712010-12-14 14:59:18 +00002634 encode_compound_hdr(xdr, req, &hdr);
2635 encode_sequence(xdr, &args->seq_args, &hdr);
2636 encode_putfh(xdr, args->fhandle, &hdr);
Kinglong Mee8c612822015-08-26 21:12:58 +08002637 encode_getattr_three(xdr, bitmask[0], bitmask[1], bitmask[2], &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002638 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002639}
2640
2641/*
2642 * a RENEW request
2643 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002644static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr,
2645 struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002647 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002648 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002649 };
2650
Chuck Lever9f06c712010-12-14 14:59:18 +00002651 encode_compound_hdr(xdr, req, &hdr);
Chuck Leverbb4dae52012-03-01 17:01:48 -05002652 encode_renew(xdr, clp->cl_clientid, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002653 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002654}
2655
2656/*
2657 * a SETCLIENTID request
2658 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002659static void nfs4_xdr_enc_setclientid(struct rpc_rqst *req,
2660 struct xdr_stream *xdr,
2661 struct nfs4_setclientid *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002663 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002664 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002665 };
2666
Chuck Lever9f06c712010-12-14 14:59:18 +00002667 encode_compound_hdr(xdr, req, &hdr);
2668 encode_setclientid(xdr, sc, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002669 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002670}
2671
2672/*
2673 * a SETCLIENTID_CONFIRM request
2674 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002675static void nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req,
2676 struct xdr_stream *xdr,
2677 struct nfs4_setclientid_res *arg)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002678{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002679 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002680 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002681 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682
Chuck Lever9f06c712010-12-14 14:59:18 +00002683 encode_compound_hdr(xdr, req, &hdr);
2684 encode_setclientid_confirm(xdr, arg, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002685 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002686}
2687
2688/*
2689 * DELEGRETURN request
2690 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002691static void nfs4_xdr_enc_delegreturn(struct rpc_rqst *req,
2692 struct xdr_stream *xdr,
2693 const struct nfs4_delegreturnargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002694{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002695 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002696 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002697 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002698
Chuck Lever9f06c712010-12-14 14:59:18 +00002699 encode_compound_hdr(xdr, req, &hdr);
2700 encode_sequence(xdr, &args->seq_args, &hdr);
2701 encode_putfh(xdr, args->fhandle, &hdr);
Trond Myklebust586f1c32016-11-15 15:03:33 -05002702 if (args->lr_args)
2703 encode_layoutreturn(xdr, args->lr_args, &hdr);
Chuck Lever9f06c712010-12-14 14:59:18 +00002704 encode_getfattr(xdr, args->bitmask, &hdr);
Trond Myklebuste144cbc2012-04-28 16:05:03 -04002705 encode_delegreturn(xdr, args->stateid, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002706 encode_nops(&hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002707}
2708
2709/*
Trond Myklebust683b57b2006-06-09 09:34:22 -04002710 * Encode FS_LOCATIONS request
2711 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002712static void nfs4_xdr_enc_fs_locations(struct rpc_rqst *req,
2713 struct xdr_stream *xdr,
2714 struct nfs4_fs_locations_arg *args)
Trond Myklebust683b57b2006-06-09 09:34:22 -04002715{
Trond Myklebust683b57b2006-06-09 09:34:22 -04002716 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002717 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Trond Myklebust683b57b2006-06-09 09:34:22 -04002718 };
Benny Halevy28f56692009-04-01 09:22:09 -04002719 uint32_t replen;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002720
Chuck Lever9f06c712010-12-14 14:59:18 +00002721 encode_compound_hdr(xdr, req, &hdr);
2722 encode_sequence(xdr, &args->seq_args, &hdr);
Chuck Leverb03d7352013-10-17 14:12:50 -04002723 if (args->migration) {
2724 encode_putfh(xdr, args->fh, &hdr);
2725 replen = hdr.replen;
2726 encode_fs_locations(xdr, args->bitmask, &hdr);
2727 if (args->renew)
2728 encode_renew(xdr, args->clientid, &hdr);
2729 } else {
2730 encode_putfh(xdr, args->dir_fh, &hdr);
2731 encode_lookup(xdr, args->name, &hdr);
2732 replen = hdr.replen;
2733 encode_fs_locations(xdr, args->bitmask, &hdr);
2734 }
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002735
Chuck Leverb03d7352013-10-17 14:12:50 -04002736 /* Set up reply kvec to capture returned fs_locations array. */
Benny Halevy28f56692009-04-01 09:22:09 -04002737 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
Trond Myklebust683b57b2006-06-09 09:34:22 -04002738 0, PAGE_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05002739 encode_nops(&hdr);
Trond Myklebust683b57b2006-06-09 09:34:22 -04002740}
2741
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00002742/*
2743 * Encode SECINFO request
2744 */
2745static void nfs4_xdr_enc_secinfo(struct rpc_rqst *req,
2746 struct xdr_stream *xdr,
2747 struct nfs4_secinfo_arg *args)
2748{
2749 struct compound_hdr hdr = {
2750 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2751 };
2752
2753 encode_compound_hdr(xdr, req, &hdr);
2754 encode_sequence(xdr, &args->seq_args, &hdr);
2755 encode_putfh(xdr, args->dir_fh, &hdr);
2756 encode_secinfo(xdr, args->name, &hdr);
2757 encode_nops(&hdr);
2758}
2759
Chuck Lever44c99932013-10-17 14:13:30 -04002760/*
2761 * Encode FSID_PRESENT request
2762 */
2763static void nfs4_xdr_enc_fsid_present(struct rpc_rqst *req,
2764 struct xdr_stream *xdr,
2765 struct nfs4_fsid_present_arg *args)
2766{
2767 struct compound_hdr hdr = {
2768 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2769 };
2770
2771 encode_compound_hdr(xdr, req, &hdr);
2772 encode_sequence(xdr, &args->seq_args, &hdr);
2773 encode_putfh(xdr, args->fh, &hdr);
2774 encode_getfh(xdr, &hdr);
2775 if (args->renew)
2776 encode_renew(xdr, args->clientid, &hdr);
2777 encode_nops(&hdr);
2778}
2779
Benny Halevy99fe60d2009-04-01 09:22:29 -04002780#if defined(CONFIG_NFS_V4_1)
2781/*
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002782 * BIND_CONN_TO_SESSION request
2783 */
2784static void nfs4_xdr_enc_bind_conn_to_session(struct rpc_rqst *req,
2785 struct xdr_stream *xdr,
Trond Myklebust71a097c2015-02-18 09:27:18 -08002786 struct nfs41_bind_conn_to_session_args *args)
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002787{
2788 struct compound_hdr hdr = {
Trond Myklebust71a097c2015-02-18 09:27:18 -08002789 .minorversion = args->client->cl_mvops->minor_version,
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002790 };
2791
2792 encode_compound_hdr(xdr, req, &hdr);
Trond Myklebust71a097c2015-02-18 09:27:18 -08002793 encode_bind_conn_to_session(xdr, args, &hdr);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04002794 encode_nops(&hdr);
2795}
2796
2797/*
Benny Halevy99fe60d2009-04-01 09:22:29 -04002798 * EXCHANGE_ID request
2799 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002800static void nfs4_xdr_enc_exchange_id(struct rpc_rqst *req,
2801 struct xdr_stream *xdr,
2802 struct nfs41_exchange_id_args *args)
Benny Halevy99fe60d2009-04-01 09:22:29 -04002803{
Benny Halevy99fe60d2009-04-01 09:22:29 -04002804 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002805 .minorversion = args->client->cl_mvops->minor_version,
Benny Halevy99fe60d2009-04-01 09:22:29 -04002806 };
2807
Chuck Lever9f06c712010-12-14 14:59:18 +00002808 encode_compound_hdr(xdr, req, &hdr);
2809 encode_exchange_id(xdr, args, &hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04002810 encode_nops(&hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04002811}
Andy Adamson2050f0c2009-04-01 09:22:30 -04002812
2813/*
Andy Adamsonfc931582009-04-01 09:22:31 -04002814 * a CREATE_SESSION request
2815 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002816static void nfs4_xdr_enc_create_session(struct rpc_rqst *req,
2817 struct xdr_stream *xdr,
2818 struct nfs41_create_session_args *args)
Andy Adamsonfc931582009-04-01 09:22:31 -04002819{
Andy Adamsonfc931582009-04-01 09:22:31 -04002820 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002821 .minorversion = args->client->cl_mvops->minor_version,
Andy Adamsonfc931582009-04-01 09:22:31 -04002822 };
2823
Chuck Lever9f06c712010-12-14 14:59:18 +00002824 encode_compound_hdr(xdr, req, &hdr);
2825 encode_create_session(xdr, args, &hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04002826 encode_nops(&hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04002827}
2828
2829/*
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002830 * a DESTROY_SESSION request
2831 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002832static void nfs4_xdr_enc_destroy_session(struct rpc_rqst *req,
2833 struct xdr_stream *xdr,
2834 struct nfs4_session *session)
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002835{
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002836 struct compound_hdr hdr = {
Trond Myklebusta4432342010-06-16 09:52:27 -04002837 .minorversion = session->clp->cl_mvops->minor_version,
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002838 };
2839
Chuck Lever9f06c712010-12-14 14:59:18 +00002840 encode_compound_hdr(xdr, req, &hdr);
2841 encode_destroy_session(xdr, session, &hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002842 encode_nops(&hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002843}
2844
2845/*
Trond Myklebust66245532012-05-25 17:18:09 -04002846 * a DESTROY_CLIENTID request
2847 */
2848static void nfs4_xdr_enc_destroy_clientid(struct rpc_rqst *req,
2849 struct xdr_stream *xdr,
2850 struct nfs_client *clp)
2851{
2852 struct compound_hdr hdr = {
2853 .minorversion = clp->cl_mvops->minor_version,
2854 };
2855
2856 encode_compound_hdr(xdr, req, &hdr);
2857 encode_destroy_clientid(xdr, clp->cl_clientid, &hdr);
2858 encode_nops(&hdr);
2859}
2860
2861/*
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002862 * a SEQUENCE request
2863 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002864static void nfs4_xdr_enc_sequence(struct rpc_rqst *req, struct xdr_stream *xdr,
2865 struct nfs4_sequence_args *args)
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002866{
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002867 struct compound_hdr hdr = {
2868 .minorversion = nfs4_xdr_minorversion(args),
2869 };
2870
Chuck Lever9f06c712010-12-14 14:59:18 +00002871 encode_compound_hdr(xdr, req, &hdr);
2872 encode_sequence(xdr, args, &hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002873 encode_nops(&hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002874}
2875
2876/*
Andy Adamson2050f0c2009-04-01 09:22:30 -04002877 * a GET_LEASE_TIME request
2878 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002879static void nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req,
2880 struct xdr_stream *xdr,
2881 struct nfs4_get_lease_time_args *args)
Andy Adamson2050f0c2009-04-01 09:22:30 -04002882{
Andy Adamson2050f0c2009-04-01 09:22:30 -04002883 struct compound_hdr hdr = {
2884 .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
2885 };
Fred Isamandae100c2011-07-30 20:52:37 -04002886 const u32 lease_bitmap[3] = { FATTR4_WORD0_LEASE_TIME };
Andy Adamson2050f0c2009-04-01 09:22:30 -04002887
Chuck Lever9f06c712010-12-14 14:59:18 +00002888 encode_compound_hdr(xdr, req, &hdr);
2889 encode_sequence(xdr, &args->la_seq_args, &hdr);
2890 encode_putrootfh(xdr, &hdr);
2891 encode_fsinfo(xdr, lease_bitmap, &hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04002892 encode_nops(&hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04002893}
Ricardo Labiaga180197532009-12-05 16:08:40 -05002894
2895/*
2896 * a RECLAIM_COMPLETE request
2897 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002898static void nfs4_xdr_enc_reclaim_complete(struct rpc_rqst *req,
2899 struct xdr_stream *xdr,
2900 struct nfs41_reclaim_complete_args *args)
Ricardo Labiaga180197532009-12-05 16:08:40 -05002901{
Ricardo Labiaga180197532009-12-05 16:08:40 -05002902 struct compound_hdr hdr = {
2903 .minorversion = nfs4_xdr_minorversion(&args->seq_args)
2904 };
2905
Chuck Lever9f06c712010-12-14 14:59:18 +00002906 encode_compound_hdr(xdr, req, &hdr);
2907 encode_sequence(xdr, &args->seq_args, &hdr);
2908 encode_reclaim_complete(xdr, args, &hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05002909 encode_nops(&hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05002910}
2911
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002912/*
2913 * Encode GETDEVICEINFO request
2914 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002915static void nfs4_xdr_enc_getdeviceinfo(struct rpc_rqst *req,
2916 struct xdr_stream *xdr,
2917 struct nfs4_getdeviceinfo_args *args)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002918{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002919 struct compound_hdr hdr = {
2920 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2921 };
2922
Chuck Lever9f06c712010-12-14 14:59:18 +00002923 encode_compound_hdr(xdr, req, &hdr);
2924 encode_sequence(xdr, &args->seq_args, &hdr);
2925 encode_getdeviceinfo(xdr, args, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002926
2927 /* set up reply kvec. Subtract notification bitmap max size (2)
2928 * so that notification bitmap is put in xdr_buf tail */
2929 xdr_inline_pages(&req->rq_rcv_buf, (hdr.replen - 2) << 2,
2930 args->pdev->pages, args->pdev->pgbase,
2931 args->pdev->pglen);
2932
2933 encode_nops(&hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002934}
2935
2936/*
2937 * Encode LAYOUTGET request
2938 */
Chuck Lever9f06c712010-12-14 14:59:18 +00002939static void nfs4_xdr_enc_layoutget(struct rpc_rqst *req,
2940 struct xdr_stream *xdr,
2941 struct nfs4_layoutget_args *args)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002942{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002943 struct compound_hdr hdr = {
2944 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2945 };
2946
Chuck Lever9f06c712010-12-14 14:59:18 +00002947 encode_compound_hdr(xdr, req, &hdr);
2948 encode_sequence(xdr, &args->seq_args, &hdr);
2949 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2950 encode_layoutget(xdr, args, &hdr);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04002951
2952 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
2953 args->layout.pages, 0, args->layout.pglen);
2954
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002955 encode_nops(&hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04002956}
Andy Adamson863a3c62011-03-23 13:27:54 +00002957
2958/*
2959 * Encode LAYOUTCOMMIT request
2960 */
Benny Halevycbe82602011-05-22 19:52:37 +03002961static void nfs4_xdr_enc_layoutcommit(struct rpc_rqst *req,
2962 struct xdr_stream *xdr,
2963 struct nfs4_layoutcommit_args *args)
Andy Adamson863a3c62011-03-23 13:27:54 +00002964{
Benny Halevyac7db722011-05-22 19:53:48 +03002965 struct nfs4_layoutcommit_data *data =
2966 container_of(args, struct nfs4_layoutcommit_data, args);
Andy Adamson863a3c62011-03-23 13:27:54 +00002967 struct compound_hdr hdr = {
2968 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2969 };
2970
2971 encode_compound_hdr(xdr, req, &hdr);
2972 encode_sequence(xdr, &args->seq_args, &hdr);
2973 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
Benny Halevyac7db722011-05-22 19:53:48 +03002974 encode_layoutcommit(xdr, data->args.inode, args, &hdr);
Andy Adamson863a3c62011-03-23 13:27:54 +00002975 encode_getfattr(xdr, args->bitmask, &hdr);
2976 encode_nops(&hdr);
Benny Halevycbe82602011-05-22 19:52:37 +03002977}
2978
2979/*
2980 * Encode LAYOUTRETURN request
2981 */
2982static void nfs4_xdr_enc_layoutreturn(struct rpc_rqst *req,
2983 struct xdr_stream *xdr,
2984 struct nfs4_layoutreturn_args *args)
2985{
2986 struct compound_hdr hdr = {
2987 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
2988 };
2989
2990 encode_compound_hdr(xdr, req, &hdr);
2991 encode_sequence(xdr, &args->seq_args, &hdr);
2992 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
2993 encode_layoutreturn(xdr, args, &hdr);
2994 encode_nops(&hdr);
Andy Adamson863a3c62011-03-23 13:27:54 +00002995}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04002996
2997/*
2998 * Encode SECINFO_NO_NAME request
2999 */
3000static int nfs4_xdr_enc_secinfo_no_name(struct rpc_rqst *req,
3001 struct xdr_stream *xdr,
3002 struct nfs41_secinfo_no_name_args *args)
3003{
3004 struct compound_hdr hdr = {
3005 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
3006 };
3007
3008 encode_compound_hdr(xdr, req, &hdr);
3009 encode_sequence(xdr, &args->seq_args, &hdr);
3010 encode_putrootfh(xdr, &hdr);
3011 encode_secinfo_no_name(xdr, args, &hdr);
3012 encode_nops(&hdr);
3013 return 0;
3014}
Bryan Schumaker7d974792011-06-02 14:59:08 -04003015
3016/*
3017 * Encode TEST_STATEID request
3018 */
3019static void nfs4_xdr_enc_test_stateid(struct rpc_rqst *req,
3020 struct xdr_stream *xdr,
3021 struct nfs41_test_stateid_args *args)
3022{
3023 struct compound_hdr hdr = {
3024 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
3025 };
3026
3027 encode_compound_hdr(xdr, req, &hdr);
3028 encode_sequence(xdr, &args->seq_args, &hdr);
3029 encode_test_stateid(xdr, args, &hdr);
3030 encode_nops(&hdr);
3031}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04003032
3033/*
3034 * Encode FREE_STATEID request
3035 */
3036static void nfs4_xdr_enc_free_stateid(struct rpc_rqst *req,
3037 struct xdr_stream *xdr,
3038 struct nfs41_free_stateid_args *args)
3039{
3040 struct compound_hdr hdr = {
3041 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
3042 };
3043
3044 encode_compound_hdr(xdr, req, &hdr);
3045 encode_sequence(xdr, &args->seq_args, &hdr);
3046 encode_free_stateid(xdr, args, &hdr);
3047 encode_nops(&hdr);
3048}
Benny Halevy99fe60d2009-04-01 09:22:29 -04003049#endif /* CONFIG_NFS_V4_1 */
3050
Benny Halevy686841b2009-08-14 17:19:48 +03003051static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
3052{
3053 dprintk("nfs: %s: prematurely hit end of receive buffer. "
3054 "Remaining buffer length is %tu words.\n",
3055 func, xdr->end - xdr->p);
3056}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003057
Trond Myklebust683b57b2006-06-09 09:34:22 -04003058static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003059{
Al Viro8687b632006-10-19 23:28:48 -07003060 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003061
Benny Halevyc0eae662009-08-14 17:20:14 +03003062 p = xdr_inline_decode(xdr, 4);
3063 if (unlikely(!p))
3064 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003065 *len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003066 p = xdr_inline_decode(xdr, *len);
3067 if (unlikely(!p))
3068 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003069 *string = (char *)p;
3070 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003071out_overflow:
3072 print_overflow_msg(__func__, xdr);
3073 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003074}
3075
3076static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
3077{
Al Viro8687b632006-10-19 23:28:48 -07003078 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003079
Benny Halevyc0eae662009-08-14 17:20:14 +03003080 p = xdr_inline_decode(xdr, 8);
3081 if (unlikely(!p))
3082 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003083 hdr->status = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03003084 hdr->taglen = be32_to_cpup(p);
Andy Adamson6c0195a2008-12-23 16:06:15 -05003085
Benny Halevyc0eae662009-08-14 17:20:14 +03003086 p = xdr_inline_decode(xdr, hdr->taglen + 4);
3087 if (unlikely(!p))
3088 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003089 hdr->tag = (char *)p;
3090 p += XDR_QUADLEN(hdr->taglen);
Benny Halevycccddf42009-08-14 17:20:19 +03003091 hdr->nops = be32_to_cpup(p);
Benny Halevyaadf6152008-12-23 16:06:13 -05003092 if (unlikely(hdr->nops < 1))
3093 return nfs4_stat_to_errno(hdr->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003095out_overflow:
3096 print_overflow_msg(__func__, xdr);
3097 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003098}
3099
Trond Myklebustc7848f62013-12-04 17:39:23 -05003100static bool __decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected,
3101 int *nfs_retval)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003102{
Al Viro8687b632006-10-19 23:28:48 -07003103 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003104 uint32_t opnum;
3105 int32_t nfserr;
3106
Benny Halevyc0eae662009-08-14 17:20:14 +03003107 p = xdr_inline_decode(xdr, 8);
3108 if (unlikely(!p))
3109 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003110 opnum = be32_to_cpup(p++);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003111 if (unlikely(opnum != expected))
3112 goto out_bad_operation;
Benny Halevycccddf42009-08-14 17:20:19 +03003113 nfserr = be32_to_cpup(p);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003114 if (nfserr == NFS_OK)
3115 *nfs_retval = 0;
3116 else
3117 *nfs_retval = nfs4_stat_to_errno(nfserr);
3118 return true;
3119out_bad_operation:
3120 dprintk("nfs: Server returned operation"
3121 " %d but we issued a request for %d\n",
3122 opnum, expected);
3123 *nfs_retval = -EREMOTEIO;
3124 return false;
Benny Halevyc0eae662009-08-14 17:20:14 +03003125out_overflow:
3126 print_overflow_msg(__func__, xdr);
Trond Myklebustc7848f62013-12-04 17:39:23 -05003127 *nfs_retval = -EIO;
3128 return false;
3129}
3130
3131static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
3132{
3133 int retval;
3134
3135 __decode_op_hdr(xdr, expected, &retval);
3136 return retval;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003137}
3138
3139/* Dummy routine */
David Howellsadfa6f92006-08-22 20:06:08 -04003140static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003141{
Al Viro8687b632006-10-19 23:28:48 -07003142 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003143 unsigned int strlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 char *str;
3145
Benny Halevyc0eae662009-08-14 17:20:14 +03003146 p = xdr_inline_decode(xdr, 12);
3147 if (likely(p))
3148 return decode_opaque_inline(xdr, &strlen, &str);
3149 print_overflow_msg(__func__, xdr);
3150 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003151}
3152
3153static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
3154{
Al Viro8687b632006-10-19 23:28:48 -07003155 uint32_t bmlen;
3156 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003157
Benny Halevyc0eae662009-08-14 17:20:14 +03003158 p = xdr_inline_decode(xdr, 4);
3159 if (unlikely(!p))
3160 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003161 bmlen = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003162
Fred Isamandae100c2011-07-30 20:52:37 -04003163 bitmap[0] = bitmap[1] = bitmap[2] = 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003164 p = xdr_inline_decode(xdr, (bmlen << 2));
3165 if (unlikely(!p))
3166 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 if (bmlen > 0) {
Benny Halevy6f723f72009-08-14 17:19:37 +03003168 bitmap[0] = be32_to_cpup(p++);
Fred Isamandae100c2011-07-30 20:52:37 -04003169 if (bmlen > 1) {
3170 bitmap[1] = be32_to_cpup(p++);
3171 if (bmlen > 2)
3172 bitmap[2] = be32_to_cpup(p);
3173 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003174 }
3175 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003176out_overflow:
3177 print_overflow_msg(__func__, xdr);
3178 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003179}
3180
Trond Myklebust256e48b2012-06-21 11:18:13 -04003181static int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, unsigned int *savep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003182{
Al Viro8687b632006-10-19 23:28:48 -07003183 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003184
Benny Halevyc0eae662009-08-14 17:20:14 +03003185 p = xdr_inline_decode(xdr, 4);
3186 if (unlikely(!p))
3187 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003188 *attrlen = be32_to_cpup(p);
Trond Myklebust256e48b2012-06-21 11:18:13 -04003189 *savep = xdr_stream_pos(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003190 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003191out_overflow:
3192 print_overflow_msg(__func__, xdr);
3193 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194}
3195
3196static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
3197{
3198 if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
Roman Borisov3388bff2010-10-13 16:54:51 +04003199 int ret;
3200 ret = decode_attr_bitmap(xdr, bitmask);
3201 if (unlikely(ret < 0))
3202 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
3204 } else
Fred Isamandae100c2011-07-30 20:52:37 -04003205 bitmask[0] = bitmask[1] = bitmask[2] = 0;
3206 dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
3207 bitmask[0], bitmask[1], bitmask[2]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003208 return 0;
3209}
3210
3211static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
3212{
Al Viro8687b632006-10-19 23:28:48 -07003213 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003214 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003215
3216 *type = 0;
3217 if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
3218 return -EIO;
3219 if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003220 p = xdr_inline_decode(xdr, 4);
3221 if (unlikely(!p))
3222 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003223 *type = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003224 if (*type < NF4REG || *type > NF4NAMEDATTR) {
Harvey Harrison3110ff82008-05-02 13:42:44 -07003225 dprintk("%s: bad type %d\n", __func__, *type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 return -EIO;
3227 }
3228 bitmap[0] &= ~FATTR4_WORD0_TYPE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003229 ret = NFS_ATTR_FATTR_TYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003230 }
Trond Myklebustbca79472009-03-11 14:10:26 -04003231 dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
Trond Myklebust409924e2009-03-11 14:10:27 -04003232 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003233out_overflow:
3234 print_overflow_msg(__func__, xdr);
3235 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003236}
3237
Chuck Lever264e6352012-03-01 17:02:05 -05003238static int decode_attr_fh_expire_type(struct xdr_stream *xdr,
3239 uint32_t *bitmap, uint32_t *type)
3240{
3241 __be32 *p;
3242
3243 *type = 0;
3244 if (unlikely(bitmap[0] & (FATTR4_WORD0_FH_EXPIRE_TYPE - 1U)))
3245 return -EIO;
3246 if (likely(bitmap[0] & FATTR4_WORD0_FH_EXPIRE_TYPE)) {
3247 p = xdr_inline_decode(xdr, 4);
3248 if (unlikely(!p))
3249 goto out_overflow;
3250 *type = be32_to_cpup(p);
3251 bitmap[0] &= ~FATTR4_WORD0_FH_EXPIRE_TYPE;
3252 }
3253 dprintk("%s: expire type=0x%x\n", __func__, *type);
3254 return 0;
3255out_overflow:
3256 print_overflow_msg(__func__, xdr);
3257 return -EIO;
3258}
3259
Linus Torvalds1da177e2005-04-16 15:20:36 -07003260static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
3261{
Al Viro8687b632006-10-19 23:28:48 -07003262 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003263 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003264
3265 *change = 0;
3266 if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
3267 return -EIO;
3268 if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003269 p = xdr_inline_decode(xdr, 8);
3270 if (unlikely(!p))
3271 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003272 xdr_decode_hyper(p, change);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003273 bitmap[0] &= ~FATTR4_WORD0_CHANGE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003274 ret = NFS_ATTR_FATTR_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003275 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003276 dprintk("%s: change attribute=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 (unsigned long long)*change);
Trond Myklebust409924e2009-03-11 14:10:27 -04003278 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003279out_overflow:
3280 print_overflow_msg(__func__, xdr);
3281 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003282}
3283
3284static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
3285{
Al Viro8687b632006-10-19 23:28:48 -07003286 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003287 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
3289 *size = 0;
3290 if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
3291 return -EIO;
3292 if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003293 p = xdr_inline_decode(xdr, 8);
3294 if (unlikely(!p))
3295 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003296 xdr_decode_hyper(p, size);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003297 bitmap[0] &= ~FATTR4_WORD0_SIZE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003298 ret = NFS_ATTR_FATTR_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003300 dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
Trond Myklebust409924e2009-03-11 14:10:27 -04003301 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003302out_overflow:
3303 print_overflow_msg(__func__, xdr);
3304 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003305}
3306
3307static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3308{
Al Viro8687b632006-10-19 23:28:48 -07003309 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003310
3311 *res = 0;
3312 if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
3313 return -EIO;
3314 if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003315 p = xdr_inline_decode(xdr, 4);
3316 if (unlikely(!p))
3317 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003318 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003319 bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
3320 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003321 dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003322 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003323out_overflow:
3324 print_overflow_msg(__func__, xdr);
3325 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003326}
3327
3328static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3329{
Al Viro8687b632006-10-19 23:28:48 -07003330 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331
3332 *res = 0;
3333 if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
3334 return -EIO;
3335 if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003336 p = xdr_inline_decode(xdr, 4);
3337 if (unlikely(!p))
3338 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003339 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003340 bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
3341 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003342 dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003343 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003344out_overflow:
3345 print_overflow_msg(__func__, xdr);
3346 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003347}
3348
Trond Myklebust8b4bdcf2006-06-09 09:34:19 -04003349static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003350{
Al Viro8687b632006-10-19 23:28:48 -07003351 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003352 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003353
3354 fsid->major = 0;
3355 fsid->minor = 0;
3356 if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
3357 return -EIO;
3358 if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003359 p = xdr_inline_decode(xdr, 16);
3360 if (unlikely(!p))
3361 goto out_overflow;
Benny Halevy3ceb4db2009-08-14 17:19:41 +03003362 p = xdr_decode_hyper(p, &fsid->major);
Benny Halevycccddf42009-08-14 17:20:19 +03003363 xdr_decode_hyper(p, &fsid->minor);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003364 bitmap[0] &= ~FATTR4_WORD0_FSID;
Trond Myklebust409924e2009-03-11 14:10:27 -04003365 ret = NFS_ATTR_FATTR_FSID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003366 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003367 dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003368 (unsigned long long)fsid->major,
3369 (unsigned long long)fsid->minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04003370 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003371out_overflow:
3372 print_overflow_msg(__func__, xdr);
3373 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003374}
3375
3376static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3377{
Al Viro8687b632006-10-19 23:28:48 -07003378 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003379
3380 *res = 60;
3381 if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
3382 return -EIO;
3383 if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003384 p = xdr_inline_decode(xdr, 4);
3385 if (unlikely(!p))
3386 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003387 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
3389 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003390 dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003391 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003392out_overflow:
3393 print_overflow_msg(__func__, xdr);
3394 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003395}
3396
Trond Myklebustee7b75f2011-06-16 13:15:41 -04003397static int decode_attr_error(struct xdr_stream *xdr, uint32_t *bitmap, int32_t *res)
Bryan Schumakerae42c702010-10-21 16:33:17 -04003398{
3399 __be32 *p;
3400
3401 if (unlikely(bitmap[0] & (FATTR4_WORD0_RDATTR_ERROR - 1U)))
3402 return -EIO;
3403 if (likely(bitmap[0] & FATTR4_WORD0_RDATTR_ERROR)) {
3404 p = xdr_inline_decode(xdr, 4);
3405 if (unlikely(!p))
3406 goto out_overflow;
3407 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
Trond Myklebustee7b75f2011-06-16 13:15:41 -04003408 *res = -be32_to_cpup(p);
Bryan Schumakerae42c702010-10-21 16:33:17 -04003409 }
3410 return 0;
3411out_overflow:
3412 print_overflow_msg(__func__, xdr);
3413 return -EIO;
3414}
3415
Kinglong Mee8c612822015-08-26 21:12:58 +08003416static int decode_attr_exclcreat_supported(struct xdr_stream *xdr,
3417 uint32_t *bitmap, uint32_t *bitmask)
3418{
3419 if (likely(bitmap[2] & FATTR4_WORD2_SUPPATTR_EXCLCREAT)) {
3420 int ret;
3421 ret = decode_attr_bitmap(xdr, bitmask);
3422 if (unlikely(ret < 0))
3423 return ret;
3424 bitmap[2] &= ~FATTR4_WORD2_SUPPATTR_EXCLCREAT;
3425 } else
3426 bitmask[0] = bitmask[1] = bitmask[2] = 0;
3427 dprintk("%s: bitmask=%08x:%08x:%08x\n", __func__,
3428 bitmask[0], bitmask[1], bitmask[2]);
3429 return 0;
3430}
3431
Bryan Schumakerae42c702010-10-21 16:33:17 -04003432static int decode_attr_filehandle(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fh *fh)
3433{
3434 __be32 *p;
3435 int len;
3436
Trond Myklebust7ad07352010-10-23 15:34:20 -04003437 if (fh != NULL)
3438 memset(fh, 0, sizeof(*fh));
Bryan Schumakerae42c702010-10-21 16:33:17 -04003439
3440 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEHANDLE - 1U)))
3441 return -EIO;
3442 if (likely(bitmap[0] & FATTR4_WORD0_FILEHANDLE)) {
3443 p = xdr_inline_decode(xdr, 4);
3444 if (unlikely(!p))
3445 goto out_overflow;
3446 len = be32_to_cpup(p);
3447 if (len > NFS4_FHSIZE)
3448 return -EIO;
Bryan Schumakerae42c702010-10-21 16:33:17 -04003449 p = xdr_inline_decode(xdr, len);
3450 if (unlikely(!p))
3451 goto out_overflow;
Trond Myklebust7ad07352010-10-23 15:34:20 -04003452 if (fh != NULL) {
3453 memcpy(fh->data, p, len);
3454 fh->size = len;
3455 }
Bryan Schumakerae42c702010-10-21 16:33:17 -04003456 bitmap[0] &= ~FATTR4_WORD0_FILEHANDLE;
3457 }
3458 return 0;
3459out_overflow:
3460 print_overflow_msg(__func__, xdr);
3461 return -EIO;
3462}
3463
Linus Torvalds1da177e2005-04-16 15:20:36 -07003464static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3465{
Al Viro8687b632006-10-19 23:28:48 -07003466 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003467
Malahal Nainenia1800ac2014-01-27 15:31:09 -06003468 *res = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003469 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
3470 return -EIO;
3471 if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003472 p = xdr_inline_decode(xdr, 4);
3473 if (unlikely(!p))
3474 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003475 *res = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003476 bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
3477 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003478 dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03003480out_overflow:
3481 print_overflow_msg(__func__, xdr);
3482 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003483}
3484
3485static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
3486{
Al Viro8687b632006-10-19 23:28:48 -07003487 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003488 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489
3490 *fileid = 0;
3491 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
3492 return -EIO;
3493 if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003494 p = xdr_inline_decode(xdr, 8);
3495 if (unlikely(!p))
3496 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003497 xdr_decode_hyper(p, fileid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003498 bitmap[0] &= ~FATTR4_WORD0_FILEID;
Trond Myklebust409924e2009-03-11 14:10:27 -04003499 ret = NFS_ATTR_FATTR_FILEID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003500 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003501 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003502 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003503out_overflow:
3504 print_overflow_msg(__func__, xdr);
3505 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003506}
3507
Manoj Naik99baf622006-06-09 09:34:24 -04003508static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
3509{
Al Viro8687b632006-10-19 23:28:48 -07003510 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003511 int ret = 0;
Manoj Naik99baf622006-06-09 09:34:24 -04003512
3513 *fileid = 0;
3514 if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
3515 return -EIO;
3516 if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003517 p = xdr_inline_decode(xdr, 8);
3518 if (unlikely(!p))
3519 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003520 xdr_decode_hyper(p, fileid);
Manoj Naik99baf622006-06-09 09:34:24 -04003521 bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
Trond Myklebust28331a42011-04-27 13:47:52 -04003522 ret = NFS_ATTR_FATTR_MOUNTED_ON_FILEID;
Manoj Naik99baf622006-06-09 09:34:24 -04003523 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003524 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003525 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003526out_overflow:
3527 print_overflow_msg(__func__, xdr);
3528 return -EIO;
Manoj Naik99baf622006-06-09 09:34:24 -04003529}
3530
Linus Torvalds1da177e2005-04-16 15:20:36 -07003531static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3532{
Al Viro8687b632006-10-19 23:28:48 -07003533 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534 int status = 0;
3535
3536 *res = 0;
3537 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
3538 return -EIO;
3539 if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003540 p = xdr_inline_decode(xdr, 8);
3541 if (unlikely(!p))
3542 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003543 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
3545 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003546 dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003547 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003548out_overflow:
3549 print_overflow_msg(__func__, xdr);
3550 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003551}
3552
3553static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3554{
Al Viro8687b632006-10-19 23:28:48 -07003555 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556 int status = 0;
3557
3558 *res = 0;
3559 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
3560 return -EIO;
3561 if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003562 p = xdr_inline_decode(xdr, 8);
3563 if (unlikely(!p))
3564 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003565 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003566 bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
3567 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003568 dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003569 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003570out_overflow:
3571 print_overflow_msg(__func__, xdr);
3572 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003573}
3574
3575static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3576{
Al Viro8687b632006-10-19 23:28:48 -07003577 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003578 int status = 0;
3579
3580 *res = 0;
3581 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
3582 return -EIO;
3583 if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003584 p = xdr_inline_decode(xdr, 8);
3585 if (unlikely(!p))
3586 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003587 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003588 bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
3589 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003590 dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003592out_overflow:
3593 print_overflow_msg(__func__, xdr);
3594 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003595}
3596
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003597static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
3598{
Chuck Lever464ad6b2007-10-26 13:32:08 -04003599 u32 n;
Al Viro8687b632006-10-19 23:28:48 -07003600 __be32 *p;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003601 int status = 0;
3602
Benny Halevyc0eae662009-08-14 17:20:14 +03003603 p = xdr_inline_decode(xdr, 4);
3604 if (unlikely(!p))
3605 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003606 n = be32_to_cpup(p);
Andy Adamson33a43f22006-06-09 09:34:30 -04003607 if (n == 0)
3608 goto root_path;
Chuck Lever02a29762012-03-01 17:00:31 -05003609 dprintk("pathname4: ");
Trond Myklebust809b4262013-03-27 11:54:45 -04003610 if (n > NFS4_PATHNAME_MAXCOMPONENTS) {
3611 dprintk("cannot parse %d components in path\n", n);
3612 goto out_eio;
3613 }
3614 for (path->ncomponents = 0; path->ncomponents < n; path->ncomponents++) {
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003615 struct nfs4_string *component = &path->components[path->ncomponents];
3616 status = decode_opaque_inline(xdr, &component->len, &component->data);
3617 if (unlikely(status != 0))
3618 goto out_eio;
Trond Myklebust95a13f72012-03-14 21:55:01 -04003619 ifdebug (XDR)
Chuck Lever02a29762012-03-01 17:00:31 -05003620 pr_cont("%s%.*s ",
3621 (path->ncomponents != n ? "/ " : ""),
3622 component->len, component->data);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003623 }
3624out:
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003625 return status;
Andy Adamson33a43f22006-06-09 09:34:30 -04003626root_path:
3627/* a root pathname is sent as a zero component4 */
3628 path->ncomponents = 1;
3629 path->components[0].len=0;
3630 path->components[0].data=NULL;
Chuck Lever02a29762012-03-01 17:00:31 -05003631 dprintk("pathname4: /\n");
Andy Adamson33a43f22006-06-09 09:34:30 -04003632 goto out;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003633out_eio:
3634 dprintk(" status %d", status);
3635 status = -EIO;
3636 goto out;
Benny Halevyc0eae662009-08-14 17:20:14 +03003637out_overflow:
3638 print_overflow_msg(__func__, xdr);
3639 return -EIO;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003640}
3641
3642static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04003643{
3644 int n;
Al Viro8687b632006-10-19 23:28:48 -07003645 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003646 int status = -EIO;
3647
3648 if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
3649 goto out;
3650 status = 0;
3651 if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
3652 goto out;
Kinglong Meef54423a2015-11-18 10:39:26 +08003653 bitmap[0] &= ~FATTR4_WORD0_FS_LOCATIONS;
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05003654 status = -EIO;
3655 /* Ignore borken servers that return unrequested attrs */
3656 if (unlikely(res == NULL))
3657 goto out;
Chuck Lever02a29762012-03-01 17:00:31 -05003658 dprintk("%s: fsroot:\n", __func__);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003659 status = decode_pathname(xdr, &res->fs_path);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003660 if (unlikely(status != 0))
3661 goto out;
Benny Halevyc0eae662009-08-14 17:20:14 +03003662 p = xdr_inline_decode(xdr, 4);
3663 if (unlikely(!p))
3664 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003665 n = be32_to_cpup(p);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003666 if (n <= 0)
3667 goto out_eio;
Trond Myklebust809b4262013-03-27 11:54:45 -04003668 for (res->nlocations = 0; res->nlocations < n; res->nlocations++) {
Chuck Lever464ad6b2007-10-26 13:32:08 -04003669 u32 m;
Trond Myklebust809b4262013-03-27 11:54:45 -04003670 struct nfs4_fs_location *loc;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003671
Trond Myklebust809b4262013-03-27 11:54:45 -04003672 if (res->nlocations == NFS4_FS_LOCATIONS_MAXENTRIES)
3673 break;
3674 loc = &res->locations[res->nlocations];
Benny Halevyc0eae662009-08-14 17:20:14 +03003675 p = xdr_inline_decode(xdr, 4);
3676 if (unlikely(!p))
3677 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003678 m = be32_to_cpup(p);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003679
Chuck Lever02a29762012-03-01 17:00:31 -05003680 dprintk("%s: servers:\n", __func__);
Trond Myklebust809b4262013-03-27 11:54:45 -04003681 for (loc->nservers = 0; loc->nservers < m; loc->nservers++) {
3682 struct nfs4_string *server;
3683
3684 if (loc->nservers == NFS4_FS_LOCATION_MAXSERVERS) {
Chuck Lever464ad6b2007-10-26 13:32:08 -04003685 unsigned int i;
3686 dprintk("%s: using first %u of %u servers "
3687 "returned for location %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003688 __func__,
Chuck Lever464ad6b2007-10-26 13:32:08 -04003689 NFS4_FS_LOCATION_MAXSERVERS,
3690 m, res->nlocations);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003691 for (i = loc->nservers; i < m; i++) {
Trond Myklebust2e42c3e2007-05-14 17:20:41 -04003692 unsigned int len;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003693 char *data;
3694 status = decode_opaque_inline(xdr, &len, &data);
3695 if (unlikely(status != 0))
3696 goto out_eio;
3697 }
Trond Myklebust809b4262013-03-27 11:54:45 -04003698 break;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003699 }
Trond Myklebust809b4262013-03-27 11:54:45 -04003700 server = &loc->servers[loc->nservers];
3701 status = decode_opaque_inline(xdr, &server->len, &server->data);
3702 if (unlikely(status != 0))
3703 goto out_eio;
3704 dprintk("%s ", server->data);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003705 }
3706 status = decode_pathname(xdr, &loc->rootpath);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003707 if (unlikely(status != 0))
3708 goto out_eio;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003709 }
Trond Myklebust409924e2009-03-11 14:10:27 -04003710 if (res->nlocations != 0)
Chuck Lever81934dd2012-03-01 17:01:57 -05003711 status = NFS_ATTR_FATTR_V4_LOCATIONS;
Trond Myklebust683b57b2006-06-09 09:34:22 -04003712out:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003713 dprintk("%s: fs_locations done, error = %d\n", __func__, status);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003714 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003715out_overflow:
3716 print_overflow_msg(__func__, xdr);
Trond Myklebust683b57b2006-06-09 09:34:22 -04003717out_eio:
3718 status = -EIO;
3719 goto out;
3720}
3721
Linus Torvalds1da177e2005-04-16 15:20:36 -07003722static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3723{
Al Viro8687b632006-10-19 23:28:48 -07003724 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003725 int status = 0;
3726
3727 *res = 0;
3728 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
3729 return -EIO;
3730 if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003731 p = xdr_inline_decode(xdr, 8);
3732 if (unlikely(!p))
3733 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003734 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003735 bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
3736 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003737 dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003739out_overflow:
3740 print_overflow_msg(__func__, xdr);
3741 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003742}
3743
3744static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
3745{
Al Viro8687b632006-10-19 23:28:48 -07003746 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 int status = 0;
3748
3749 *maxlink = 1;
3750 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
3751 return -EIO;
3752 if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003753 p = xdr_inline_decode(xdr, 4);
3754 if (unlikely(!p))
3755 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003756 *maxlink = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757 bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
3758 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003759 dprintk("%s: maxlink=%u\n", __func__, *maxlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003760 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003761out_overflow:
3762 print_overflow_msg(__func__, xdr);
3763 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003764}
3765
3766static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
3767{
Al Viro8687b632006-10-19 23:28:48 -07003768 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003769 int status = 0;
3770
3771 *maxname = 1024;
3772 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
3773 return -EIO;
3774 if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003775 p = xdr_inline_decode(xdr, 4);
3776 if (unlikely(!p))
3777 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003778 *maxname = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003779 bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
3780 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003781 dprintk("%s: maxname=%u\n", __func__, *maxname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003782 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003783out_overflow:
3784 print_overflow_msg(__func__, xdr);
3785 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003786}
3787
3788static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3789{
Al Viro8687b632006-10-19 23:28:48 -07003790 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003791 int status = 0;
3792
3793 *res = 1024;
3794 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
3795 return -EIO;
3796 if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
3797 uint64_t maxread;
Benny Halevyc0eae662009-08-14 17:20:14 +03003798 p = xdr_inline_decode(xdr, 8);
3799 if (unlikely(!p))
3800 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003801 xdr_decode_hyper(p, &maxread);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003802 if (maxread > 0x7FFFFFFF)
3803 maxread = 0x7FFFFFFF;
3804 *res = (uint32_t)maxread;
3805 bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
3806 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003807 dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003808 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003809out_overflow:
3810 print_overflow_msg(__func__, xdr);
3811 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003812}
3813
3814static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
3815{
Al Viro8687b632006-10-19 23:28:48 -07003816 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003817 int status = 0;
3818
3819 *res = 1024;
3820 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
3821 return -EIO;
3822 if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
3823 uint64_t maxwrite;
Benny Halevyc0eae662009-08-14 17:20:14 +03003824 p = xdr_inline_decode(xdr, 8);
3825 if (unlikely(!p))
3826 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003827 xdr_decode_hyper(p, &maxwrite);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003828 if (maxwrite > 0x7FFFFFFF)
3829 maxwrite = 0x7FFFFFFF;
3830 *res = (uint32_t)maxwrite;
3831 bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
3832 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003833 dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003834 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03003835out_overflow:
3836 print_overflow_msg(__func__, xdr);
3837 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003838}
3839
Trond Myklebustbca79472009-03-11 14:10:26 -04003840static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003841{
Trond Myklebustbca79472009-03-11 14:10:26 -04003842 uint32_t tmp;
Al Viro8687b632006-10-19 23:28:48 -07003843 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003844 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003845
3846 *mode = 0;
3847 if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
3848 return -EIO;
3849 if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003850 p = xdr_inline_decode(xdr, 4);
3851 if (unlikely(!p))
3852 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003853 tmp = be32_to_cpup(p);
Trond Myklebustbca79472009-03-11 14:10:26 -04003854 *mode = tmp & ~S_IFMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003855 bitmap[1] &= ~FATTR4_WORD1_MODE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003856 ret = NFS_ATTR_FATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003857 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003858 dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
Trond Myklebust409924e2009-03-11 14:10:27 -04003859 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003860out_overflow:
3861 print_overflow_msg(__func__, xdr);
3862 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003863}
3864
3865static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
3866{
Al Viro8687b632006-10-19 23:28:48 -07003867 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003868 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003869
3870 *nlink = 1;
3871 if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
3872 return -EIO;
3873 if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003874 p = xdr_inline_decode(xdr, 4);
3875 if (unlikely(!p))
3876 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003877 *nlink = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003878 bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
Trond Myklebust409924e2009-03-11 14:10:27 -04003879 ret = NFS_ATTR_FATTR_NLINK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003880 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003881 dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
Trond Myklebust409924e2009-03-11 14:10:27 -04003882 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003883out_overflow:
3884 print_overflow_msg(__func__, xdr);
3885 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003886}
3887
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003888static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap,
Eric W. Biedermane5782072013-02-01 14:22:02 -08003889 const struct nfs_server *server, kuid_t *uid,
Trond Myklebust6926afd2012-01-07 13:22:46 -05003890 struct nfs4_string *owner_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003891{
Al Viro8687b632006-10-19 23:28:48 -07003892 uint32_t len;
3893 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003894 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003895
Eric W. Biedermane5782072013-02-01 14:22:02 -08003896 *uid = make_kuid(&init_user_ns, -2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003897 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
3898 return -EIO;
3899 if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003900 p = xdr_inline_decode(xdr, 4);
3901 if (unlikely(!p))
3902 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003903 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003904 p = xdr_inline_decode(xdr, len);
3905 if (unlikely(!p))
3906 goto out_overflow;
Trond Myklebust6926afd2012-01-07 13:22:46 -05003907 if (owner_name != NULL) {
3908 owner_name->data = kmemdup(p, len, GFP_NOWAIT);
3909 if (owner_name->data != NULL) {
3910 owner_name->len = len;
3911 ret = NFS_ATTR_FATTR_OWNER_NAME;
3912 }
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003913 } else if (len < XDR_MAX_NETOBJ) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08003914 if (nfs_map_name_to_uid(server, (char *)p, len, uid) == 0)
Trond Myklebust409924e2009-03-11 14:10:27 -04003915 ret = NFS_ATTR_FATTR_OWNER;
3916 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003917 dprintk("%s: nfs_map_name_to_uid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003918 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003919 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003920 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003921 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003922 bitmap[1] &= ~FATTR4_WORD1_OWNER;
3923 }
Eric W. Biedermane5782072013-02-01 14:22:02 -08003924 dprintk("%s: uid=%d\n", __func__, (int)from_kuid(&init_user_ns, *uid));
Trond Myklebust409924e2009-03-11 14:10:27 -04003925 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003926out_overflow:
3927 print_overflow_msg(__func__, xdr);
3928 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003929}
3930
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003931static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap,
Eric W. Biedermane5782072013-02-01 14:22:02 -08003932 const struct nfs_server *server, kgid_t *gid,
Trond Myklebust6926afd2012-01-07 13:22:46 -05003933 struct nfs4_string *group_name)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003934{
Al Viro8687b632006-10-19 23:28:48 -07003935 uint32_t len;
3936 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003937 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003938
Eric W. Biedermane5782072013-02-01 14:22:02 -08003939 *gid = make_kgid(&init_user_ns, -2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003940 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
3941 return -EIO;
3942 if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03003943 p = xdr_inline_decode(xdr, 4);
3944 if (unlikely(!p))
3945 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03003946 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03003947 p = xdr_inline_decode(xdr, len);
3948 if (unlikely(!p))
3949 goto out_overflow;
Trond Myklebust6926afd2012-01-07 13:22:46 -05003950 if (group_name != NULL) {
3951 group_name->data = kmemdup(p, len, GFP_NOWAIT);
3952 if (group_name->data != NULL) {
3953 group_name->len = len;
3954 ret = NFS_ATTR_FATTR_GROUP_NAME;
3955 }
Trond Myklebust80e52ac2009-08-09 15:06:19 -04003956 } else if (len < XDR_MAX_NETOBJ) {
Trond Myklebuste4fd72a2011-02-22 15:44:31 -08003957 if (nfs_map_group_to_gid(server, (char *)p, len, gid) == 0)
Trond Myklebust409924e2009-03-11 14:10:27 -04003958 ret = NFS_ATTR_FATTR_GROUP;
3959 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003960 dprintk("%s: nfs_map_group_to_gid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003961 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003962 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003963 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003964 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003965 bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
3966 }
Eric W. Biedermane5782072013-02-01 14:22:02 -08003967 dprintk("%s: gid=%d\n", __func__, (int)from_kgid(&init_user_ns, *gid));
Trond Myklebust409924e2009-03-11 14:10:27 -04003968 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003969out_overflow:
3970 print_overflow_msg(__func__, xdr);
3971 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003972}
3973
3974static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
3975{
Al Viro8687b632006-10-19 23:28:48 -07003976 uint32_t major = 0, minor = 0;
3977 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003978 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003979
3980 *rdev = MKDEV(0,0);
3981 if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
3982 return -EIO;
3983 if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
3984 dev_t tmp;
3985
Benny Halevyc0eae662009-08-14 17:20:14 +03003986 p = xdr_inline_decode(xdr, 8);
3987 if (unlikely(!p))
3988 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03003989 major = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03003990 minor = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003991 tmp = MKDEV(major, minor);
3992 if (MAJOR(tmp) == major && MINOR(tmp) == minor)
3993 *rdev = tmp;
3994 bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
Trond Myklebust409924e2009-03-11 14:10:27 -04003995 ret = NFS_ATTR_FATTR_RDEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003996 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003997 dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04003998 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03003999out_overflow:
4000 print_overflow_msg(__func__, xdr);
4001 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004002}
4003
4004static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
4005{
Al Viro8687b632006-10-19 23:28:48 -07004006 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004007 int status = 0;
4008
4009 *res = 0;
4010 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
4011 return -EIO;
4012 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004013 p = xdr_inline_decode(xdr, 8);
4014 if (unlikely(!p))
4015 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004016 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004017 bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
4018 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004019 dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004020 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004021out_overflow:
4022 print_overflow_msg(__func__, xdr);
4023 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004024}
4025
4026static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
4027{
Al Viro8687b632006-10-19 23:28:48 -07004028 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004029 int status = 0;
4030
4031 *res = 0;
4032 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
4033 return -EIO;
4034 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004035 p = xdr_inline_decode(xdr, 8);
4036 if (unlikely(!p))
4037 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004038 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004039 bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
4040 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004041 dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004042 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004043out_overflow:
4044 print_overflow_msg(__func__, xdr);
4045 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004046}
4047
4048static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
4049{
Al Viro8687b632006-10-19 23:28:48 -07004050 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004051 int status = 0;
4052
4053 *res = 0;
4054 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
4055 return -EIO;
4056 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004057 p = xdr_inline_decode(xdr, 8);
4058 if (unlikely(!p))
4059 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004060 xdr_decode_hyper(p, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004061 bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
4062 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004063 dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004064 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004065out_overflow:
4066 print_overflow_msg(__func__, xdr);
4067 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004068}
4069
4070static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
4071{
Al Viro8687b632006-10-19 23:28:48 -07004072 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04004073 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004074
4075 *used = 0;
4076 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
4077 return -EIO;
4078 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
Benny Halevyc0eae662009-08-14 17:20:14 +03004079 p = xdr_inline_decode(xdr, 8);
4080 if (unlikely(!p))
4081 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004082 xdr_decode_hyper(p, used);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
Trond Myklebust409924e2009-03-11 14:10:27 -04004084 ret = NFS_ATTR_FATTR_SPACE_USED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004085 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004086 dprintk("%s: space used=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004087 (unsigned long long)*used);
Trond Myklebust409924e2009-03-11 14:10:27 -04004088 return ret;
Benny Halevyc0eae662009-08-14 17:20:14 +03004089out_overflow:
4090 print_overflow_msg(__func__, xdr);
4091 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004092}
4093
4094static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
4095{
Al Viro8687b632006-10-19 23:28:48 -07004096 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004097 uint64_t sec;
4098 uint32_t nsec;
4099
Benny Halevyc0eae662009-08-14 17:20:14 +03004100 p = xdr_inline_decode(xdr, 12);
4101 if (unlikely(!p))
4102 goto out_overflow;
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004103 p = xdr_decode_hyper(p, &sec);
Benny Halevycccddf42009-08-14 17:20:19 +03004104 nsec = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004105 time->tv_sec = (time_t)sec;
4106 time->tv_nsec = (long)nsec;
4107 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004108out_overflow:
4109 print_overflow_msg(__func__, xdr);
4110 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004111}
4112
4113static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4114{
4115 int status = 0;
4116
4117 time->tv_sec = 0;
4118 time->tv_nsec = 0;
4119 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
4120 return -EIO;
4121 if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
4122 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004123 if (status == 0)
4124 status = NFS_ATTR_FATTR_ATIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125 bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
4126 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004127 dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004128 return status;
4129}
4130
4131static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4132{
4133 int status = 0;
4134
4135 time->tv_sec = 0;
4136 time->tv_nsec = 0;
4137 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
4138 return -EIO;
4139 if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
4140 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004141 if (status == 0)
4142 status = NFS_ATTR_FATTR_CTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004143 bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
4144 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004145 dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004146 return status;
4147}
4148
Ricardo Labiaga55b6e772010-10-12 16:30:06 -07004149static int decode_attr_time_delta(struct xdr_stream *xdr, uint32_t *bitmap,
4150 struct timespec *time)
4151{
4152 int status = 0;
4153
4154 time->tv_sec = 0;
4155 time->tv_nsec = 0;
4156 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_DELTA - 1U)))
4157 return -EIO;
4158 if (likely(bitmap[1] & FATTR4_WORD1_TIME_DELTA)) {
4159 status = decode_attr_time(xdr, time);
4160 bitmap[1] &= ~FATTR4_WORD1_TIME_DELTA;
4161 }
4162 dprintk("%s: time_delta=%ld %ld\n", __func__, (long)time->tv_sec,
4163 (long)time->tv_nsec);
4164 return status;
4165}
4166
David Quigleyaa9c2662013-05-22 12:50:44 -04004167static int decode_attr_security_label(struct xdr_stream *xdr, uint32_t *bitmap,
4168 struct nfs4_label *label)
4169{
4170 uint32_t pi = 0;
4171 uint32_t lfs = 0;
4172 __u32 len;
4173 __be32 *p;
4174 int status = 0;
4175
4176 if (unlikely(bitmap[2] & (FATTR4_WORD2_SECURITY_LABEL - 1U)))
4177 return -EIO;
4178 if (likely(bitmap[2] & FATTR4_WORD2_SECURITY_LABEL)) {
4179 p = xdr_inline_decode(xdr, 4);
4180 if (unlikely(!p))
4181 goto out_overflow;
4182 lfs = be32_to_cpup(p++);
4183 p = xdr_inline_decode(xdr, 4);
4184 if (unlikely(!p))
4185 goto out_overflow;
4186 pi = be32_to_cpup(p++);
4187 p = xdr_inline_decode(xdr, 4);
4188 if (unlikely(!p))
4189 goto out_overflow;
4190 len = be32_to_cpup(p++);
4191 p = xdr_inline_decode(xdr, len);
4192 if (unlikely(!p))
4193 goto out_overflow;
4194 if (len < NFS4_MAXLABELLEN) {
4195 if (label) {
4196 memcpy(label->label, p, len);
4197 label->len = len;
4198 label->pi = pi;
4199 label->lfs = lfs;
4200 status = NFS_ATTR_FATTR_V4_SECURITY_LABEL;
4201 }
4202 bitmap[2] &= ~FATTR4_WORD2_SECURITY_LABEL;
4203 } else
4204 printk(KERN_WARNING "%s: label too long (%u)!\n",
4205 __func__, len);
4206 }
4207 if (label && label->label)
4208 dprintk("%s: label=%s, len=%d, PI=%d, LFS=%d\n", __func__,
4209 (char *)label->label, label->len, label->pi, label->lfs);
4210 return status;
4211
4212out_overflow:
4213 print_overflow_msg(__func__, xdr);
4214 return -EIO;
4215}
4216
Linus Torvalds1da177e2005-04-16 15:20:36 -07004217static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
4218{
4219 int status = 0;
4220
4221 time->tv_sec = 0;
4222 time->tv_nsec = 0;
4223 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
4224 return -EIO;
4225 if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
4226 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04004227 if (status == 0)
4228 status = NFS_ATTR_FATTR_MTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004229 bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
4230 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07004231 dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004232 return status;
4233}
4234
Trond Myklebust256e48b2012-06-21 11:18:13 -04004235static int verify_attr_len(struct xdr_stream *xdr, unsigned int savep, uint32_t attrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004236{
4237 unsigned int attrwords = XDR_QUADLEN(attrlen);
Trond Myklebust256e48b2012-06-21 11:18:13 -04004238 unsigned int nwords = (xdr_stream_pos(xdr) - savep) >> 2;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004239
4240 if (unlikely(attrwords != nwords)) {
Chuck Leverfe82a182007-09-11 18:01:10 -04004241 dprintk("%s: server returned incorrect attribute length: "
4242 "%u %c %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07004243 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07004244 attrwords << 2,
4245 (attrwords < nwords) ? '<' : '>',
4246 nwords << 2);
4247 return -EIO;
4248 }
4249 return 0;
4250}
4251
4252static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4253{
Al Viro8687b632006-10-19 23:28:48 -07004254 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004255
Benny Halevyc0eae662009-08-14 17:20:14 +03004256 p = xdr_inline_decode(xdr, 20);
4257 if (unlikely(!p))
4258 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03004259 cinfo->atomic = be32_to_cpup(p++);
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004260 p = xdr_decode_hyper(p, &cinfo->before);
Benny Halevycccddf42009-08-14 17:20:19 +03004261 xdr_decode_hyper(p, &cinfo->after);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004262 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004263out_overflow:
4264 print_overflow_msg(__func__, xdr);
4265 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004266}
4267
Weston Andros Adamson6168f622012-09-10 14:00:46 -04004268static int decode_access(struct xdr_stream *xdr, u32 *supported, u32 *access)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004269{
Al Viro8687b632006-10-19 23:28:48 -07004270 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004271 uint32_t supp, acc;
4272 int status;
4273
4274 status = decode_op_hdr(xdr, OP_ACCESS);
4275 if (status)
4276 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004277 p = xdr_inline_decode(xdr, 8);
4278 if (unlikely(!p))
4279 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03004280 supp = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03004281 acc = be32_to_cpup(p);
Weston Andros Adamson6168f622012-09-10 14:00:46 -04004282 *supported = supp;
4283 *access = acc;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004284 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004285out_overflow:
4286 print_overflow_msg(__func__, xdr);
4287 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004288}
4289
Benny Halevy07d30432009-08-14 17:19:52 +03004290static int decode_opaque_fixed(struct xdr_stream *xdr, void *buf, size_t len)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004291{
Al Viro8687b632006-10-19 23:28:48 -07004292 __be32 *p;
Benny Halevy07d30432009-08-14 17:19:52 +03004293
4294 p = xdr_inline_decode(xdr, len);
4295 if (likely(p)) {
4296 memcpy(buf, p, len);
4297 return 0;
4298 }
4299 print_overflow_msg(__func__, xdr);
4300 return -EIO;
4301}
4302
4303static int decode_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4304{
Trond Myklebust2d2f24a2012-03-04 18:13:57 -05004305 return decode_opaque_fixed(xdr, stateid, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004306}
4307
Trond Myklebust93b717f2016-05-16 17:42:43 -04004308static int decode_open_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4309{
4310 stateid->type = NFS4_OPEN_STATEID_TYPE;
4311 return decode_stateid(xdr, stateid);
4312}
4313
4314static int decode_lock_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4315{
4316 stateid->type = NFS4_LOCK_STATEID_TYPE;
4317 return decode_stateid(xdr, stateid);
4318}
4319
4320static int decode_delegation_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
4321{
4322 stateid->type = NFS4_DELEGATION_STATEID_TYPE;
4323 return decode_stateid(xdr, stateid);
4324}
4325
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
4327{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004328 int status;
4329
4330 status = decode_op_hdr(xdr, OP_CLOSE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04004331 if (status != -EIO)
4332 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03004333 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04004334 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03004335 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004336}
4337
Benny Halevydb942bb2009-08-14 17:19:56 +03004338static int decode_verifier(struct xdr_stream *xdr, void *verifier)
4339{
Chuck Levercd937102012-03-02 17:14:31 -05004340 return decode_opaque_fixed(xdr, verifier, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004341}
4342
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04004343static int decode_write_verifier(struct xdr_stream *xdr, struct nfs_write_verifier *verifier)
4344{
4345 return decode_opaque_fixed(xdr, verifier->data, NFS4_VERIFIER_SIZE);
4346}
4347
Fred Isaman0b7c0152012-04-20 14:47:39 -04004348static int decode_commit(struct xdr_stream *xdr, struct nfs_commitres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004349{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 int status;
4351
4352 status = decode_op_hdr(xdr, OP_COMMIT);
Benny Halevydb942bb2009-08-14 17:19:56 +03004353 if (!status)
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04004354 status = decode_write_verifier(xdr, &res->verf->verifier);
Benny Halevydb942bb2009-08-14 17:19:56 +03004355 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004356}
4357
4358static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4359{
Al Viro8687b632006-10-19 23:28:48 -07004360 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004361 uint32_t bmlen;
4362 int status;
4363
4364 status = decode_op_hdr(xdr, OP_CREATE);
4365 if (status)
4366 return status;
4367 if ((status = decode_change_info(xdr, cinfo)))
4368 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03004369 p = xdr_inline_decode(xdr, 4);
4370 if (unlikely(!p))
4371 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004372 bmlen = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03004373 p = xdr_inline_decode(xdr, bmlen << 2);
4374 if (likely(p))
4375 return 0;
4376out_overflow:
4377 print_overflow_msg(__func__, xdr);
4378 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004379}
4380
4381static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
4382{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004383 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004384 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 int status;
4386
4387 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4388 goto xdr_error;
4389 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4390 goto xdr_error;
4391 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4392 goto xdr_error;
4393 if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
4394 goto xdr_error;
Chuck Lever264e6352012-03-01 17:02:05 -05004395 if ((status = decode_attr_fh_expire_type(xdr, bitmap,
4396 &res->fh_expire_type)) != 0)
4397 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004398 if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
4399 goto xdr_error;
4400 if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
4401 goto xdr_error;
4402 if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
4403 goto xdr_error;
Kinglong Mee8c612822015-08-26 21:12:58 +08004404 if ((status = decode_attr_exclcreat_supported(xdr, bitmap,
4405 res->exclcreat_bitmask)) != 0)
4406 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407 status = verify_attr_len(xdr, savep, attrlen);
4408xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004409 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004410 return status;
4411}
Andy Adamson6c0195a2008-12-23 16:06:15 -05004412
Linus Torvalds1da177e2005-04-16 15:20:36 -07004413static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
4414{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004415 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004416 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004417 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004418
Linus Torvalds1da177e2005-04-16 15:20:36 -07004419 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4420 goto xdr_error;
4421 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4422 goto xdr_error;
4423 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4424 goto xdr_error;
4425
4426 if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
4427 goto xdr_error;
4428 if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
4429 goto xdr_error;
4430 if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
4431 goto xdr_error;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004432
4433 status = -EIO;
4434 if (unlikely(bitmap[0]))
4435 goto xdr_error;
4436
Linus Torvalds1da177e2005-04-16 15:20:36 -07004437 if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
4438 goto xdr_error;
4439 if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
4440 goto xdr_error;
4441 if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
4442 goto xdr_error;
4443
4444 status = verify_attr_len(xdr, savep, attrlen);
4445xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004446 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004447 return status;
4448}
4449
4450static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
4451{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004452 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004453 uint32_t attrlen, bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07004454 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004455
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4457 goto xdr_error;
4458 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4459 goto xdr_error;
4460 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4461 goto xdr_error;
4462
4463 if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
4464 goto xdr_error;
4465 if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
4466 goto xdr_error;
4467
4468 status = verify_attr_len(xdr, savep, attrlen);
4469xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004470 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004471 return status;
4472}
4473
Andy Adamson88034c32012-05-23 05:02:34 -04004474static int decode_threshold_hint(struct xdr_stream *xdr,
4475 uint32_t *bitmap,
4476 uint64_t *res,
4477 uint32_t hint_bit)
4478{
4479 __be32 *p;
4480
4481 *res = 0;
4482 if (likely(bitmap[0] & hint_bit)) {
4483 p = xdr_inline_decode(xdr, 8);
4484 if (unlikely(!p))
4485 goto out_overflow;
4486 xdr_decode_hyper(p, res);
4487 }
4488 return 0;
4489out_overflow:
4490 print_overflow_msg(__func__, xdr);
4491 return -EIO;
4492}
4493
4494static int decode_first_threshold_item4(struct xdr_stream *xdr,
4495 struct nfs4_threshold *res)
4496{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004497 __be32 *p;
4498 unsigned int savep;
Andy Adamson88034c32012-05-23 05:02:34 -04004499 uint32_t bitmap[3] = {0,}, attrlen;
4500 int status;
4501
4502 /* layout type */
4503 p = xdr_inline_decode(xdr, 4);
4504 if (unlikely(!p)) {
4505 print_overflow_msg(__func__, xdr);
4506 return -EIO;
4507 }
4508 res->l_type = be32_to_cpup(p);
4509
4510 /* thi_hintset bitmap */
4511 status = decode_attr_bitmap(xdr, bitmap);
4512 if (status < 0)
4513 goto xdr_error;
4514
4515 /* thi_hintlist length */
4516 status = decode_attr_length(xdr, &attrlen, &savep);
4517 if (status < 0)
4518 goto xdr_error;
4519 /* thi_hintlist */
4520 status = decode_threshold_hint(xdr, bitmap, &res->rd_sz, THRESHOLD_RD);
4521 if (status < 0)
4522 goto xdr_error;
4523 status = decode_threshold_hint(xdr, bitmap, &res->wr_sz, THRESHOLD_WR);
4524 if (status < 0)
4525 goto xdr_error;
4526 status = decode_threshold_hint(xdr, bitmap, &res->rd_io_sz,
4527 THRESHOLD_RD_IO);
4528 if (status < 0)
4529 goto xdr_error;
4530 status = decode_threshold_hint(xdr, bitmap, &res->wr_io_sz,
4531 THRESHOLD_WR_IO);
4532 if (status < 0)
4533 goto xdr_error;
4534
4535 status = verify_attr_len(xdr, savep, attrlen);
4536 res->bm = bitmap[0];
4537
4538 dprintk("%s bm=0x%x rd_sz=%llu wr_sz=%llu rd_io=%llu wr_io=%llu\n",
4539 __func__, res->bm, res->rd_sz, res->wr_sz, res->rd_io_sz,
4540 res->wr_io_sz);
4541xdr_error:
4542 dprintk("%s ret=%d!\n", __func__, status);
4543 return status;
4544}
4545
4546/*
4547 * Thresholds on pNFS direct I/O vrs MDS I/O
4548 */
4549static int decode_attr_mdsthreshold(struct xdr_stream *xdr,
4550 uint32_t *bitmap,
4551 struct nfs4_threshold *res)
4552{
4553 __be32 *p;
4554 int status = 0;
4555 uint32_t num;
4556
4557 if (unlikely(bitmap[2] & (FATTR4_WORD2_MDSTHRESHOLD - 1U)))
4558 return -EIO;
Trond Myklebust029c5342012-06-05 09:35:44 -04004559 if (bitmap[2] & FATTR4_WORD2_MDSTHRESHOLD) {
Trond Myklebust1549210f2012-06-05 09:16:47 -04004560 /* Did the server return an unrequested attribute? */
4561 if (unlikely(res == NULL))
4562 return -EREMOTEIO;
Andy Adamson88034c32012-05-23 05:02:34 -04004563 p = xdr_inline_decode(xdr, 4);
4564 if (unlikely(!p))
4565 goto out_overflow;
4566 num = be32_to_cpup(p);
4567 if (num == 0)
4568 return 0;
4569 if (num > 1)
4570 printk(KERN_INFO "%s: Warning: Multiple pNFS layout "
4571 "drivers per filesystem not supported\n",
4572 __func__);
4573
4574 status = decode_first_threshold_item4(xdr, res);
Trond Myklebust029c5342012-06-05 09:35:44 -04004575 bitmap[2] &= ~FATTR4_WORD2_MDSTHRESHOLD;
Andy Adamson88034c32012-05-23 05:02:34 -04004576 }
4577 return status;
4578out_overflow:
4579 print_overflow_msg(__func__, xdr);
4580 return -EIO;
4581}
4582
Bryan Schumakerae42c702010-10-21 16:33:17 -04004583static int decode_getfattr_attrs(struct xdr_stream *xdr, uint32_t *bitmap,
4584 struct nfs_fattr *fattr, struct nfs_fh *fh,
David Quigleyaa9c2662013-05-22 12:50:44 -04004585 struct nfs4_fs_locations *fs_loc, struct nfs4_label *label,
Trond Myklebust6926afd2012-01-07 13:22:46 -05004586 const struct nfs_server *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004587{
Trond Myklebustbca79472009-03-11 14:10:26 -04004588 int status;
4589 umode_t fmode = 0;
Bryan Schumakerae42c702010-10-21 16:33:17 -04004590 uint32_t type;
Trond Myklebustee7b75f2011-06-16 13:15:41 -04004591 int32_t err;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004592
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004593 status = decode_attr_type(xdr, bitmap, &type);
4594 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004595 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004596 fattr->mode = 0;
4597 if (status != 0) {
4598 fattr->mode |= nfs_type2fmt[type];
4599 fattr->valid |= status;
4600 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004601
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004602 status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
4603 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004604 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004605 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004606
4607 status = decode_attr_size(xdr, bitmap, &fattr->size);
4608 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004609 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004610 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004611
4612 status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
4613 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004614 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004615 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004616
Trond Myklebustee7b75f2011-06-16 13:15:41 -04004617 err = 0;
4618 status = decode_attr_error(xdr, bitmap, &err);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004619 if (status < 0)
4620 goto xdr_error;
4621
4622 status = decode_attr_filehandle(xdr, bitmap, fh);
4623 if (status < 0)
4624 goto xdr_error;
4625
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004626 status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
4627 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004628 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004629 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004630
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05004631 status = decode_attr_fs_locations(xdr, bitmap, fs_loc);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004632 if (status < 0)
Trond Myklebust683b57b2006-06-09 09:34:22 -04004633 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004634 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004635
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004636 status = -EIO;
4637 if (unlikely(bitmap[0]))
4638 goto xdr_error;
4639
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004640 status = decode_attr_mode(xdr, bitmap, &fmode);
4641 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004642 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004643 if (status != 0) {
4644 fattr->mode |= fmode;
4645 fattr->valid |= status;
4646 }
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004647
4648 status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
4649 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004650 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004651 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004652
Trond Myklebust6926afd2012-01-07 13:22:46 -05004653 status = decode_attr_owner(xdr, bitmap, server, &fattr->uid, fattr->owner_name);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004654 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004655 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004656 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004657
Trond Myklebust6926afd2012-01-07 13:22:46 -05004658 status = decode_attr_group(xdr, bitmap, server, &fattr->gid, fattr->group_name);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004659 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004660 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004661 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004662
4663 status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
4664 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004665 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004666 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004667
4668 status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
4669 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004671 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004672
4673 status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
4674 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004675 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004676 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004677
4678 status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
4679 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004680 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004681 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004682
4683 status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
4684 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004685 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04004686 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004687
Trond Myklebust28331a42011-04-27 13:47:52 -04004688 status = decode_attr_mounted_on_fileid(xdr, bitmap, &fattr->mounted_on_fileid);
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004689 if (status < 0)
Manoj Naik99baf622006-06-09 09:34:24 -04004690 goto xdr_error;
Trond Myklebust28331a42011-04-27 13:47:52 -04004691 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004692
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004693 status = -EIO;
4694 if (unlikely(bitmap[1]))
4695 goto xdr_error;
4696
Andy Adamson88034c32012-05-23 05:02:34 -04004697 status = decode_attr_mdsthreshold(xdr, bitmap, fattr->mdsthreshold);
4698 if (status < 0)
4699 goto xdr_error;
4700
David Quigleyaa9c2662013-05-22 12:50:44 -04004701 if (label) {
4702 status = decode_attr_security_label(xdr, bitmap, label);
4703 if (status < 0)
4704 goto xdr_error;
4705 fattr->valid |= status;
4706 }
4707
Bryan Schumakerae42c702010-10-21 16:33:17 -04004708xdr_error:
4709 dprintk("%s: xdr returned %d\n", __func__, -status);
4710 return status;
4711}
4712
4713static int decode_getfattr_generic(struct xdr_stream *xdr, struct nfs_fattr *fattr,
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05004714 struct nfs_fh *fh, struct nfs4_fs_locations *fs_loc,
David Quigleyaa9c2662013-05-22 12:50:44 -04004715 struct nfs4_label *label, const struct nfs_server *server)
Bryan Schumakerae42c702010-10-21 16:33:17 -04004716{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004717 unsigned int savep;
Bryan Schumakerae42c702010-10-21 16:33:17 -04004718 uint32_t attrlen,
Fred Isamandae100c2011-07-30 20:52:37 -04004719 bitmap[3] = {0};
Bryan Schumakerae42c702010-10-21 16:33:17 -04004720 int status;
4721
4722 status = decode_op_hdr(xdr, OP_GETATTR);
4723 if (status < 0)
4724 goto xdr_error;
4725
4726 status = decode_attr_bitmap(xdr, bitmap);
4727 if (status < 0)
4728 goto xdr_error;
4729
4730 status = decode_attr_length(xdr, &attrlen, &savep);
4731 if (status < 0)
4732 goto xdr_error;
4733
David Quigleyaa9c2662013-05-22 12:50:44 -04004734 status = decode_getfattr_attrs(xdr, bitmap, fattr, fh, fs_loc,
4735 label, server);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004736 if (status < 0)
4737 goto xdr_error;
4738
Trond Myklebustf26c7a72009-03-11 14:10:26 -04004739 status = verify_attr_len(xdr, savep, attrlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004740xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004741 dprintk("%s: xdr returned %d\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004742 return status;
4743}
4744
David Quigleyaa9c2662013-05-22 12:50:44 -04004745static int decode_getfattr_label(struct xdr_stream *xdr, struct nfs_fattr *fattr,
4746 struct nfs4_label *label, const struct nfs_server *server)
4747{
4748 return decode_getfattr_generic(xdr, fattr, NULL, NULL, label, server);
4749}
4750
Bryan Schumakerae42c702010-10-21 16:33:17 -04004751static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr,
Trond Myklebust6926afd2012-01-07 13:22:46 -05004752 const struct nfs_server *server)
Bryan Schumakerae42c702010-10-21 16:33:17 -04004753{
David Quigleyaa9c2662013-05-22 12:50:44 -04004754 return decode_getfattr_generic(xdr, fattr, NULL, NULL, NULL, server);
Bryan Schumakerae42c702010-10-21 16:33:17 -04004755}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756
Andy Adamson504913f2010-10-20 00:17:57 -04004757/*
Jeff Layton3132e492016-08-10 15:58:24 -04004758 * Decode potentially multiple layout types.
Andy Adamson504913f2010-10-20 00:17:57 -04004759 */
Jeff Layton3132e492016-08-10 15:58:24 -04004760static int decode_pnfs_layout_types(struct xdr_stream *xdr,
Jeff Laytonca440c32016-09-15 14:40:49 -04004761 struct nfs_fsinfo *fsinfo)
Andy Adamson504913f2010-10-20 00:17:57 -04004762{
Trond Myklebustb8a8a0d2013-08-20 21:08:56 -04004763 __be32 *p;
Jeff Laytonca440c32016-09-15 14:40:49 -04004764 uint32_t i;
Andy Adamson504913f2010-10-20 00:17:57 -04004765
4766 p = xdr_inline_decode(xdr, 4);
4767 if (unlikely(!p))
4768 goto out_overflow;
Jeff Laytonca440c32016-09-15 14:40:49 -04004769 fsinfo->nlayouttypes = be32_to_cpup(p);
Andy Adamson504913f2010-10-20 00:17:57 -04004770
4771 /* pNFS is not supported by the underlying file system */
Jeff Laytonca440c32016-09-15 14:40:49 -04004772 if (fsinfo->nlayouttypes == 0)
Andy Adamson504913f2010-10-20 00:17:57 -04004773 return 0;
Andy Adamson504913f2010-10-20 00:17:57 -04004774
4775 /* Decode and set first layout type, move xdr->p past unused types */
Jeff Laytonca440c32016-09-15 14:40:49 -04004776 p = xdr_inline_decode(xdr, fsinfo->nlayouttypes * 4);
Andy Adamson504913f2010-10-20 00:17:57 -04004777 if (unlikely(!p))
4778 goto out_overflow;
Jeff Laytonca440c32016-09-15 14:40:49 -04004779
4780 /* If we get too many, then just cap it at the max */
4781 if (fsinfo->nlayouttypes > NFS_MAX_LAYOUT_TYPES) {
4782 printk(KERN_INFO "NFS: %s: Warning: Too many (%u) pNFS layout types\n",
4783 __func__, fsinfo->nlayouttypes);
4784 fsinfo->nlayouttypes = NFS_MAX_LAYOUT_TYPES;
4785 }
4786
4787 for(i = 0; i < fsinfo->nlayouttypes; ++i)
4788 fsinfo->layouttype[i] = be32_to_cpup(p++);
Andy Adamson504913f2010-10-20 00:17:57 -04004789 return 0;
4790out_overflow:
4791 print_overflow_msg(__func__, xdr);
4792 return -EIO;
4793}
4794
4795/*
4796 * The type of file system exported.
4797 * Note we must ensure that layouttype is set in any non-error case.
4798 */
4799static int decode_attr_pnfstype(struct xdr_stream *xdr, uint32_t *bitmap,
Jeff Laytonca440c32016-09-15 14:40:49 -04004800 struct nfs_fsinfo *fsinfo)
Andy Adamson504913f2010-10-20 00:17:57 -04004801{
4802 int status = 0;
4803
4804 dprintk("%s: bitmap is %x\n", __func__, bitmap[1]);
4805 if (unlikely(bitmap[1] & (FATTR4_WORD1_FS_LAYOUT_TYPES - 1U)))
4806 return -EIO;
4807 if (bitmap[1] & FATTR4_WORD1_FS_LAYOUT_TYPES) {
Jeff Laytonca440c32016-09-15 14:40:49 -04004808 status = decode_pnfs_layout_types(xdr, fsinfo);
Andy Adamson504913f2010-10-20 00:17:57 -04004809 bitmap[1] &= ~FATTR4_WORD1_FS_LAYOUT_TYPES;
Jeff Layton3132e492016-08-10 15:58:24 -04004810 }
Andy Adamson504913f2010-10-20 00:17:57 -04004811 return status;
4812}
4813
Fred Isamandae100c2011-07-30 20:52:37 -04004814/*
4815 * The prefered block size for layout directed io
4816 */
4817static int decode_attr_layout_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
4818 uint32_t *res)
4819{
4820 __be32 *p;
4821
4822 dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
4823 *res = 0;
4824 if (bitmap[2] & FATTR4_WORD2_LAYOUT_BLKSIZE) {
4825 p = xdr_inline_decode(xdr, 4);
4826 if (unlikely(!p)) {
4827 print_overflow_msg(__func__, xdr);
4828 return -EIO;
4829 }
4830 *res = be32_to_cpup(p);
4831 bitmap[2] &= ~FATTR4_WORD2_LAYOUT_BLKSIZE;
4832 }
4833 return 0;
4834}
4835
Peng Tao2a92ee92015-09-26 02:24:37 +08004836/*
4837 * The granularity of a CLONE operation.
4838 */
4839static int decode_attr_clone_blksize(struct xdr_stream *xdr, uint32_t *bitmap,
4840 uint32_t *res)
4841{
4842 __be32 *p;
4843
4844 dprintk("%s: bitmap is %x\n", __func__, bitmap[2]);
4845 *res = 0;
4846 if (bitmap[2] & FATTR4_WORD2_CLONE_BLKSIZE) {
4847 p = xdr_inline_decode(xdr, 4);
4848 if (unlikely(!p)) {
4849 print_overflow_msg(__func__, xdr);
4850 return -EIO;
4851 }
4852 *res = be32_to_cpup(p);
4853 bitmap[2] &= ~FATTR4_WORD2_CLONE_BLKSIZE;
4854 }
4855 return 0;
4856}
4857
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
4859{
Trond Myklebust256e48b2012-06-21 11:18:13 -04004860 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04004861 uint32_t attrlen, bitmap[3];
Linus Torvalds1da177e2005-04-16 15:20:36 -07004862 int status;
4863
4864 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4865 goto xdr_error;
4866 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4867 goto xdr_error;
4868 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4869 goto xdr_error;
4870
4871 fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
4872
4873 if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
4874 goto xdr_error;
4875 if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
4876 goto xdr_error;
4877 if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
4878 goto xdr_error;
4879 fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
4880 if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
4881 goto xdr_error;
4882 fsinfo->wtpref = fsinfo->wtmax;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004883
4884 status = -EIO;
4885 if (unlikely(bitmap[0]))
4886 goto xdr_error;
4887
Ricardo Labiaga55b6e772010-10-12 16:30:06 -07004888 status = decode_attr_time_delta(xdr, bitmap, &fsinfo->time_delta);
4889 if (status != 0)
4890 goto xdr_error;
Jeff Laytonca440c32016-09-15 14:40:49 -04004891 status = decode_attr_pnfstype(xdr, bitmap, fsinfo);
Andy Adamson504913f2010-10-20 00:17:57 -04004892 if (status != 0)
4893 goto xdr_error;
Andreas Gruenbacher1ca843a2015-11-03 18:25:33 +01004894
4895 status = -EIO;
4896 if (unlikely(bitmap[1]))
4897 goto xdr_error;
4898
Fred Isamandae100c2011-07-30 20:52:37 -04004899 status = decode_attr_layout_blksize(xdr, bitmap, &fsinfo->blksize);
4900 if (status)
4901 goto xdr_error;
Peng Tao2a92ee92015-09-26 02:24:37 +08004902 status = decode_attr_clone_blksize(xdr, bitmap, &fsinfo->clone_blksize);
4903 if (status)
4904 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004905
4906 status = verify_attr_len(xdr, savep, attrlen);
4907xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07004908 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004909 return status;
4910}
4911
4912static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
4913{
Al Viro8687b632006-10-19 23:28:48 -07004914 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004915 uint32_t len;
4916 int status;
4917
Trond Myklebust99367812007-07-17 21:52:41 -04004918 /* Zero handle first to allow comparisons */
4919 memset(fh, 0, sizeof(*fh));
4920
Linus Torvalds1da177e2005-04-16 15:20:36 -07004921 status = decode_op_hdr(xdr, OP_GETFH);
4922 if (status)
4923 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004924
Benny Halevyc0eae662009-08-14 17:20:14 +03004925 p = xdr_inline_decode(xdr, 4);
4926 if (unlikely(!p))
4927 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03004928 len = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004929 if (len > NFS4_FHSIZE)
4930 return -EIO;
4931 fh->size = len;
Benny Halevyc0eae662009-08-14 17:20:14 +03004932 p = xdr_inline_decode(xdr, len);
4933 if (unlikely(!p))
4934 goto out_overflow;
Benny Halevy99398d02009-08-14 17:20:05 +03004935 memcpy(fh->data, p, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004936 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03004937out_overflow:
4938 print_overflow_msg(__func__, xdr);
4939 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004940}
4941
4942static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
4943{
4944 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004945
Linus Torvalds1da177e2005-04-16 15:20:36 -07004946 status = decode_op_hdr(xdr, OP_LINK);
4947 if (status)
4948 return status;
4949 return decode_change_info(xdr, cinfo);
4950}
4951
4952/*
4953 * We create the owner, so we know a proper owner.id length is 4.
4954 */
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004955static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004956{
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004957 uint64_t offset, length, clientid;
Al Viro8687b632006-10-19 23:28:48 -07004958 __be32 *p;
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004959 uint32_t namelen, type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004960
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004961 p = xdr_inline_decode(xdr, 32); /* read 32 bytes */
Benny Halevyc0eae662009-08-14 17:20:14 +03004962 if (unlikely(!p))
4963 goto out_overflow;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004964 p = xdr_decode_hyper(p, &offset); /* read 2 8-byte long words */
Benny Halevy3ceb4db2009-08-14 17:19:41 +03004965 p = xdr_decode_hyper(p, &length);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004966 type = be32_to_cpup(p++); /* 4 byte read */
4967 if (fl != NULL) { /* manipulate file lock */
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004968 fl->fl_start = (loff_t)offset;
4969 fl->fl_end = fl->fl_start + (loff_t)length - 1;
4970 if (length == ~(uint64_t)0)
4971 fl->fl_end = OFFSET_MAX;
4972 fl->fl_type = F_WRLCK;
4973 if (type & 1)
4974 fl->fl_type = F_RDLCK;
4975 fl->fl_pid = 0;
4976 }
Bryan Schumakerbabddc72010-10-20 15:44:29 -04004977 p = xdr_decode_hyper(p, &clientid); /* read 8 bytes */
4978 namelen = be32_to_cpup(p); /* read 4 bytes */ /* have read all 32 bytes now */
4979 p = xdr_inline_decode(xdr, namelen); /* variable size field */
Benny Halevyc0eae662009-08-14 17:20:14 +03004980 if (likely(p))
4981 return -NFS4ERR_DENIED;
4982out_overflow:
4983 print_overflow_msg(__func__, xdr);
4984 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004985}
4986
Trond Myklebust911d1aa2006-01-03 09:55:16 +01004987static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004988{
Linus Torvalds1da177e2005-04-16 15:20:36 -07004989 int status;
4990
4991 status = decode_op_hdr(xdr, OP_LOCK);
Trond Myklebustc1d51932008-04-07 13:20:54 -04004992 if (status == -EIO)
4993 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004994 if (status == 0) {
Trond Myklebust93b717f2016-05-16 17:42:43 -04004995 status = decode_lock_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03004996 if (unlikely(status))
4997 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 } else if (status == -NFS4ERR_DENIED)
Trond Myklebustc1d51932008-04-07 13:20:54 -04004999 status = decode_lock_denied(xdr, NULL);
5000 if (res->open_seqid != NULL)
5001 nfs_increment_open_seqid(status, res->open_seqid);
5002 nfs_increment_lock_seqid(status, res->lock_seqid);
5003out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005004 return status;
5005}
5006
Trond Myklebust911d1aa2006-01-03 09:55:16 +01005007static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005008{
5009 int status;
5010 status = decode_op_hdr(xdr, OP_LOCKT);
5011 if (status == -NFS4ERR_DENIED)
Trond Myklebust911d1aa2006-01-03 09:55:16 +01005012 return decode_lock_denied(xdr, res->denied);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005013 return status;
5014}
5015
Trond Myklebust911d1aa2006-01-03 09:55:16 +01005016static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005017{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005018 int status;
5019
5020 status = decode_op_hdr(xdr, OP_LOCKU);
Trond Myklebustc1d51932008-04-07 13:20:54 -04005021 if (status != -EIO)
5022 nfs_increment_lock_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03005023 if (status == 0)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005024 status = decode_lock_stateid(xdr, &res->stateid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005025 return status;
5026}
5027
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04005028static int decode_release_lockowner(struct xdr_stream *xdr)
5029{
5030 return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER);
5031}
5032
Linus Torvalds1da177e2005-04-16 15:20:36 -07005033static int decode_lookup(struct xdr_stream *xdr)
5034{
5035 return decode_op_hdr(xdr, OP_LOOKUP);
5036}
5037
5038/* This is too sick! */
Trond Myklebust7d160a62015-09-05 19:06:57 -04005039static int decode_space_limit(struct xdr_stream *xdr,
5040 unsigned long *pagemod_limit)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005041{
Andy Adamson05d564f2008-12-23 16:06:15 -05005042 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005043 uint32_t limit_type, nblocks, blocksize;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005044 u64 maxsize = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045
Benny Halevyc0eae662009-08-14 17:20:14 +03005046 p = xdr_inline_decode(xdr, 12);
5047 if (unlikely(!p))
5048 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005049 limit_type = be32_to_cpup(p++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005050 switch (limit_type) {
Trond Myklebust7d160a62015-09-05 19:06:57 -04005051 case NFS4_LIMIT_SIZE:
5052 xdr_decode_hyper(p, &maxsize);
Andy Adamson05d564f2008-12-23 16:06:15 -05005053 break;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005054 case NFS4_LIMIT_BLOCKS:
Benny Halevy6f723f72009-08-14 17:19:37 +03005055 nblocks = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005056 blocksize = be32_to_cpup(p);
Trond Myklebust7d160a62015-09-05 19:06:57 -04005057 maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005058 }
Kirill A. Shutemov09cbfea2016-04-01 15:29:47 +03005059 maxsize >>= PAGE_SHIFT;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005060 *pagemod_limit = min_t(u64, maxsize, ULONG_MAX);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005061 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005062out_overflow:
5063 print_overflow_msg(__func__, xdr);
5064 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005065}
5066
Trond Myklebust6ae37332015-01-30 14:21:14 -05005067static int decode_rw_delegation(struct xdr_stream *xdr,
5068 uint32_t delegation_type,
5069 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005070{
Andy Adamson05d564f2008-12-23 16:06:15 -05005071 __be32 *p;
Benny Halevy07d30432009-08-14 17:19:52 +03005072 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005073
Trond Myklebust93b717f2016-05-16 17:42:43 -04005074 status = decode_delegation_stateid(xdr, &res->delegation);
Benny Halevy07d30432009-08-14 17:19:52 +03005075 if (unlikely(status))
5076 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005077 p = xdr_inline_decode(xdr, 4);
5078 if (unlikely(!p))
5079 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005080 res->do_recall = be32_to_cpup(p);
Andy Adamson05d564f2008-12-23 16:06:15 -05005081
Linus Torvalds1da177e2005-04-16 15:20:36 -07005082 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05005083 case NFS4_OPEN_DELEGATE_READ:
5084 res->delegation_type = FMODE_READ;
5085 break;
5086 case NFS4_OPEN_DELEGATE_WRITE:
5087 res->delegation_type = FMODE_WRITE|FMODE_READ;
Trond Myklebust7d160a62015-09-05 19:06:57 -04005088 if (decode_space_limit(xdr, &res->pagemod_limit) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005089 return -EIO;
5090 }
David Howells7539bba2006-08-22 20:06:09 -04005091 return decode_ace(xdr, NULL, res->server->nfs_client);
Benny Halevyc0eae662009-08-14 17:20:14 +03005092out_overflow:
5093 print_overflow_msg(__func__, xdr);
5094 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005095}
5096
Trond Myklebust6ae37332015-01-30 14:21:14 -05005097static int decode_no_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
5098{
5099 __be32 *p;
5100 uint32_t why_no_delegation;
5101
5102 p = xdr_inline_decode(xdr, 4);
5103 if (unlikely(!p))
5104 goto out_overflow;
5105 why_no_delegation = be32_to_cpup(p);
5106 switch (why_no_delegation) {
5107 case WND4_CONTENTION:
5108 case WND4_RESOURCE:
5109 xdr_inline_decode(xdr, 4);
5110 /* Ignore for now */
5111 }
5112 return 0;
5113out_overflow:
5114 print_overflow_msg(__func__, xdr);
5115 return -EIO;
5116}
5117
5118static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
5119{
5120 __be32 *p;
5121 uint32_t delegation_type;
5122
5123 p = xdr_inline_decode(xdr, 4);
5124 if (unlikely(!p))
5125 goto out_overflow;
5126 delegation_type = be32_to_cpup(p);
5127 res->delegation_type = 0;
5128 switch (delegation_type) {
5129 case NFS4_OPEN_DELEGATE_NONE:
5130 return 0;
5131 case NFS4_OPEN_DELEGATE_READ:
5132 case NFS4_OPEN_DELEGATE_WRITE:
5133 return decode_rw_delegation(xdr, delegation_type, res);
5134 case NFS4_OPEN_DELEGATE_NONE_EXT:
5135 return decode_no_delegation(xdr, res);
5136 }
5137 return -EIO;
5138out_overflow:
5139 print_overflow_msg(__func__, xdr);
5140 return -EIO;
5141}
5142
Linus Torvalds1da177e2005-04-16 15:20:36 -07005143static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
5144{
Andy Adamson05d564f2008-12-23 16:06:15 -05005145 __be32 *p;
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005146 uint32_t savewords, bmlen, i;
Andy Adamson05d564f2008-12-23 16:06:15 -05005147 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005148
Trond Myklebustc7848f62013-12-04 17:39:23 -05005149 if (!__decode_op_hdr(xdr, OP_OPEN, &status))
5150 return status;
5151 nfs_increment_open_seqid(status, res->seqid);
5152 if (status)
5153 return status;
Trond Myklebust93b717f2016-05-16 17:42:43 -04005154 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005155 if (unlikely(status))
Andy Adamson05d564f2008-12-23 16:06:15 -05005156 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005157
Andy Adamson05d564f2008-12-23 16:06:15 -05005158 decode_change_info(xdr, &res->cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005159
Benny Halevyc0eae662009-08-14 17:20:14 +03005160 p = xdr_inline_decode(xdr, 8);
5161 if (unlikely(!p))
5162 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005163 res->rflags = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005164 bmlen = be32_to_cpup(p);
Andy Adamson05d564f2008-12-23 16:06:15 -05005165 if (bmlen > 10)
5166 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005167
Benny Halevyc0eae662009-08-14 17:20:14 +03005168 p = xdr_inline_decode(xdr, bmlen << 2);
5169 if (unlikely(!p))
5170 goto out_overflow;
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005171 savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
5172 for (i = 0; i < savewords; ++i)
Benny Halevy6f723f72009-08-14 17:19:37 +03005173 res->attrset[i] = be32_to_cpup(p++);
Jeff Laytonaa53ed52007-06-05 14:49:03 -04005174 for (; i < NFS4_BITMAP_SIZE; i++)
5175 res->attrset[i] = 0;
5176
Linus Torvalds1da177e2005-04-16 15:20:36 -07005177 return decode_delegation(xdr, res);
5178xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07005179 dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005180 return -EIO;
Benny Halevyc0eae662009-08-14 17:20:14 +03005181out_overflow:
5182 print_overflow_msg(__func__, xdr);
5183 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005184}
5185
5186static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
5187{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005188 int status;
5189
Andy Adamson05d564f2008-12-23 16:06:15 -05005190 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
Trond Myklebustc1d51932008-04-07 13:20:54 -04005191 if (status != -EIO)
5192 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03005193 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005194 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005195 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005196}
5197
5198static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
5199{
Linus Torvalds1da177e2005-04-16 15:20:36 -07005200 int status;
5201
5202 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04005203 if (status != -EIO)
5204 nfs_increment_open_seqid(status, res->seqid);
Benny Halevy07d30432009-08-14 17:19:52 +03005205 if (!status)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005206 status = decode_open_stateid(xdr, &res->stateid);
Benny Halevy07d30432009-08-14 17:19:52 +03005207 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005208}
5209
5210static int decode_putfh(struct xdr_stream *xdr)
5211{
5212 return decode_op_hdr(xdr, OP_PUTFH);
5213}
5214
5215static int decode_putrootfh(struct xdr_stream *xdr)
5216{
5217 return decode_op_hdr(xdr, OP_PUTROOTFH);
5218}
5219
Anna Schumaker9137bdf2014-05-06 09:12:25 -04005220static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req,
5221 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005222{
Al Viro8687b632006-10-19 23:28:48 -07005223 __be32 *p;
Trond Myklebust64bd5772012-06-20 22:35:05 -04005224 uint32_t count, eof, recvd;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005225 int status;
5226
5227 status = decode_op_hdr(xdr, OP_READ);
5228 if (status)
5229 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005230 p = xdr_inline_decode(xdr, 8);
5231 if (unlikely(!p))
5232 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005233 eof = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005234 count = be32_to_cpup(p);
Trond Myklebust64bd5772012-06-20 22:35:05 -04005235 recvd = xdr_read_pages(xdr, count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005236 if (count > recvd) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005237 dprintk("NFS: server cheating in read reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07005238 "count %u > recvd %u\n", count, recvd);
5239 count = recvd;
5240 eof = 0;
5241 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005242 res->eof = eof;
5243 res->count = count;
5244 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005245out_overflow:
5246 print_overflow_msg(__func__, xdr);
5247 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005248}
5249
5250static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
5251{
Chuck Leverbcecff72007-10-26 13:32:03 -04005252 int status;
Chuck Levercd937102012-03-02 17:14:31 -05005253 __be32 verf[2];
Linus Torvalds1da177e2005-04-16 15:20:36 -07005254
5255 status = decode_op_hdr(xdr, OP_READDIR);
Benny Halevydb942bb2009-08-14 17:19:56 +03005256 if (!status)
5257 status = decode_verifier(xdr, readdir->verifier.data);
5258 if (unlikely(status))
Linus Torvalds1da177e2005-04-16 15:20:36 -07005259 return status;
Chuck Levercd937102012-03-02 17:14:31 -05005260 memcpy(verf, readdir->verifier.data, sizeof(verf));
Fred Isaman44109242008-04-02 15:21:15 +03005261 dprintk("%s: verifier = %08x:%08x\n",
Chuck Levercd937102012-03-02 17:14:31 -05005262 __func__, verf[0], verf[1]);
Trond Myklebust64bd5772012-06-20 22:35:05 -04005263 return xdr_read_pages(xdr, xdr->buf->page_len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005264}
5265
5266static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
5267{
5268 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
Chuck Leverbcecff72007-10-26 13:32:03 -04005269 u32 len, recvd;
Al Viro8687b632006-10-19 23:28:48 -07005270 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005271 int status;
5272
5273 status = decode_op_hdr(xdr, OP_READLINK);
5274 if (status)
5275 return status;
5276
5277 /* Convert length of symlink */
Benny Halevyc0eae662009-08-14 17:20:14 +03005278 p = xdr_inline_decode(xdr, 4);
5279 if (unlikely(!p))
5280 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005281 len = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005282 if (len >= rcvbuf->page_len || len <= 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005283 dprintk("nfs: server returned giant symlink!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07005284 return -ENAMETOOLONG;
5285 }
Trond Myklebust64bd5772012-06-20 22:35:05 -04005286 recvd = xdr_read_pages(xdr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005287 if (recvd < len) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005288 dprintk("NFS: server cheating in readlink reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07005289 "count %u > recvd %u\n", len, recvd);
5290 return -EIO;
5291 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005292 /*
5293 * The XDR encode routine has set things up so that
5294 * the link text will be copied directly into the
5295 * buffer. We just have to do overflow-checking,
5296 * and and null-terminate the text (the VFS expects
5297 * null-termination).
5298 */
Chuck Leverb4687da2010-09-21 16:55:48 -04005299 xdr_terminate_string(rcvbuf, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005300 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005301out_overflow:
5302 print_overflow_msg(__func__, xdr);
5303 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005304}
5305
5306static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
5307{
5308 int status;
5309
5310 status = decode_op_hdr(xdr, OP_REMOVE);
5311 if (status)
5312 goto out;
5313 status = decode_change_info(xdr, cinfo);
5314out:
5315 return status;
5316}
5317
5318static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
5319 struct nfs4_change_info *new_cinfo)
5320{
5321 int status;
5322
5323 status = decode_op_hdr(xdr, OP_RENAME);
5324 if (status)
5325 goto out;
5326 if ((status = decode_change_info(xdr, old_cinfo)))
5327 goto out;
5328 status = decode_change_info(xdr, new_cinfo);
5329out:
5330 return status;
5331}
5332
5333static int decode_renew(struct xdr_stream *xdr)
5334{
5335 return decode_op_hdr(xdr, OP_RENEW);
5336}
5337
Trond Myklebust56ae19f2005-10-27 22:12:40 -04005338static int
5339decode_restorefh(struct xdr_stream *xdr)
5340{
5341 return decode_op_hdr(xdr, OP_RESTOREFH);
5342}
5343
J. Bruce Fields029d1052005-06-22 17:16:22 +00005344static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
Andy Adamsonbf118a32011-12-07 11:55:27 -05005345 struct nfs_getaclres *res)
J. Bruce Fields029d1052005-06-22 17:16:22 +00005346{
Trond Myklebust256e48b2012-06-21 11:18:13 -04005347 unsigned int savep;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005348 uint32_t attrlen,
Fred Isamandae100c2011-07-30 20:52:37 -04005349 bitmap[3] = {0};
J. Bruce Fields029d1052005-06-22 17:16:22 +00005350 int status;
Trond Myklebustcff298c2012-08-14 17:14:17 -04005351 unsigned int pg_offset;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005352
Andy Adamsonbf118a32011-12-07 11:55:27 -05005353 res->acl_len = 0;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005354 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
5355 goto out;
Sachin Prabhu5a006892012-04-17 14:35:39 +01005356
Trond Myklebust519d3952012-08-14 17:30:10 -04005357 xdr_enter_page(xdr, xdr->buf->page_len);
5358
Trond Myklebustcff298c2012-08-14 17:14:17 -04005359 /* Calculate the offset of the page data */
5360 pg_offset = xdr->buf->head[0].iov_len;
Sachin Prabhu5a006892012-04-17 14:35:39 +01005361
J. Bruce Fields029d1052005-06-22 17:16:22 +00005362 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
5363 goto out;
5364 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
5365 goto out;
5366
5367 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
5368 return -EIO;
5369 if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
J. Bruce Fields029d1052005-06-22 17:16:22 +00005370
Andy Adamsonbf118a32011-12-07 11:55:27 -05005371 /* The bitmap (xdr len + bitmaps) and the attr xdr len words
5372 * are stored with the acl data to handle the problem of
5373 * variable length bitmaps.*/
Trond Myklebustcff298c2012-08-14 17:14:17 -04005374 res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
Trond Myklebust519d3952012-08-14 17:30:10 -04005375 res->acl_len = attrlen;
Trond Myklebust1f1ea6c2012-08-26 11:44:43 -07005376
5377 /* Check for receive buffer overflow */
5378 if (res->acl_len > (xdr->nwords << 2) ||
5379 res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
5380 res->acl_flags |= NFS4_ACL_TRUNC;
Trond Myklebust519d3952012-08-14 17:30:10 -04005381 dprintk("NFS: acl reply: attrlen %u > page_len %u\n",
Trond Myklebustcff298c2012-08-14 17:14:17 -04005382 attrlen, xdr->nwords << 2);
J. Bruce Fields029d1052005-06-22 17:16:22 +00005383 }
J. Bruce Fields8c233cf2005-10-13 16:54:27 -04005384 } else
5385 status = -EOPNOTSUPP;
J. Bruce Fields029d1052005-06-22 17:16:22 +00005386
5387out:
5388 return status;
5389}
5390
Linus Torvalds1da177e2005-04-16 15:20:36 -07005391static int
5392decode_savefh(struct xdr_stream *xdr)
5393{
5394 return decode_op_hdr(xdr, OP_SAVEFH);
5395}
5396
Benny Halevy9e9ecc02009-04-01 09:22:00 -04005397static int decode_setattr(struct xdr_stream *xdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005398{
Al Viro8687b632006-10-19 23:28:48 -07005399 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005400 uint32_t bmlen;
5401 int status;
5402
Linus Torvalds1da177e2005-04-16 15:20:36 -07005403 status = decode_op_hdr(xdr, OP_SETATTR);
5404 if (status)
5405 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005406 p = xdr_inline_decode(xdr, 4);
5407 if (unlikely(!p))
5408 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005409 bmlen = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005410 p = xdr_inline_decode(xdr, bmlen << 2);
5411 if (likely(p))
5412 return 0;
5413out_overflow:
5414 print_overflow_msg(__func__, xdr);
5415 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005416}
5417
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04005418static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_setclientid_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005419{
Al Viro8687b632006-10-19 23:28:48 -07005420 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005421 uint32_t opnum;
5422 int32_t nfserr;
5423
Benny Halevyc0eae662009-08-14 17:20:14 +03005424 p = xdr_inline_decode(xdr, 8);
5425 if (unlikely(!p))
5426 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005427 opnum = be32_to_cpup(p++);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005428 if (opnum != OP_SETCLIENTID) {
Chuck Leverfe82a182007-09-11 18:01:10 -04005429 dprintk("nfs: decode_setclientid: Server returned operation"
Andy Adamson6c0195a2008-12-23 16:06:15 -05005430 " %d\n", opnum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005431 return -EIO;
5432 }
Benny Halevycccddf42009-08-14 17:20:19 +03005433 nfserr = be32_to_cpup(p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005434 if (nfserr == NFS_OK) {
Benny Halevyc0eae662009-08-14 17:20:14 +03005435 p = xdr_inline_decode(xdr, 8 + NFS4_VERIFIER_SIZE);
5436 if (unlikely(!p))
5437 goto out_overflow;
Trond Myklebustbb8b27e2010-04-16 16:43:06 -04005438 p = xdr_decode_hyper(p, &res->clientid);
5439 memcpy(res->confirm.data, p, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005440 } else if (nfserr == NFSERR_CLID_INUSE) {
5441 uint32_t len;
5442
5443 /* skip netid string */
Benny Halevyc0eae662009-08-14 17:20:14 +03005444 p = xdr_inline_decode(xdr, 4);
5445 if (unlikely(!p))
5446 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005447 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005448 p = xdr_inline_decode(xdr, len);
5449 if (unlikely(!p))
5450 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005451
5452 /* skip uaddr string */
Benny Halevyc0eae662009-08-14 17:20:14 +03005453 p = xdr_inline_decode(xdr, 4);
5454 if (unlikely(!p))
5455 goto out_overflow;
Benny Halevycccddf42009-08-14 17:20:19 +03005456 len = be32_to_cpup(p);
Benny Halevyc0eae662009-08-14 17:20:14 +03005457 p = xdr_inline_decode(xdr, len);
5458 if (unlikely(!p))
5459 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005460 return -NFSERR_CLID_INUSE;
5461 } else
Benny Halevy856dff32008-03-31 17:39:06 +03005462 return nfs4_stat_to_errno(nfserr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005463
5464 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005465out_overflow:
5466 print_overflow_msg(__func__, xdr);
5467 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468}
5469
5470static int decode_setclientid_confirm(struct xdr_stream *xdr)
5471{
5472 return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
5473}
5474
Anna Schumaker9137bdf2014-05-06 09:12:25 -04005475static int decode_write(struct xdr_stream *xdr, struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005476{
Al Viro8687b632006-10-19 23:28:48 -07005477 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005478 int status;
5479
5480 status = decode_op_hdr(xdr, OP_WRITE);
5481 if (status)
5482 return status;
5483
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04005484 p = xdr_inline_decode(xdr, 8);
Benny Halevyc0eae662009-08-14 17:20:14 +03005485 if (unlikely(!p))
5486 goto out_overflow;
Benny Halevy6f723f72009-08-14 17:19:37 +03005487 res->count = be32_to_cpup(p++);
5488 res->verf->committed = be32_to_cpup(p++);
Trond Myklebust2f2c63b2012-06-08 11:56:09 -04005489 return decode_write_verifier(xdr, &res->verf->verifier);
Benny Halevyc0eae662009-08-14 17:20:14 +03005490out_overflow:
5491 print_overflow_msg(__func__, xdr);
5492 return -EIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005493}
5494
5495static int decode_delegreturn(struct xdr_stream *xdr)
5496{
5497 return decode_op_hdr(xdr, OP_DELEGRETURN);
5498}
5499
Chuck Leverfb15b262013-03-16 15:54:34 -04005500static int decode_secinfo_gss(struct xdr_stream *xdr,
5501 struct nfs4_secinfo4 *flavor)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005502{
Chuck Leverfb15b262013-03-16 15:54:34 -04005503 u32 oid_len;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005504 __be32 *p;
5505
5506 p = xdr_inline_decode(xdr, 4);
5507 if (unlikely(!p))
5508 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005509 oid_len = be32_to_cpup(p);
5510 if (oid_len > GSS_OID_MAX_LEN)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005511 goto out_err;
5512
Chuck Leverfb15b262013-03-16 15:54:34 -04005513 p = xdr_inline_decode(xdr, oid_len);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005514 if (unlikely(!p))
5515 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005516 memcpy(flavor->flavor_info.oid.data, p, oid_len);
5517 flavor->flavor_info.oid.len = oid_len;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005518
5519 p = xdr_inline_decode(xdr, 8);
5520 if (unlikely(!p))
5521 goto out_overflow;
Chuck Leverfb15b262013-03-16 15:54:34 -04005522 flavor->flavor_info.qop = be32_to_cpup(p++);
5523 flavor->flavor_info.service = be32_to_cpup(p);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005524
5525 return 0;
5526
5527out_overflow:
5528 print_overflow_msg(__func__, xdr);
5529 return -EIO;
5530out_err:
5531 return -EINVAL;
5532}
5533
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005534static int decode_secinfo_common(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005535{
Chuck Leverfb15b262013-03-16 15:54:34 -04005536 struct nfs4_secinfo4 *sec_flavor;
5537 unsigned int i, num_flavors;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005538 int status;
5539 __be32 *p;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005540
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005541 p = xdr_inline_decode(xdr, 4);
5542 if (unlikely(!p))
5543 goto out_overflow;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005544
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005545 res->flavors->num_flavors = 0;
5546 num_flavors = be32_to_cpup(p);
5547
5548 for (i = 0; i < num_flavors; i++) {
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005549 sec_flavor = &res->flavors->flavors[i];
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005550 if ((char *)&sec_flavor[1] - (char *)res->flavors > PAGE_SIZE)
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005551 break;
5552
5553 p = xdr_inline_decode(xdr, 4);
5554 if (unlikely(!p))
5555 goto out_overflow;
5556 sec_flavor->flavor = be32_to_cpup(p);
5557
5558 if (sec_flavor->flavor == RPC_AUTH_GSS) {
Bryan Schumaker613e9012011-04-27 15:28:44 -04005559 status = decode_secinfo_gss(xdr, sec_flavor);
5560 if (status)
5561 goto out;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005562 }
Bryan Schumakerc3dfc282011-04-13 14:31:31 -04005563 res->flavors->num_flavors++;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005564 }
5565
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005566 status = 0;
Bryan Schumaker613e9012011-04-27 15:28:44 -04005567out:
5568 return status;
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00005569out_overflow:
5570 print_overflow_msg(__func__, xdr);
5571 return -EIO;
5572}
5573
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005574static int decode_secinfo(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
5575{
5576 int status = decode_op_hdr(xdr, OP_SECINFO);
5577 if (status)
5578 return status;
5579 return decode_secinfo_common(xdr, res);
5580}
5581
Benny Halevy99fe60d2009-04-01 09:22:29 -04005582#if defined(CONFIG_NFS_V4_1)
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04005583static int decode_secinfo_no_name(struct xdr_stream *xdr, struct nfs4_secinfo_res *res)
5584{
5585 int status = decode_op_hdr(xdr, OP_SECINFO_NO_NAME);
5586 if (status)
5587 return status;
5588 return decode_secinfo_common(xdr, res);
5589}
5590
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005591static int decode_op_map(struct xdr_stream *xdr, struct nfs4_op_map *op_map)
5592{
5593 __be32 *p;
5594 uint32_t bitmap_words;
5595 unsigned int i;
5596
5597 p = xdr_inline_decode(xdr, 4);
5598 bitmap_words = be32_to_cpup(p++);
5599 if (bitmap_words > NFS4_OP_MAP_NUM_WORDS)
5600 return -EIO;
5601 p = xdr_inline_decode(xdr, 4 * bitmap_words);
5602 for (i = 0; i < bitmap_words; i++)
5603 op_map->u.words[i] = be32_to_cpup(p++);
5604
5605 return 0;
5606}
5607
Benny Halevy99fe60d2009-04-01 09:22:29 -04005608static int decode_exchange_id(struct xdr_stream *xdr,
5609 struct nfs41_exchange_id_res *res)
5610{
5611 __be32 *p;
5612 uint32_t dummy;
Benny Halevy2460ba52009-08-14 17:20:10 +03005613 char *dummy_str;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005614 int status;
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005615 uint32_t impl_id_count;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005616
5617 status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
5618 if (status)
5619 return status;
5620
Benny Halevyc0eae662009-08-14 17:20:14 +03005621 p = xdr_inline_decode(xdr, 8);
5622 if (unlikely(!p))
5623 goto out_overflow;
Trond Myklebust32b01312012-05-26 13:41:04 -04005624 xdr_decode_hyper(p, &res->clientid);
Benny Halevyc0eae662009-08-14 17:20:14 +03005625 p = xdr_inline_decode(xdr, 12);
5626 if (unlikely(!p))
5627 goto out_overflow;
Trond Myklebust32b01312012-05-26 13:41:04 -04005628 res->seqid = be32_to_cpup(p++);
5629 res->flags = be32_to_cpup(p++);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005630
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005631 res->state_protect.how = be32_to_cpup(p);
5632 switch (res->state_protect.how) {
5633 case SP4_NONE:
5634 break;
5635 case SP4_MACH_CRED:
5636 status = decode_op_map(xdr, &res->state_protect.enforce);
5637 if (status)
5638 return status;
5639 status = decode_op_map(xdr, &res->state_protect.allow);
5640 if (status)
5641 return status;
5642 break;
5643 default:
5644 WARN_ON_ONCE(1);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005645 return -EIO;
Weston Andros Adamson2031cd12013-08-13 16:37:32 -04005646 }
Benny Halevy99fe60d2009-04-01 09:22:29 -04005647
Chuck Leveracdeb692012-05-21 22:46:16 -04005648 /* server_owner4.so_minor_id */
Benny Halevyc0eae662009-08-14 17:20:14 +03005649 p = xdr_inline_decode(xdr, 8);
5650 if (unlikely(!p))
5651 goto out_overflow;
Chuck Leveracdeb692012-05-21 22:46:16 -04005652 p = xdr_decode_hyper(p, &res->server_owner->minor_id);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005653
Chuck Leveracdeb692012-05-21 22:46:16 -04005654 /* server_owner4.so_major_id */
Benny Halevy2460ba52009-08-14 17:20:10 +03005655 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5656 if (unlikely(status))
5657 return status;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005658 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5659 return -EIO;
Chuck Leveracdeb692012-05-21 22:46:16 -04005660 memcpy(res->server_owner->major_id, dummy_str, dummy);
5661 res->server_owner->major_id_sz = dummy;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005662
Chuck Leveracdeb692012-05-21 22:46:16 -04005663 /* server_scope4 */
5664 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5665 if (unlikely(status))
5666 return status;
5667 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5668 return -EIO;
Weston Andros Adamson78fe0f42011-05-31 19:05:47 -04005669 memcpy(res->server_scope->server_scope, dummy_str, dummy);
5670 res->server_scope->server_scope_sz = dummy;
5671
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005672 /* Implementation Id */
5673 p = xdr_inline_decode(xdr, 4);
5674 if (unlikely(!p))
5675 goto out_overflow;
5676 impl_id_count = be32_to_cpup(p++);
Benny Halevy99fe60d2009-04-01 09:22:29 -04005677
Weston Andros Adamson7d2ed9a2012-02-17 15:20:26 -05005678 if (impl_id_count) {
5679 /* nii_domain */
5680 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5681 if (unlikely(status))
5682 return status;
5683 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5684 return -EIO;
5685 memcpy(res->impl_id->domain, dummy_str, dummy);
5686
5687 /* nii_name */
5688 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
5689 if (unlikely(status))
5690 return status;
5691 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
5692 return -EIO;
5693 memcpy(res->impl_id->name, dummy_str, dummy);
5694
5695 /* nii_date */
5696 p = xdr_inline_decode(xdr, 12);
5697 if (unlikely(!p))
5698 goto out_overflow;
5699 p = xdr_decode_hyper(p, &res->impl_id->date.seconds);
5700 res->impl_id->date.nseconds = be32_to_cpup(p);
5701
5702 /* if there's more than one entry, ignore the rest */
5703 }
Benny Halevy99fe60d2009-04-01 09:22:29 -04005704 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005705out_overflow:
5706 print_overflow_msg(__func__, xdr);
5707 return -EIO;
Benny Halevy99fe60d2009-04-01 09:22:29 -04005708}
Andy Adamsonfc931582009-04-01 09:22:31 -04005709
5710static int decode_chan_attrs(struct xdr_stream *xdr,
5711 struct nfs4_channel_attrs *attrs)
5712{
5713 __be32 *p;
Benny Halevyc9c30dd2011-06-11 17:08:39 -04005714 u32 nr_attrs, val;
Andy Adamsonfc931582009-04-01 09:22:31 -04005715
Benny Halevyc0eae662009-08-14 17:20:14 +03005716 p = xdr_inline_decode(xdr, 28);
5717 if (unlikely(!p))
5718 goto out_overflow;
Benny Halevyc9c30dd2011-06-11 17:08:39 -04005719 val = be32_to_cpup(p++); /* headerpadsz */
5720 if (val)
5721 return -EINVAL; /* no support for header padding yet */
Benny Halevy6f723f72009-08-14 17:19:37 +03005722 attrs->max_rqst_sz = be32_to_cpup(p++);
5723 attrs->max_resp_sz = be32_to_cpup(p++);
5724 attrs->max_resp_sz_cached = be32_to_cpup(p++);
5725 attrs->max_ops = be32_to_cpup(p++);
5726 attrs->max_reqs = be32_to_cpup(p++);
Benny Halevycccddf42009-08-14 17:20:19 +03005727 nr_attrs = be32_to_cpup(p);
Andy Adamsonfc931582009-04-01 09:22:31 -04005728 if (unlikely(nr_attrs > 1)) {
Weston Andros Adamsona0308892012-01-26 13:32:23 -05005729 printk(KERN_WARNING "NFS: %s: Invalid rdma channel attrs "
5730 "count %u\n", __func__, nr_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005731 return -EINVAL;
5732 }
Benny Halevyc0eae662009-08-14 17:20:14 +03005733 if (nr_attrs == 1) {
5734 p = xdr_inline_decode(xdr, 4); /* skip rdma_attrs */
5735 if (unlikely(!p))
5736 goto out_overflow;
5737 }
Andy Adamsonfc931582009-04-01 09:22:31 -04005738 return 0;
Benny Halevyc0eae662009-08-14 17:20:14 +03005739out_overflow:
5740 print_overflow_msg(__func__, xdr);
5741 return -EIO;
Andy Adamsonfc931582009-04-01 09:22:31 -04005742}
5743
Benny Halevye78291e2009-08-14 17:20:00 +03005744static int decode_sessionid(struct xdr_stream *xdr, struct nfs4_sessionid *sid)
5745{
5746 return decode_opaque_fixed(xdr, sid->data, NFS4_MAX_SESSIONID_LEN);
Andy Adamsonfc931582009-04-01 09:22:31 -04005747}
5748
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04005749static int decode_bind_conn_to_session(struct xdr_stream *xdr,
5750 struct nfs41_bind_conn_to_session_res *res)
5751{
5752 __be32 *p;
5753 int status;
5754
5755 status = decode_op_hdr(xdr, OP_BIND_CONN_TO_SESSION);
5756 if (!status)
Trond Myklebust71a097c2015-02-18 09:27:18 -08005757 status = decode_sessionid(xdr, &res->sessionid);
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04005758 if (unlikely(status))
5759 return status;
5760
5761 /* dir flags, rdma mode bool */
5762 p = xdr_inline_decode(xdr, 8);
5763 if (unlikely(!p))
5764 goto out_overflow;
5765
5766 res->dir = be32_to_cpup(p++);
5767 if (res->dir == 0 || res->dir > NFS4_CDFS4_BOTH)
5768 return -EIO;
5769 if (be32_to_cpup(p) == 0)
5770 res->use_conn_in_rdma_mode = false;
5771 else
5772 res->use_conn_in_rdma_mode = true;
5773
5774 return 0;
5775out_overflow:
5776 print_overflow_msg(__func__, xdr);
5777 return -EIO;
5778}
5779
Andy Adamsonfc931582009-04-01 09:22:31 -04005780static int decode_create_session(struct xdr_stream *xdr,
5781 struct nfs41_create_session_res *res)
5782{
5783 __be32 *p;
5784 int status;
Andy Adamsonfc931582009-04-01 09:22:31 -04005785
5786 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
Benny Halevye78291e2009-08-14 17:20:00 +03005787 if (!status)
Trond Myklebust79969dd2015-02-18 11:30:18 -08005788 status = decode_sessionid(xdr, &res->sessionid);
Benny Halevye78291e2009-08-14 17:20:00 +03005789 if (unlikely(status))
Andy Adamsonfc931582009-04-01 09:22:31 -04005790 return status;
5791
Andy Adamsonfc931582009-04-01 09:22:31 -04005792 /* seqid, flags */
Benny Halevyc0eae662009-08-14 17:20:14 +03005793 p = xdr_inline_decode(xdr, 8);
5794 if (unlikely(!p))
5795 goto out_overflow;
Trond Myklebust79969dd2015-02-18 11:30:18 -08005796 res->seqid = be32_to_cpup(p++);
5797 res->flags = be32_to_cpup(p);
Andy Adamsonfc931582009-04-01 09:22:31 -04005798
5799 /* Channel attributes */
Trond Myklebust79969dd2015-02-18 11:30:18 -08005800 status = decode_chan_attrs(xdr, &res->fc_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005801 if (!status)
Trond Myklebust79969dd2015-02-18 11:30:18 -08005802 status = decode_chan_attrs(xdr, &res->bc_attrs);
Andy Adamsonfc931582009-04-01 09:22:31 -04005803 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005804out_overflow:
5805 print_overflow_msg(__func__, xdr);
5806 return -EIO;
Andy Adamsonfc931582009-04-01 09:22:31 -04005807}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04005808
5809static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
5810{
5811 return decode_op_hdr(xdr, OP_DESTROY_SESSION);
5812}
Ricardo Labiaga180197532009-12-05 16:08:40 -05005813
Trond Myklebust66245532012-05-25 17:18:09 -04005814static int decode_destroy_clientid(struct xdr_stream *xdr, void *dummy)
5815{
5816 return decode_op_hdr(xdr, OP_DESTROY_CLIENTID);
5817}
5818
Ricardo Labiaga180197532009-12-05 16:08:40 -05005819static int decode_reclaim_complete(struct xdr_stream *xdr, void *dummy)
5820{
5821 return decode_op_hdr(xdr, OP_RECLAIM_COMPLETE);
5822}
Benny Halevy99fe60d2009-04-01 09:22:29 -04005823#endif /* CONFIG_NFS_V4_1 */
5824
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005825static int decode_sequence(struct xdr_stream *xdr,
5826 struct nfs4_sequence_res *res,
5827 struct rpc_rqst *rqstp)
5828{
5829#if defined(CONFIG_NFS_V4_1)
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005830 struct nfs4_session *session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005831 struct nfs4_sessionid id;
5832 u32 dummy;
5833 int status;
5834 __be32 *p;
5835
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005836 if (res->sr_slot == NULL)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005837 return 0;
Chuck Lever3bd23842013-08-09 12:49:19 -04005838 if (!res->sr_slot->table->session)
5839 return 0;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005840
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005841 status = decode_op_hdr(xdr, OP_SEQUENCE);
Benny Halevye78291e2009-08-14 17:20:00 +03005842 if (!status)
5843 status = decode_sessionid(xdr, &id);
5844 if (unlikely(status))
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005845 goto out_err;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005846
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005847 /*
5848 * If the server returns different values for sessionID, slotID or
5849 * sequence number, the server is looney tunes.
5850 */
Trond Myklebustfdcb4572010-02-08 09:32:40 -05005851 status = -EREMOTEIO;
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005852 session = res->sr_slot->table->session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005853
Trond Myklebuste3725ec2012-11-16 12:25:01 -05005854 if (memcmp(id.data, session->sess_id.data,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005855 NFS4_MAX_SESSIONID_LEN)) {
5856 dprintk("%s Invalid session id\n", __func__);
5857 goto out_err;
5858 }
Benny Halevye78291e2009-08-14 17:20:00 +03005859
Benny Halevyc0eae662009-08-14 17:20:14 +03005860 p = xdr_inline_decode(xdr, 20);
5861 if (unlikely(!p))
5862 goto out_overflow;
Benny Halevye78291e2009-08-14 17:20:00 +03005863
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005864 /* seqid */
Benny Halevy6f723f72009-08-14 17:19:37 +03005865 dummy = be32_to_cpup(p++);
Benny Halevydfb4f3092010-09-24 09:17:01 -04005866 if (dummy != res->sr_slot->seq_nr) {
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005867 dprintk("%s Invalid sequence number\n", __func__);
5868 goto out_err;
5869 }
5870 /* slot id */
Benny Halevy6f723f72009-08-14 17:19:37 +03005871 dummy = be32_to_cpup(p++);
Trond Myklebustdf2fabf2012-11-16 12:45:06 -05005872 if (dummy != res->sr_slot->slot_nr) {
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005873 dprintk("%s Invalid slot id\n", __func__);
5874 goto out_err;
5875 }
Trond Myklebustda0507b2012-11-20 18:10:30 -05005876 /* highest slot id */
5877 res->sr_highest_slotid = be32_to_cpup(p++);
Trond Myklebust464ee9f2012-11-20 12:49:27 -05005878 /* target highest slot id */
5879 res->sr_target_highest_slotid = be32_to_cpup(p++);
Alexandros Batsakis0629e372009-12-05 13:46:14 -05005880 /* result flags */
5881 res->sr_status_flags = be32_to_cpup(p);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005882 status = 0;
5883out_err:
5884 res->sr_status = status;
5885 return status;
Benny Halevyc0eae662009-08-14 17:20:14 +03005886out_overflow:
5887 print_overflow_msg(__func__, xdr);
5888 status = -EIO;
5889 goto out_err;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005890#else /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005891 return 0;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005892#endif /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005893}
5894
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005895#if defined(CONFIG_NFS_V4_1)
Trond Myklebust93b717f2016-05-16 17:42:43 -04005896static int decode_layout_stateid(struct xdr_stream *xdr, nfs4_stateid *stateid)
5897{
5898 stateid->type = NFS4_LAYOUT_STATEID_TYPE;
5899 return decode_stateid(xdr, stateid);
5900}
5901
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005902static int decode_getdeviceinfo(struct xdr_stream *xdr,
Trond Myklebust4e590802015-03-09 14:01:25 -04005903 struct nfs4_getdeviceinfo_res *res)
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005904{
Trond Myklebust4e590802015-03-09 14:01:25 -04005905 struct pnfs_device *pdev = res->pdev;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005906 __be32 *p;
5907 uint32_t len, type;
5908 int status;
5909
5910 status = decode_op_hdr(xdr, OP_GETDEVICEINFO);
5911 if (status) {
5912 if (status == -ETOOSMALL) {
5913 p = xdr_inline_decode(xdr, 4);
5914 if (unlikely(!p))
5915 goto out_overflow;
5916 pdev->mincount = be32_to_cpup(p);
5917 dprintk("%s: Min count too small. mincnt = %u\n",
5918 __func__, pdev->mincount);
5919 }
5920 return status;
5921 }
5922
5923 p = xdr_inline_decode(xdr, 8);
5924 if (unlikely(!p))
5925 goto out_overflow;
5926 type = be32_to_cpup(p++);
5927 if (type != pdev->layout_type) {
5928 dprintk("%s: layout mismatch req: %u pdev: %u\n",
5929 __func__, pdev->layout_type, type);
5930 return -EINVAL;
5931 }
5932 /*
5933 * Get the length of the opaque device_addr4. xdr_read_pages places
5934 * the opaque device_addr4 in the xdr_buf->pages (pnfs_device->pages)
5935 * and places the remaining xdr data in xdr_buf->tail
5936 */
5937 pdev->mincount = be32_to_cpup(p);
Trond Myklebust13fe4ba2012-08-01 14:21:12 -04005938 if (xdr_read_pages(xdr, pdev->mincount) != pdev->mincount)
5939 goto out_overflow;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005940
5941 /* Parse notification bitmap, verifying that it is zero. */
5942 p = xdr_inline_decode(xdr, 4);
5943 if (unlikely(!p))
5944 goto out_overflow;
5945 len = be32_to_cpup(p);
5946 if (len) {
Chuck Leveread00592010-12-14 14:58:21 +00005947 uint32_t i;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005948
5949 p = xdr_inline_decode(xdr, 4 * len);
5950 if (unlikely(!p))
5951 goto out_overflow;
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07005952
Trond Myklebust4e590802015-03-09 14:01:25 -04005953 res->notification = be32_to_cpup(p++);
Christoph Hellwig84c9dee2014-09-10 17:37:28 -07005954 for (i = 1; i < len; i++) {
5955 if (be32_to_cpup(p++)) {
5956 dprintk("%s: unsupported notification\n",
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005957 __func__);
5958 return -EIO;
5959 }
5960 }
5961 }
5962 return 0;
5963out_overflow:
5964 print_overflow_msg(__func__, xdr);
5965 return -EIO;
5966}
5967
5968static int decode_layoutget(struct xdr_stream *xdr, struct rpc_rqst *req,
5969 struct nfs4_layoutget_res *res)
5970{
5971 __be32 *p;
5972 int status;
5973 u32 layout_count;
Trond Myklebust64bd5772012-06-20 22:35:05 -04005974 u32 recvd;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005975
5976 status = decode_op_hdr(xdr, OP_LAYOUTGET);
5977 if (status)
5978 return status;
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005979 p = xdr_inline_decode(xdr, 4);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005980 if (unlikely(!p))
5981 goto out_overflow;
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005982 res->return_on_close = be32_to_cpup(p);
Trond Myklebust93b717f2016-05-16 17:42:43 -04005983 decode_layout_stateid(xdr, &res->stateid);
Trond Myklebustea9d23f2012-03-04 18:13:56 -05005984 p = xdr_inline_decode(xdr, 4);
5985 if (unlikely(!p))
5986 goto out_overflow;
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005987 layout_count = be32_to_cpup(p);
5988 if (!layout_count) {
5989 dprintk("%s: server responded with empty layout array\n",
5990 __func__);
5991 return -EINVAL;
5992 }
5993
Weston Andros Adamson35124a02011-03-24 16:48:21 -04005994 p = xdr_inline_decode(xdr, 28);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04005995 if (unlikely(!p))
5996 goto out_overflow;
5997 p = xdr_decode_hyper(p, &res->range.offset);
5998 p = xdr_decode_hyper(p, &res->range.length);
5999 res->range.iomode = be32_to_cpup(p++);
6000 res->type = be32_to_cpup(p++);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04006001 res->layoutp->len = be32_to_cpup(p);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04006002
6003 dprintk("%s roff:%lu rlen:%lu riomode:%d, lo_type:0x%x, lo.len:%d\n",
6004 __func__,
6005 (unsigned long)res->range.offset,
6006 (unsigned long)res->range.length,
6007 res->range.iomode,
6008 res->type,
Weston Andros Adamson35124a02011-03-24 16:48:21 -04006009 res->layoutp->len);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04006010
Trond Myklebust64bd5772012-06-20 22:35:05 -04006011 recvd = xdr_read_pages(xdr, res->layoutp->len);
Weston Andros Adamson35124a02011-03-24 16:48:21 -04006012 if (res->layoutp->len > recvd) {
6013 dprintk("NFS: server cheating in layoutget reply: "
6014 "layout len %u > recvd %u\n",
6015 res->layoutp->len, recvd);
6016 return -EINVAL;
6017 }
6018
Andy Adamsonb1f69b72010-10-20 00:18:03 -04006019 if (layout_count > 1) {
6020 /* We only handle a length one array at the moment. Any
6021 * further entries are just ignored. Note that this means
6022 * the client may see a response that is less than the
6023 * minimum it requested.
6024 */
6025 dprintk("%s: server responded with %d layouts, dropping tail\n",
6026 __func__, layout_count);
6027 }
6028
6029 return 0;
6030out_overflow:
6031 print_overflow_msg(__func__, xdr);
6032 return -EIO;
6033}
Andy Adamson863a3c62011-03-23 13:27:54 +00006034
Benny Halevycbe82602011-05-22 19:52:37 +03006035static int decode_layoutreturn(struct xdr_stream *xdr,
6036 struct nfs4_layoutreturn_res *res)
6037{
6038 __be32 *p;
6039 int status;
6040
6041 status = decode_op_hdr(xdr, OP_LAYOUTRETURN);
6042 if (status)
6043 return status;
6044 p = xdr_inline_decode(xdr, 4);
6045 if (unlikely(!p))
6046 goto out_overflow;
6047 res->lrs_present = be32_to_cpup(p);
6048 if (res->lrs_present)
Trond Myklebust93b717f2016-05-16 17:42:43 -04006049 status = decode_layout_stateid(xdr, &res->stateid);
Benny Halevycbe82602011-05-22 19:52:37 +03006050 return status;
6051out_overflow:
6052 print_overflow_msg(__func__, xdr);
6053 return -EIO;
6054}
6055
Andy Adamson863a3c62011-03-23 13:27:54 +00006056static int decode_layoutcommit(struct xdr_stream *xdr,
6057 struct rpc_rqst *req,
6058 struct nfs4_layoutcommit_res *res)
6059{
6060 __be32 *p;
6061 __u32 sizechanged;
6062 int status;
6063
6064 status = decode_op_hdr(xdr, OP_LAYOUTCOMMIT);
Andy Adamsondb29c082011-07-30 20:52:38 -04006065 res->status = status;
Andy Adamson863a3c62011-03-23 13:27:54 +00006066 if (status)
6067 return status;
6068
6069 p = xdr_inline_decode(xdr, 4);
6070 if (unlikely(!p))
6071 goto out_overflow;
6072 sizechanged = be32_to_cpup(p);
6073
6074 if (sizechanged) {
6075 /* throw away new size */
6076 p = xdr_inline_decode(xdr, 8);
6077 if (unlikely(!p))
6078 goto out_overflow;
6079 }
6080 return 0;
6081out_overflow:
6082 print_overflow_msg(__func__, xdr);
6083 return -EIO;
6084}
Bryan Schumaker7d974792011-06-02 14:59:08 -04006085
6086static int decode_test_stateid(struct xdr_stream *xdr,
6087 struct nfs41_test_stateid_res *res)
6088{
6089 __be32 *p;
6090 int status;
6091 int num_res;
6092
6093 status = decode_op_hdr(xdr, OP_TEST_STATEID);
6094 if (status)
6095 return status;
6096
6097 p = xdr_inline_decode(xdr, 4);
6098 if (unlikely(!p))
6099 goto out_overflow;
6100 num_res = be32_to_cpup(p++);
6101 if (num_res != 1)
6102 goto out;
6103
6104 p = xdr_inline_decode(xdr, 4);
6105 if (unlikely(!p))
6106 goto out_overflow;
6107 res->status = be32_to_cpup(p++);
Bryan Schumaker1cab0652012-01-31 10:39:29 -05006108
6109 return status;
Bryan Schumaker7d974792011-06-02 14:59:08 -04006110out_overflow:
6111 print_overflow_msg(__func__, xdr);
6112out:
6113 return -EIO;
6114}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006115
6116static int decode_free_stateid(struct xdr_stream *xdr,
6117 struct nfs41_free_stateid_res *res)
6118{
Andy Adamson9f79fb42013-09-10 12:56:29 -04006119 res->status = decode_op_hdr(xdr, OP_FREE_STATEID);
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006120 return res->status;
Bryan Schumaker9aeda352011-06-02 14:59:09 -04006121}
Trond Myklebustcf805162016-11-15 14:56:07 -05006122#else
6123static inline
6124int decode_layoutreturn(struct xdr_stream *xdr,
6125 struct nfs4_layoutreturn_res *res)
6126{
6127 return 0;
6128}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04006129#endif /* CONFIG_NFS_V4_1 */
6130
Linus Torvalds1da177e2005-04-16 15:20:36 -07006131/*
Benny Halevy49c25592008-12-23 16:06:16 -05006132 * END OF "GENERIC" DECODE ROUTINES.
6133 */
6134
6135/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006136 * Decode OPEN_DOWNGRADE response
6137 */
Chuck Leverbf269552010-12-14 14:59:29 +00006138static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp,
6139 struct xdr_stream *xdr,
6140 struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006141{
Andy Adamson05d564f2008-12-23 16:06:15 -05006142 struct compound_hdr hdr;
6143 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006144
Chuck Leverbf269552010-12-14 14:59:29 +00006145 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006146 if (status)
6147 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006148 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006149 if (status)
6150 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006151 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006152 if (status)
6153 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006154 status = decode_open_downgrade(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006155out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006156 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006157}
6158
6159/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006160 * Decode ACCESS response
6161 */
Chuck Leverbf269552010-12-14 14:59:29 +00006162static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6163 struct nfs4_accessres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006164{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006165 struct compound_hdr hdr;
6166 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006167
Chuck Leverbf269552010-12-14 14:59:29 +00006168 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006169 if (status)
6170 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006171 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006172 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006173 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006174 status = decode_putfh(xdr);
Trond Myklebust76b32992007-08-10 17:45:11 -04006175 if (status != 0)
6176 goto out;
Weston Andros Adamson6168f622012-09-10 14:00:46 -04006177 status = decode_access(xdr, &res->supported, &res->access);
Trond Myklebust76b32992007-08-10 17:45:11 -04006178 if (status != 0)
6179 goto out;
Trond Myklebust6926afd2012-01-07 13:22:46 -05006180 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006181out:
6182 return status;
6183}
6184
6185/*
6186 * Decode LOOKUP response
6187 */
Chuck Leverbf269552010-12-14 14:59:29 +00006188static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6189 struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006190{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006191 struct compound_hdr hdr;
6192 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006193
Chuck Leverbf269552010-12-14 14:59:29 +00006194 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006195 if (status)
6196 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006197 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006198 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006199 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006200 status = decode_putfh(xdr);
6201 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006202 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006203 status = decode_lookup(xdr);
6204 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006205 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006206 status = decode_getfh(xdr, res->fh);
6207 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006208 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006209 status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006210out:
6211 return status;
6212}
6213
6214/*
6215 * Decode LOOKUP_ROOT response
6216 */
Chuck Leverbf269552010-12-14 14:59:29 +00006217static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp,
6218 struct xdr_stream *xdr,
6219 struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006220{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006221 struct compound_hdr hdr;
6222 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006223
Chuck Leverbf269552010-12-14 14:59:29 +00006224 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006225 if (status)
6226 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006227 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006228 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006229 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006230 status = decode_putrootfh(xdr);
6231 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006232 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006233 status = decode_getfh(xdr, res->fh);
6234 if (status == 0)
David Quigleyaa9c2662013-05-22 12:50:44 -04006235 status = decode_getfattr_label(xdr, res->fattr,
6236 res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006237out:
6238 return status;
6239}
6240
6241/*
6242 * Decode REMOVE response
6243 */
Chuck Leverbf269552010-12-14 14:59:29 +00006244static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6245 struct nfs_removeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006246{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006247 struct compound_hdr hdr;
6248 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006249
Chuck Leverbf269552010-12-14 14:59:29 +00006250 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006251 if (status)
6252 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006253 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006254 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006255 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006256 status = decode_putfh(xdr);
6257 if (status)
Trond Myklebust16e42952005-10-27 22:12:44 -04006258 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006259 status = decode_remove(xdr, &res->cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006260out:
6261 return status;
6262}
6263
6264/*
6265 * Decode RENAME response
6266 */
Chuck Leverbf269552010-12-14 14:59:29 +00006267static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6268 struct nfs_renameres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006269{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006270 struct compound_hdr hdr;
6271 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006272
Chuck Leverbf269552010-12-14 14:59:29 +00006273 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006274 if (status)
6275 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006276 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006277 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006278 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006279 status = decode_putfh(xdr);
6280 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006281 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006282 status = decode_savefh(xdr);
6283 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006284 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006285 status = decode_putfh(xdr);
6286 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006287 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006288 status = decode_rename(xdr, &res->old_cinfo, &res->new_cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006289out:
6290 return status;
6291}
6292
6293/*
6294 * Decode LINK response
6295 */
Chuck Leverbf269552010-12-14 14:59:29 +00006296static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6297 struct nfs4_link_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006298{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006299 struct compound_hdr hdr;
6300 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006301
Chuck Leverbf269552010-12-14 14:59:29 +00006302 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006303 if (status)
6304 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006305 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006306 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006307 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006308 status = decode_putfh(xdr);
6309 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006310 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006311 status = decode_savefh(xdr);
6312 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006313 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006314 status = decode_putfh(xdr);
6315 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006316 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006317 status = decode_link(xdr, &res->cinfo);
6318 if (status)
Trond Myklebust91ba2ee2005-10-27 22:12:42 -04006319 goto out;
6320 /*
6321 * Note order: OP_LINK leaves the directory as the current
6322 * filehandle.
6323 */
Chuck Leverbf269552010-12-14 14:59:29 +00006324 status = decode_restorefh(xdr);
6325 if (status)
Trond Myklebust91ba2ee2005-10-27 22:12:42 -04006326 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006327 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006328out:
6329 return status;
6330}
6331
6332/*
6333 * Decode CREATE response
6334 */
Chuck Leverbf269552010-12-14 14:59:29 +00006335static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6336 struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006337{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006338 struct compound_hdr hdr;
6339 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006340
Chuck Leverbf269552010-12-14 14:59:29 +00006341 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006342 if (status)
6343 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006344 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006345 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006346 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006347 status = decode_putfh(xdr);
6348 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006349 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006350 status = decode_create(xdr, &res->dir_cinfo);
6351 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006352 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006353 status = decode_getfh(xdr, res->fh);
6354 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006355 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006356 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006357out:
6358 return status;
6359}
6360
6361/*
6362 * Decode SYMLINK response
6363 */
Chuck Leverbf269552010-12-14 14:59:29 +00006364static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6365 struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006366{
Chuck Leverbf269552010-12-14 14:59:29 +00006367 return nfs4_xdr_dec_create(rqstp, xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006368}
6369
6370/*
6371 * Decode GETATTR response
6372 */
Chuck Leverbf269552010-12-14 14:59:29 +00006373static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6374 struct nfs4_getattr_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006375{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006376 struct compound_hdr hdr;
6377 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05006378
Chuck Leverbf269552010-12-14 14:59:29 +00006379 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006380 if (status)
6381 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006382 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006383 if (status)
6384 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006385 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006386 if (status)
6387 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006388 status = decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006389out:
6390 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006391}
6392
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006393/*
6394 * Encode an SETACL request
6395 */
Chuck Lever9f06c712010-12-14 14:59:18 +00006396static void nfs4_xdr_enc_setacl(struct rpc_rqst *req, struct xdr_stream *xdr,
6397 struct nfs_setaclargs *args)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006398{
Andy Adamson05d564f2008-12-23 16:06:15 -05006399 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04006400 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05006401 };
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006402
Chuck Lever9f06c712010-12-14 14:59:18 +00006403 encode_compound_hdr(xdr, req, &hdr);
6404 encode_sequence(xdr, &args->seq_args, &hdr);
6405 encode_putfh(xdr, args->fh, &hdr);
6406 encode_setacl(xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05006407 encode_nops(&hdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006408}
Andy Adamson05d564f2008-12-23 16:06:15 -05006409
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006410/*
6411 * Decode SETACL response
6412 */
6413static int
Chuck Leverbf269552010-12-14 14:59:29 +00006414nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Benny Halevy73c403a2009-04-01 09:22:01 -04006415 struct nfs_setaclres *res)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006416{
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006417 struct compound_hdr hdr;
6418 int status;
6419
Chuck Leverbf269552010-12-14 14:59:29 +00006420 status = decode_compound_hdr(xdr, &hdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006421 if (status)
6422 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006423 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006424 if (status)
6425 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006426 status = decode_putfh(xdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006427 if (status)
6428 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006429 status = decode_setattr(xdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00006430out:
6431 return status;
6432}
Linus Torvalds1da177e2005-04-16 15:20:36 -07006433
6434/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00006435 * Decode GETACL response
6436 */
6437static int
Chuck Leverbf269552010-12-14 14:59:29 +00006438nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Benny Halevy663c79b2009-04-01 09:21:59 -04006439 struct nfs_getaclres *res)
J. Bruce Fields029d1052005-06-22 17:16:22 +00006440{
J. Bruce Fields029d1052005-06-22 17:16:22 +00006441 struct compound_hdr hdr;
6442 int status;
6443
Trond Myklebust331818f2012-02-03 18:30:53 -05006444 if (res->acl_scratch != NULL) {
6445 void *p = page_address(res->acl_scratch);
6446 xdr_set_scratch_buffer(xdr, p, PAGE_SIZE);
6447 }
Chuck Leverbf269552010-12-14 14:59:29 +00006448 status = decode_compound_hdr(xdr, &hdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006449 if (status)
6450 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006451 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006452 if (status)
6453 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006454 status = decode_putfh(xdr);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006455 if (status)
6456 goto out;
Andy Adamsonbf118a32011-12-07 11:55:27 -05006457 status = decode_getacl(xdr, rqstp, res);
J. Bruce Fields029d1052005-06-22 17:16:22 +00006458
6459out:
6460 return status;
6461}
6462
6463/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07006464 * Decode CLOSE response
6465 */
Chuck Leverbf269552010-12-14 14:59:29 +00006466static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6467 struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006468{
Andy Adamson05d564f2008-12-23 16:06:15 -05006469 struct compound_hdr hdr;
6470 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006471
Chuck Leverbf269552010-12-14 14:59:29 +00006472 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006473 if (status)
6474 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006475 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006476 if (status)
6477 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006478 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006479 if (status)
6480 goto out;
Trond Myklebustcf805162016-11-15 14:56:07 -05006481 if (res->lr_res) {
6482 status = decode_layoutreturn(xdr, res->lr_res);
6483 res->lr_ret = status;
6484 if (status)
6485 goto out;
6486 }
Chuck Leverbf269552010-12-14 14:59:29 +00006487 status = decode_close(xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04006488 if (status != 0)
6489 goto out;
6490 /*
6491 * Note: Server may do delete on close for this file
6492 * in which case the getattr call will fail with
6493 * an ESTALE error. Shouldn't be a problem,
6494 * though, since fattr->valid will remain unset.
6495 */
Trond Myklebust6926afd2012-01-07 13:22:46 -05006496 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006497out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006498 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006499}
6500
6501/*
6502 * Decode OPEN response
6503 */
Chuck Leverbf269552010-12-14 14:59:29 +00006504static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6505 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006506{
Andy Adamson05d564f2008-12-23 16:06:15 -05006507 struct compound_hdr hdr;
6508 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006509
Chuck Leverbf269552010-12-14 14:59:29 +00006510 status = decode_compound_hdr(xdr, &hdr);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04006511 if (status)
6512 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006513 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006514 if (status)
6515 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006516 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006517 if (status)
6518 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006519 status = decode_open(xdr, res);
Andy Adamson05d564f2008-12-23 16:06:15 -05006520 if (status)
6521 goto out;
Weston Andros Adamson01913b42012-09-06 15:54:27 -04006522 status = decode_getfh(xdr, &res->fh);
6523 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006524 goto out;
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07006525 if (res->access_request)
6526 decode_access(xdr, &res->access_supported, &res->access_result);
David Quigleyaa9c2662013-05-22 12:50:44 -04006527 decode_getfattr_label(xdr, res->f_attr, res->f_label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006528out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006529 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006530}
6531
6532/*
6533 * Decode OPEN_CONFIRM response
6534 */
Chuck Leverbf269552010-12-14 14:59:29 +00006535static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp,
6536 struct xdr_stream *xdr,
6537 struct nfs_open_confirmres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006538{
Andy Adamson05d564f2008-12-23 16:06:15 -05006539 struct compound_hdr hdr;
6540 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006541
Chuck Leverbf269552010-12-14 14:59:29 +00006542 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006543 if (status)
6544 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006545 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006546 if (status)
6547 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006548 status = decode_open_confirm(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006549out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006550 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006551}
6552
6553/*
6554 * Decode OPEN response
6555 */
Chuck Leverbf269552010-12-14 14:59:29 +00006556static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp,
6557 struct xdr_stream *xdr,
6558 struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006559{
Andy Adamson05d564f2008-12-23 16:06:15 -05006560 struct compound_hdr hdr;
6561 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006562
Chuck Leverbf269552010-12-14 14:59:29 +00006563 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006564 if (status)
6565 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006566 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006567 if (status)
6568 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006569 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006570 if (status)
6571 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006572 status = decode_open(xdr, res);
Andy Adamson05d564f2008-12-23 16:06:15 -05006573 if (status)
6574 goto out;
Weston Andros Adamsonae2bb032012-10-02 14:49:52 -07006575 if (res->access_request)
6576 decode_access(xdr, &res->access_supported, &res->access_result);
Trond Myklebust6926afd2012-01-07 13:22:46 -05006577 decode_getfattr(xdr, res->f_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006578out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006579 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006580}
6581
6582/*
6583 * Decode SETATTR response
6584 */
Chuck Leverbf269552010-12-14 14:59:29 +00006585static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp,
6586 struct xdr_stream *xdr,
6587 struct nfs_setattrres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006588{
Andy Adamson05d564f2008-12-23 16:06:15 -05006589 struct compound_hdr hdr;
6590 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006591
Chuck Leverbf269552010-12-14 14:59:29 +00006592 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006593 if (status)
6594 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006595 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006596 if (status)
6597 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006598 status = decode_putfh(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006599 if (status)
6600 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006601 status = decode_setattr(xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05006602 if (status)
6603 goto out;
David Quigleyaa9c2662013-05-22 12:50:44 -04006604 decode_getfattr_label(xdr, res->fattr, res->label, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006605out:
Andy Adamson05d564f2008-12-23 16:06:15 -05006606 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006607}
6608
6609/*
6610 * Decode LOCK response
6611 */
Chuck Leverbf269552010-12-14 14:59:29 +00006612static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6613 struct nfs_lock_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_lock(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006628out:
6629 return status;
6630}
6631
6632/*
6633 * Decode LOCKT response
6634 */
Chuck Leverbf269552010-12-14 14:59:29 +00006635static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6636 struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006637{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006638 struct compound_hdr hdr;
6639 int status;
6640
Chuck Leverbf269552010-12-14 14:59:29 +00006641 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006642 if (status)
6643 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006644 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006645 if (status)
6646 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006647 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006648 if (status)
6649 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006650 status = decode_lockt(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006651out:
6652 return status;
6653}
6654
6655/*
6656 * Decode LOCKU response
6657 */
Chuck Leverbf269552010-12-14 14:59:29 +00006658static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6659 struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006660{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006661 struct compound_hdr hdr;
6662 int status;
6663
Chuck Leverbf269552010-12-14 14:59:29 +00006664 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006665 if (status)
6666 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006667 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006668 if (status)
6669 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006670 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006671 if (status)
6672 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006673 status = decode_locku(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006674out:
6675 return status;
6676}
6677
Chuck Leverbf269552010-12-14 14:59:29 +00006678static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp,
6679 struct xdr_stream *xdr, void *dummy)
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006680{
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006681 struct compound_hdr hdr;
6682 int status;
6683
Chuck Leverbf269552010-12-14 14:59:29 +00006684 status = decode_compound_hdr(xdr, &hdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006685 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006686 status = decode_release_lockowner(xdr);
Trond Myklebustd3c7b7c2010-07-01 12:49:01 -04006687 return status;
6688}
6689
Linus Torvalds1da177e2005-04-16 15:20:36 -07006690/*
6691 * Decode READLINK response
6692 */
Chuck Leverbf269552010-12-14 14:59:29 +00006693static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp,
6694 struct xdr_stream *xdr,
Benny Halevyf50c7002009-04-01 09:21:55 -04006695 struct nfs4_readlink_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);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006701 if (status)
6702 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006703 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006704 if (status)
6705 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006706 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006707 if (status)
6708 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006709 status = decode_readlink(xdr, rqstp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006710out:
6711 return status;
6712}
6713
6714/*
6715 * Decode READDIR response
6716 */
Chuck Leverbf269552010-12-14 14:59:29 +00006717static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6718 struct nfs4_readdir_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006719{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006720 struct compound_hdr hdr;
6721 int status;
6722
Chuck Leverbf269552010-12-14 14:59:29 +00006723 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006724 if (status)
6725 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006726 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006727 if (status)
6728 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006729 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006730 if (status)
6731 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006732 status = decode_readdir(xdr, rqstp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006733out:
6734 return status;
6735}
6736
6737/*
6738 * Decode Read response
6739 */
Chuck Leverbf269552010-12-14 14:59:29 +00006740static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Anna Schumaker9137bdf2014-05-06 09:12:25 -04006741 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006742{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006743 struct compound_hdr hdr;
6744 int status;
6745
Chuck Leverbf269552010-12-14 14:59:29 +00006746 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006747 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006748 if (status)
6749 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006750 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006751 if (status)
6752 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006753 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006754 if (status)
6755 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006756 status = decode_read(xdr, rqstp, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006757 if (!status)
6758 status = res->count;
6759out:
6760 return status;
6761}
6762
6763/*
6764 * Decode WRITE response
6765 */
Chuck Leverbf269552010-12-14 14:59:29 +00006766static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Anna Schumaker9137bdf2014-05-06 09:12:25 -04006767 struct nfs_pgio_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006768{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006769 struct compound_hdr hdr;
6770 int status;
6771
Chuck Leverbf269552010-12-14 14:59:29 +00006772 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006773 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006774 if (status)
6775 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006776 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006777 if (status)
6778 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006779 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006780 if (status)
6781 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006782 status = decode_write(xdr, res);
Trond Myklebust4f9838c2005-10-27 22:12:44 -04006783 if (status)
6784 goto out;
Fred Isaman7ffd1062011-03-03 15:13:46 +00006785 if (res->fattr)
Trond Myklebust6926afd2012-01-07 13:22:46 -05006786 decode_getfattr(xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006787 if (!status)
6788 status = res->count;
6789out:
6790 return status;
6791}
6792
6793/*
6794 * Decode COMMIT response
6795 */
Chuck Leverbf269552010-12-14 14:59:29 +00006796static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
Fred Isaman0b7c0152012-04-20 14:47:39 -04006797 struct nfs_commitres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006798{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006799 struct compound_hdr hdr;
6800 int status;
6801
Chuck Leverbf269552010-12-14 14:59:29 +00006802 status = decode_compound_hdr(xdr, &hdr);
Peng Taoaabff4d2014-08-27 10:47:14 +08006803 res->op_status = hdr.status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07006804 if (status)
6805 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006806 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006807 if (status)
6808 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006809 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006810 if (status)
6811 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006812 status = decode_commit(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006813out:
6814 return status;
6815}
6816
6817/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006818 * Decode FSINFO response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006819 */
Chuck Leverbf269552010-12-14 14:59:29 +00006820static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevy3dda5e42009-04-01 09:21:57 -04006821 struct nfs4_fsinfo_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006822{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006823 struct compound_hdr hdr;
6824 int status;
6825
Chuck Leverbf269552010-12-14 14:59:29 +00006826 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006827 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006828 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006829 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006830 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006831 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006832 status = decode_fsinfo(xdr, res->fsinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006833 return status;
6834}
6835
6836/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006837 * Decode PATHCONF response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006838 */
Chuck Leverbf269552010-12-14 14:59:29 +00006839static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevyd45b2982009-04-01 09:21:58 -04006840 struct nfs4_pathconf_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006841{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006842 struct compound_hdr hdr;
6843 int status;
6844
Chuck Leverbf269552010-12-14 14:59:29 +00006845 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006846 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006847 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006848 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006849 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006850 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006851 status = decode_pathconf(xdr, res->pathconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006852 return status;
6853}
6854
6855/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006856 * Decode STATFS response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006857 */
Chuck Leverbf269552010-12-14 14:59:29 +00006858static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, struct xdr_stream *xdr,
Benny Halevy24ad1482009-04-01 09:21:56 -04006859 struct nfs4_statfs_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006860{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006861 struct compound_hdr hdr;
6862 int status;
6863
Chuck Leverbf269552010-12-14 14:59:29 +00006864 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006865 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006866 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006867 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006868 status = decode_putfh(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006869 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006870 status = decode_statfs(xdr, res->fsstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006871 return status;
6872}
6873
6874/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006875 * Decode GETATTR_BITMAP response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006876 */
Chuck Leverbf269552010-12-14 14:59:29 +00006877static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req,
6878 struct xdr_stream *xdr,
6879 struct nfs4_server_caps_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006880{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006881 struct compound_hdr hdr;
6882 int status;
6883
Chuck Leverbf269552010-12-14 14:59:29 +00006884 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006885 if (status)
6886 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006887 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006888 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006889 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006890 status = decode_putfh(xdr);
6891 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006892 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006893 status = decode_server_caps(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006894out:
6895 return status;
6896}
6897
6898/*
6899 * Decode RENEW response
6900 */
Chuck Leverbf269552010-12-14 14:59:29 +00006901static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
6902 void *__unused)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006903{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006904 struct compound_hdr hdr;
6905 int status;
6906
Chuck Leverbf269552010-12-14 14:59:29 +00006907 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006908 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006909 status = decode_renew(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006910 return status;
6911}
6912
6913/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006914 * Decode SETCLIENTID response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006915 */
Chuck Leverbf269552010-12-14 14:59:29 +00006916static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req,
6917 struct xdr_stream *xdr,
6918 struct nfs4_setclientid_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006919{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006920 struct compound_hdr hdr;
6921 int status;
6922
Chuck Leverbf269552010-12-14 14:59:29 +00006923 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006924 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006925 status = decode_setclientid(xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006926 return status;
6927}
6928
6929/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006930 * Decode SETCLIENTID_CONFIRM response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006931 */
Chuck Leverbf269552010-12-14 14:59:29 +00006932static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req,
Chuck Lever83ca7f52013-03-16 15:55:53 -04006933 struct xdr_stream *xdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006934{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006935 struct compound_hdr hdr;
6936 int status;
6937
Chuck Leverbf269552010-12-14 14:59:29 +00006938 status = decode_compound_hdr(xdr, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006939 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00006940 status = decode_setclientid_confirm(xdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07006941 return status;
6942}
6943
6944/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006945 * Decode DELEGRETURN response
Linus Torvalds1da177e2005-04-16 15:20:36 -07006946 */
Chuck Leverbf269552010-12-14 14:59:29 +00006947static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp,
6948 struct xdr_stream *xdr,
6949 struct nfs4_delegreturnres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07006950{
Linus Torvalds1da177e2005-04-16 15:20:36 -07006951 struct compound_hdr hdr;
6952 int status;
6953
Chuck Leverbf269552010-12-14 14:59:29 +00006954 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006955 if (status)
6956 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006957 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006958 if (status)
Trond Myklebustfa178f22006-01-03 09:55:38 +01006959 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006960 status = decode_putfh(xdr);
Trond Myklebustfa178f22006-01-03 09:55:38 +01006961 if (status != 0)
6962 goto out;
Trond Myklebust586f1c32016-11-15 15:03:33 -05006963 if (res->lr_res) {
6964 status = decode_layoutreturn(xdr, res->lr_res);
6965 res->lr_ret = status;
6966 if (status)
6967 goto out;
6968 }
Trond Myklebuste144cbc2012-04-28 16:05:03 -04006969 status = decode_getfattr(xdr, res->fattr, res->server);
Jeff Layton556ae3b2010-03-21 12:10:36 -04006970 if (status != 0)
6971 goto out;
Trond Myklebuste144cbc2012-04-28 16:05:03 -04006972 status = decode_delegreturn(xdr);
Trond Myklebustfa178f22006-01-03 09:55:38 +01006973out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07006974 return status;
6975}
6976
Trond Myklebust683b57b2006-06-09 09:34:22 -04006977/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05006978 * Decode FS_LOCATIONS response
Trond Myklebust683b57b2006-06-09 09:34:22 -04006979 */
Chuck Leverbf269552010-12-14 14:59:29 +00006980static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req,
6981 struct xdr_stream *xdr,
Benny Halevy22958462009-04-01 09:22:02 -04006982 struct nfs4_fs_locations_res *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006983{
Trond Myklebust683b57b2006-06-09 09:34:22 -04006984 struct compound_hdr hdr;
6985 int status;
6986
Chuck Leverbf269552010-12-14 14:59:29 +00006987 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006988 if (status)
6989 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006990 status = decode_sequence(xdr, &res->seq_res, req);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04006991 if (status)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006992 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00006993 status = decode_putfh(xdr);
6994 if (status)
Trond Myklebust683b57b2006-06-09 09:34:22 -04006995 goto out;
Chuck Leverb03d7352013-10-17 14:12:50 -04006996 if (res->migration) {
6997 xdr_enter_page(xdr, PAGE_SIZE);
6998 status = decode_getfattr_generic(xdr,
6999 &res->fs_locations->fattr,
Trond Myklebust8b7e3f42012-01-30 15:43:56 -05007000 NULL, res->fs_locations,
David Quigleyaa9c2662013-05-22 12:50:44 -04007001 NULL, res->fs_locations->server);
Chuck Leverb03d7352013-10-17 14:12:50 -04007002 if (status)
7003 goto out;
7004 if (res->renew)
7005 status = decode_renew(xdr);
7006 } else {
7007 status = decode_lookup(xdr);
7008 if (status)
7009 goto out;
7010 xdr_enter_page(xdr, PAGE_SIZE);
7011 status = decode_getfattr_generic(xdr,
7012 &res->fs_locations->fattr,
7013 NULL, res->fs_locations,
7014 NULL, res->fs_locations->server);
7015 }
Trond Myklebust683b57b2006-06-09 09:34:22 -04007016out:
7017 return status;
7018}
7019
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00007020/*
7021 * Decode SECINFO response
7022 */
7023static int nfs4_xdr_dec_secinfo(struct rpc_rqst *rqstp,
7024 struct xdr_stream *xdr,
7025 struct nfs4_secinfo_res *res)
7026{
7027 struct compound_hdr hdr;
7028 int status;
7029
7030 status = decode_compound_hdr(xdr, &hdr);
7031 if (status)
7032 goto out;
7033 status = decode_sequence(xdr, &res->seq_res, rqstp);
7034 if (status)
7035 goto out;
7036 status = decode_putfh(xdr);
7037 if (status)
7038 goto out;
7039 status = decode_secinfo(xdr, res);
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00007040out:
7041 return status;
7042}
7043
Chuck Lever44c99932013-10-17 14:13:30 -04007044/*
7045 * Decode FSID_PRESENT response
7046 */
7047static int nfs4_xdr_dec_fsid_present(struct rpc_rqst *rqstp,
7048 struct xdr_stream *xdr,
7049 struct nfs4_fsid_present_res *res)
7050{
7051 struct compound_hdr hdr;
7052 int status;
7053
7054 status = decode_compound_hdr(xdr, &hdr);
7055 if (status)
7056 goto out;
7057 status = decode_sequence(xdr, &res->seq_res, rqstp);
7058 if (status)
7059 goto out;
7060 status = decode_putfh(xdr);
7061 if (status)
7062 goto out;
7063 status = decode_getfh(xdr, res->fh);
7064 if (status)
7065 goto out;
7066 if (res->renew)
7067 status = decode_renew(xdr);
7068out:
7069 return status;
7070}
7071
Benny Halevy99fe60d2009-04-01 09:22:29 -04007072#if defined(CONFIG_NFS_V4_1)
7073/*
Weston Andros Adamson7c44f1ae2012-05-24 13:22:50 -04007074 * Decode BIND_CONN_TO_SESSION response
7075 */
7076static int nfs4_xdr_dec_bind_conn_to_session(struct rpc_rqst *rqstp,
7077 struct xdr_stream *xdr,
7078 void *res)
7079{
7080 struct compound_hdr hdr;
7081 int status;
7082
7083 status = decode_compound_hdr(xdr, &hdr);
7084 if (!status)
7085 status = decode_bind_conn_to_session(xdr, res);
7086 return status;
7087}
7088
7089/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007090 * Decode EXCHANGE_ID response
Benny Halevy99fe60d2009-04-01 09:22:29 -04007091 */
Chuck Leverbf269552010-12-14 14:59:29 +00007092static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp,
7093 struct xdr_stream *xdr,
Benny Halevy99fe60d2009-04-01 09:22:29 -04007094 void *res)
7095{
Benny Halevy99fe60d2009-04-01 09:22:29 -04007096 struct compound_hdr hdr;
7097 int status;
7098
Chuck Leverbf269552010-12-14 14:59:29 +00007099 status = decode_compound_hdr(xdr, &hdr);
Benny Halevy99fe60d2009-04-01 09:22:29 -04007100 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007101 status = decode_exchange_id(xdr, res);
Benny Halevy99fe60d2009-04-01 09:22:29 -04007102 return status;
7103}
Andy Adamson2050f0c2009-04-01 09:22:30 -04007104
7105/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007106 * Decode CREATE_SESSION response
Andy Adamsonfc931582009-04-01 09:22:31 -04007107 */
Chuck Leverbf269552010-12-14 14:59:29 +00007108static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp,
7109 struct xdr_stream *xdr,
Andy Adamsonfc931582009-04-01 09:22:31 -04007110 struct nfs41_create_session_res *res)
7111{
Andy Adamsonfc931582009-04-01 09:22:31 -04007112 struct compound_hdr hdr;
7113 int status;
7114
Chuck Leverbf269552010-12-14 14:59:29 +00007115 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonfc931582009-04-01 09:22:31 -04007116 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007117 status = decode_create_session(xdr, res);
Andy Adamsonfc931582009-04-01 09:22:31 -04007118 return status;
7119}
7120
7121/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007122 * Decode DESTROY_SESSION response
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007123 */
Chuck Leverbf269552010-12-14 14:59:29 +00007124static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp,
7125 struct xdr_stream *xdr,
7126 void *res)
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007127{
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007128 struct compound_hdr hdr;
7129 int status;
7130
Chuck Leverbf269552010-12-14 14:59:29 +00007131 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007132 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007133 status = decode_destroy_session(xdr, res);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04007134 return status;
7135}
7136
7137/*
Trond Myklebust66245532012-05-25 17:18:09 -04007138 * Decode DESTROY_CLIENTID response
7139 */
7140static int nfs4_xdr_dec_destroy_clientid(struct rpc_rqst *rqstp,
7141 struct xdr_stream *xdr,
7142 void *res)
7143{
7144 struct compound_hdr hdr;
7145 int status;
7146
7147 status = decode_compound_hdr(xdr, &hdr);
7148 if (!status)
7149 status = decode_destroy_clientid(xdr, res);
7150 return status;
7151}
7152
7153/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007154 * Decode SEQUENCE response
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007155 */
Chuck Leverbf269552010-12-14 14:59:29 +00007156static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp,
7157 struct xdr_stream *xdr,
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007158 struct nfs4_sequence_res *res)
7159{
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007160 struct compound_hdr hdr;
7161 int status;
7162
Chuck Leverbf269552010-12-14 14:59:29 +00007163 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007164 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007165 status = decode_sequence(xdr, res, rqstp);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04007166 return status;
7167}
7168
7169/*
Ricardo Labiaga8b173212009-12-05 16:08:39 -05007170 * Decode GET_LEASE_TIME response
Andy Adamson2050f0c2009-04-01 09:22:30 -04007171 */
Chuck Leverbf269552010-12-14 14:59:29 +00007172static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp,
7173 struct xdr_stream *xdr,
Andy Adamson2050f0c2009-04-01 09:22:30 -04007174 struct nfs4_get_lease_time_res *res)
7175{
Andy Adamson2050f0c2009-04-01 09:22:30 -04007176 struct compound_hdr hdr;
7177 int status;
7178
Chuck Leverbf269552010-12-14 14:59:29 +00007179 status = decode_compound_hdr(xdr, &hdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007180 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007181 status = decode_sequence(xdr, &res->lr_seq_res, rqstp);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007182 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007183 status = decode_putrootfh(xdr);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007184 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007185 status = decode_fsinfo(xdr, res->lr_fsinfo);
Andy Adamson2050f0c2009-04-01 09:22:30 -04007186 return status;
7187}
Ricardo Labiaga180197532009-12-05 16:08:40 -05007188
7189/*
7190 * Decode RECLAIM_COMPLETE response
7191 */
Chuck Leverbf269552010-12-14 14:59:29 +00007192static int nfs4_xdr_dec_reclaim_complete(struct rpc_rqst *rqstp,
7193 struct xdr_stream *xdr,
Ricardo Labiaga180197532009-12-05 16:08:40 -05007194 struct nfs41_reclaim_complete_res *res)
7195{
Ricardo Labiaga180197532009-12-05 16:08:40 -05007196 struct compound_hdr hdr;
7197 int status;
7198
Chuck Leverbf269552010-12-14 14:59:29 +00007199 status = decode_compound_hdr(xdr, &hdr);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007200 if (!status)
Chuck Leverbf269552010-12-14 14:59:29 +00007201 status = decode_sequence(xdr, &res->seq_res, rqstp);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007202 if (!status)
Himangi Saraogi8ee2b782014-06-27 00:09:09 +05307203 status = decode_reclaim_complete(xdr, NULL);
Ricardo Labiaga180197532009-12-05 16:08:40 -05007204 return status;
7205}
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007206
7207/*
7208 * Decode GETDEVINFO response
7209 */
Chuck Leverbf269552010-12-14 14:59:29 +00007210static int nfs4_xdr_dec_getdeviceinfo(struct rpc_rqst *rqstp,
7211 struct xdr_stream *xdr,
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007212 struct nfs4_getdeviceinfo_res *res)
7213{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007214 struct compound_hdr hdr;
7215 int status;
7216
Chuck Leverbf269552010-12-14 14:59:29 +00007217 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007218 if (status != 0)
7219 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007220 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007221 if (status != 0)
7222 goto out;
Trond Myklebust4e590802015-03-09 14:01:25 -04007223 status = decode_getdeviceinfo(xdr, res);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007224out:
7225 return status;
7226}
7227
7228/*
7229 * Decode LAYOUTGET response
7230 */
Chuck Leverbf269552010-12-14 14:59:29 +00007231static int nfs4_xdr_dec_layoutget(struct rpc_rqst *rqstp,
7232 struct xdr_stream *xdr,
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007233 struct nfs4_layoutget_res *res)
7234{
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007235 struct compound_hdr hdr;
7236 int status;
7237
Chuck Leverbf269552010-12-14 14:59:29 +00007238 status = decode_compound_hdr(xdr, &hdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007239 if (status)
7240 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007241 status = decode_sequence(xdr, &res->seq_res, rqstp);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007242 if (status)
7243 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007244 status = decode_putfh(xdr);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007245 if (status)
7246 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +00007247 status = decode_layoutget(xdr, rqstp, res);
Andy Adamsonb1f69b72010-10-20 00:18:03 -04007248out:
7249 return status;
7250}
Andy Adamson863a3c62011-03-23 13:27:54 +00007251
7252/*
Benny Halevycbe82602011-05-22 19:52:37 +03007253 * Decode LAYOUTRETURN response
7254 */
7255static int nfs4_xdr_dec_layoutreturn(struct rpc_rqst *rqstp,
7256 struct xdr_stream *xdr,
7257 struct nfs4_layoutreturn_res *res)
7258{
7259 struct compound_hdr hdr;
7260 int status;
7261
7262 status = decode_compound_hdr(xdr, &hdr);
7263 if (status)
7264 goto out;
7265 status = decode_sequence(xdr, &res->seq_res, rqstp);
7266 if (status)
7267 goto out;
7268 status = decode_putfh(xdr);
7269 if (status)
7270 goto out;
7271 status = decode_layoutreturn(xdr, res);
7272out:
7273 return status;
7274}
7275
7276/*
Andy Adamson863a3c62011-03-23 13:27:54 +00007277 * Decode LAYOUTCOMMIT response
7278 */
7279static int nfs4_xdr_dec_layoutcommit(struct rpc_rqst *rqstp,
7280 struct xdr_stream *xdr,
7281 struct nfs4_layoutcommit_res *res)
7282{
7283 struct compound_hdr hdr;
7284 int status;
7285
7286 status = decode_compound_hdr(xdr, &hdr);
7287 if (status)
7288 goto out;
7289 status = decode_sequence(xdr, &res->seq_res, rqstp);
7290 if (status)
7291 goto out;
7292 status = decode_putfh(xdr);
7293 if (status)
7294 goto out;
7295 status = decode_layoutcommit(xdr, rqstp, res);
7296 if (status)
7297 goto out;
Trond Myklebust6926afd2012-01-07 13:22:46 -05007298 decode_getfattr(xdr, res->fattr, res->server);
Andy Adamson863a3c62011-03-23 13:27:54 +00007299out:
7300 return status;
7301}
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007302
7303/*
7304 * Decode SECINFO_NO_NAME response
7305 */
7306static int nfs4_xdr_dec_secinfo_no_name(struct rpc_rqst *rqstp,
7307 struct xdr_stream *xdr,
7308 struct nfs4_secinfo_res *res)
7309{
7310 struct compound_hdr hdr;
7311 int status;
7312
7313 status = decode_compound_hdr(xdr, &hdr);
7314 if (status)
7315 goto out;
7316 status = decode_sequence(xdr, &res->seq_res, rqstp);
7317 if (status)
7318 goto out;
7319 status = decode_putrootfh(xdr);
7320 if (status)
7321 goto out;
Bryan Schumaker31e4dda2012-04-27 13:27:38 -04007322 status = decode_secinfo_no_name(xdr, res);
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007323out:
7324 return status;
7325}
Bryan Schumaker7d974792011-06-02 14:59:08 -04007326
7327/*
7328 * Decode TEST_STATEID response
7329 */
7330static int nfs4_xdr_dec_test_stateid(struct rpc_rqst *rqstp,
7331 struct xdr_stream *xdr,
7332 struct nfs41_test_stateid_res *res)
7333{
7334 struct compound_hdr hdr;
7335 int status;
7336
7337 status = decode_compound_hdr(xdr, &hdr);
7338 if (status)
7339 goto out;
7340 status = decode_sequence(xdr, &res->seq_res, rqstp);
7341 if (status)
7342 goto out;
7343 status = decode_test_stateid(xdr, res);
7344out:
7345 return status;
7346}
Bryan Schumaker9aeda352011-06-02 14:59:09 -04007347
7348/*
7349 * Decode FREE_STATEID response
7350 */
7351static int nfs4_xdr_dec_free_stateid(struct rpc_rqst *rqstp,
7352 struct xdr_stream *xdr,
7353 struct nfs41_free_stateid_res *res)
7354{
7355 struct compound_hdr hdr;
7356 int status;
7357
7358 status = decode_compound_hdr(xdr, &hdr);
7359 if (status)
7360 goto out;
7361 status = decode_sequence(xdr, &res->seq_res, rqstp);
7362 if (status)
7363 goto out;
7364 status = decode_free_stateid(xdr, res);
7365out:
7366 return status;
7367}
Benny Halevy99fe60d2009-04-01 09:22:29 -04007368#endif /* CONFIG_NFS_V4_1 */
7369
Chuck Lever573c4e12010-12-14 14:58:11 +00007370/**
7371 * nfs4_decode_dirent - Decode a single NFSv4 directory entry stored in
7372 * the local page cache.
7373 * @xdr: XDR stream where entry resides
7374 * @entry: buffer to fill in with entry data
7375 * @plus: boolean indicating whether this should be a readdirplus entry
7376 *
7377 * Returns zero if successful, otherwise a negative errno value is
7378 * returned.
7379 *
7380 * This function is not invoked during READDIR reply decoding, but
7381 * rather whenever an application invokes the getdents(2) system call
7382 * on a directory already in our cache.
7383 */
7384int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
7385 int plus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007386{
Trond Myklebust256e48b2012-06-21 11:18:13 -04007387 unsigned int savep;
Fred Isamandae100c2011-07-30 20:52:37 -04007388 uint32_t bitmap[3] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07007389 uint32_t len;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007390 __be32 *p = xdr_inline_decode(xdr, 4);
7391 if (unlikely(!p))
7392 goto out_overflow;
Chuck Leverc08e76d2011-01-28 12:40:55 -05007393 if (*p == xdr_zero) {
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007394 p = xdr_inline_decode(xdr, 4);
7395 if (unlikely(!p))
7396 goto out_overflow;
Chuck Leverc08e76d2011-01-28 12:40:55 -05007397 if (*p == xdr_zero)
Chuck Lever573c4e12010-12-14 14:58:11 +00007398 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007399 entry->eof = 1;
Chuck Lever573c4e12010-12-14 14:58:11 +00007400 return -EBADCOOKIE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007401 }
7402
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007403 p = xdr_inline_decode(xdr, 12);
7404 if (unlikely(!p))
7405 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007406 entry->prev_cookie = entry->cookie;
7407 p = xdr_decode_hyper(p, &entry->cookie);
Chuck Leverc08e76d2011-01-28 12:40:55 -05007408 entry->len = be32_to_cpup(p);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007409
Trond Myklebust9af8c222010-10-24 11:52:55 -04007410 p = xdr_inline_decode(xdr, entry->len);
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007411 if (unlikely(!p))
7412 goto out_overflow;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007413 entry->name = (const char *) p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007414
7415 /*
7416 * In case the server doesn't return an inode number,
7417 * we fake one here. (We don't use inode number 0,
7418 * since glibc seems to choke on it...)
7419 */
7420 entry->ino = 1;
Trond Myklebust4f082222010-10-24 13:14:02 -04007421 entry->fattr->valid = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007422
Trond Myklebust9af8c222010-10-24 11:52:55 -04007423 if (decode_attr_bitmap(xdr, bitmap) < 0)
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007424 goto out_overflow;
Trond Myklebust9af8c222010-10-24 11:52:55 -04007425
Trond Myklebust256e48b2012-06-21 11:18:13 -04007426 if (decode_attr_length(xdr, &len, &savep) < 0)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007427 goto out_overflow;
7428
Chuck Lever573c4e12010-12-14 14:58:11 +00007429 if (decode_getfattr_attrs(xdr, bitmap, entry->fattr, entry->fh,
David Quigleyaa9c2662013-05-22 12:50:44 -04007430 NULL, entry->label, entry->server) < 0)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007431 goto out_overflow;
Trond Myklebust28331a42011-04-27 13:47:52 -04007432 if (entry->fattr->valid & NFS_ATTR_FATTR_MOUNTED_ON_FILEID)
7433 entry->ino = entry->fattr->mounted_on_fileid;
7434 else if (entry->fattr->valid & NFS_ATTR_FATTR_FILEID)
Trond Myklebust9af8c222010-10-24 11:52:55 -04007435 entry->ino = entry->fattr->fileid;
7436
Trond Myklebust0b26a0b2010-11-20 14:26:44 -05007437 entry->d_type = DT_UNKNOWN;
7438 if (entry->fattr->valid & NFS_ATTR_FATTR_TYPE)
7439 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
7440
Chuck Lever573c4e12010-12-14 14:58:11 +00007441 return 0;
Bryan Schumakerbabddc72010-10-20 15:44:29 -04007442
7443out_overflow:
7444 print_overflow_msg(__func__, xdr);
Chuck Lever573c4e12010-12-14 14:58:11 +00007445 return -EAGAIN;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007446}
7447
7448/*
7449 * We need to translate between nfs status return values and
7450 * the local errno values which may not be the same.
7451 */
7452static struct {
7453 int stat;
7454 int errno;
7455} nfs_errtbl[] = {
7456 { NFS4_OK, 0 },
Benny Halevy856dff32008-03-31 17:39:06 +03007457 { NFS4ERR_PERM, -EPERM },
7458 { NFS4ERR_NOENT, -ENOENT },
7459 { NFS4ERR_IO, -errno_NFSERR_IO},
7460 { NFS4ERR_NXIO, -ENXIO },
7461 { NFS4ERR_ACCESS, -EACCES },
7462 { NFS4ERR_EXIST, -EEXIST },
7463 { NFS4ERR_XDEV, -EXDEV },
7464 { NFS4ERR_NOTDIR, -ENOTDIR },
7465 { NFS4ERR_ISDIR, -EISDIR },
7466 { NFS4ERR_INVAL, -EINVAL },
7467 { NFS4ERR_FBIG, -EFBIG },
7468 { NFS4ERR_NOSPC, -ENOSPC },
7469 { NFS4ERR_ROFS, -EROFS },
7470 { NFS4ERR_MLINK, -EMLINK },
7471 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
7472 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
7473 { NFS4ERR_DQUOT, -EDQUOT },
7474 { NFS4ERR_STALE, -ESTALE },
7475 { NFS4ERR_BADHANDLE, -EBADHANDLE },
Benny Halevy856dff32008-03-31 17:39:06 +03007476 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
7477 { NFS4ERR_NOTSUPP, -ENOTSUPP },
7478 { NFS4ERR_TOOSMALL, -ETOOSMALL },
Trond Myklebustfdcb4572010-02-08 09:32:40 -05007479 { NFS4ERR_SERVERFAULT, -EREMOTEIO },
Benny Halevy856dff32008-03-31 17:39:06 +03007480 { NFS4ERR_BADTYPE, -EBADTYPE },
7481 { NFS4ERR_LOCKED, -EAGAIN },
Benny Halevy856dff32008-03-31 17:39:06 +03007482 { NFS4ERR_SYMLINK, -ELOOP },
7483 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
7484 { NFS4ERR_DEADLOCK, -EDEADLK },
Benny Halevy856dff32008-03-31 17:39:06 +03007485 { -1, -EIO }
Linus Torvalds1da177e2005-04-16 15:20:36 -07007486};
7487
7488/*
7489 * Convert an NFS error code to a local one.
7490 * This one is used jointly by NFSv2 and NFSv3.
7491 */
7492static int
David Howells0a8ea432006-08-22 20:06:08 -04007493nfs4_stat_to_errno(int stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07007494{
7495 int i;
7496 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
7497 if (nfs_errtbl[i].stat == stat)
7498 return nfs_errtbl[i].errno;
7499 }
7500 if (stat <= 10000 || stat > 10100) {
7501 /* The server is looney tunes. */
Trond Myklebustfdcb4572010-02-08 09:32:40 -05007502 return -EREMOTEIO;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007503 }
7504 /* If we cannot translate the error, the recovery routines should
7505 * handle it.
7506 * Note: remaining NFSv4 error codes have values > 10000, so should
7507 * not conflict with native Linux error codes.
7508 */
Benny Halevy856dff32008-03-31 17:39:06 +03007509 return -stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07007510}
7511
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007512#ifdef CONFIG_NFS_V4_2
7513#include "nfs42xdr.c"
7514#endif /* CONFIG_NFS_V4_2 */
7515
Linus Torvalds1da177e2005-04-16 15:20:36 -07007516#define PROC(proc, argtype, restype) \
7517[NFSPROC4_CLNT_##proc] = { \
7518 .p_proc = NFSPROC4_COMPOUND, \
Chuck Lever9f06c712010-12-14 14:59:18 +00007519 .p_encode = (kxdreproc_t)nfs4_xdr_##argtype, \
Chuck Leverbf269552010-12-14 14:59:29 +00007520 .p_decode = (kxdrdproc_t)nfs4_xdr_##restype, \
Chuck Lever2bea90d2007-03-29 16:47:53 -04007521 .p_arglen = NFS4_##argtype##_sz, \
7522 .p_replen = NFS4_##restype##_sz, \
Chuck Levercc0175c2006-03-20 13:44:22 -05007523 .p_statidx = NFSPROC4_CLNT_##proc, \
7524 .p_name = #proc, \
Andy Adamson05d564f2008-12-23 16:06:15 -05007525}
Linus Torvalds1da177e2005-04-16 15:20:36 -07007526
Anna Schumaker7c61f0d2015-04-14 10:34:20 -04007527#define STUB(proc) \
7528[NFSPROC4_CLNT_##proc] = { \
7529 .p_name = #proc, \
7530}
7531
Linus Torvalds1da177e2005-04-16 15:20:36 -07007532struct rpc_procinfo nfs4_procedures[] = {
Chuck Lever7d93bd712010-12-14 14:57:42 +00007533 PROC(READ, enc_read, dec_read),
7534 PROC(WRITE, enc_write, dec_write),
7535 PROC(COMMIT, enc_commit, dec_commit),
7536 PROC(OPEN, enc_open, dec_open),
7537 PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
7538 PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr),
7539 PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade),
7540 PROC(CLOSE, enc_close, dec_close),
7541 PROC(SETATTR, enc_setattr, dec_setattr),
7542 PROC(FSINFO, enc_fsinfo, dec_fsinfo),
7543 PROC(RENEW, enc_renew, dec_renew),
7544 PROC(SETCLIENTID, enc_setclientid, dec_setclientid),
7545 PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm),
7546 PROC(LOCK, enc_lock, dec_lock),
7547 PROC(LOCKT, enc_lockt, dec_lockt),
7548 PROC(LOCKU, enc_locku, dec_locku),
7549 PROC(ACCESS, enc_access, dec_access),
7550 PROC(GETATTR, enc_getattr, dec_getattr),
7551 PROC(LOOKUP, enc_lookup, dec_lookup),
7552 PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
7553 PROC(REMOVE, enc_remove, dec_remove),
7554 PROC(RENAME, enc_rename, dec_rename),
7555 PROC(LINK, enc_link, dec_link),
7556 PROC(SYMLINK, enc_symlink, dec_symlink),
7557 PROC(CREATE, enc_create, dec_create),
7558 PROC(PATHCONF, enc_pathconf, dec_pathconf),
7559 PROC(STATFS, enc_statfs, dec_statfs),
7560 PROC(READLINK, enc_readlink, dec_readlink),
7561 PROC(READDIR, enc_readdir, dec_readdir),
7562 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
7563 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
7564 PROC(GETACL, enc_getacl, dec_getacl),
7565 PROC(SETACL, enc_setacl, dec_setacl),
7566 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
7567 PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner),
Bryan Schumaker5a5ea0d2011-03-24 17:12:29 +00007568 PROC(SECINFO, enc_secinfo, dec_secinfo),
Chuck Lever44c99932013-10-17 14:13:30 -04007569 PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present),
Benny Halevy99fe60d2009-04-01 09:22:29 -04007570#if defined(CONFIG_NFS_V4_1)
Chuck Lever7d93bd712010-12-14 14:57:42 +00007571 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
7572 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
7573 PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
7574 PROC(SEQUENCE, enc_sequence, dec_sequence),
7575 PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
7576 PROC(RECLAIM_COMPLETE, enc_reclaim_complete, dec_reclaim_complete),
7577 PROC(GETDEVICEINFO, enc_getdeviceinfo, dec_getdeviceinfo),
7578 PROC(LAYOUTGET, enc_layoutget, dec_layoutget),
Andy Adamson863a3c62011-03-23 13:27:54 +00007579 PROC(LAYOUTCOMMIT, enc_layoutcommit, dec_layoutcommit),
Benny Halevycbe82602011-05-22 19:52:37 +03007580 PROC(LAYOUTRETURN, enc_layoutreturn, dec_layoutreturn),
Bryan Schumakerfca78d62011-06-02 14:59:07 -04007581 PROC(SECINFO_NO_NAME, enc_secinfo_no_name, dec_secinfo_no_name),
Bryan Schumaker7d974792011-06-02 14:59:08 -04007582 PROC(TEST_STATEID, enc_test_stateid, dec_test_stateid),
Bryan Schumaker9aeda352011-06-02 14:59:09 -04007583 PROC(FREE_STATEID, enc_free_stateid, dec_free_stateid),
Anna Schumaker7c61f0d2015-04-14 10:34:20 -04007584 STUB(GETDEVICELIST),
Trond Myklebustad24ecf2012-05-25 17:11:42 -04007585 PROC(BIND_CONN_TO_SESSION,
7586 enc_bind_conn_to_session, dec_bind_conn_to_session),
Trond Myklebust66245532012-05-25 17:18:09 -04007587 PROC(DESTROY_CLIENTID, enc_destroy_clientid, dec_destroy_clientid),
Benny Halevy99fe60d2009-04-01 09:22:29 -04007588#endif /* CONFIG_NFS_V4_1 */
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007589#ifdef CONFIG_NFS_V4_2
7590 PROC(SEEK, enc_seek, dec_seek),
Anna Schumakerf4ac1672014-11-25 13:18:15 -05007591 PROC(ALLOCATE, enc_allocate, dec_allocate),
Anna Schumaker624bd5b2014-11-25 13:18:16 -05007592 PROC(DEALLOCATE, enc_deallocate, dec_deallocate),
Trond Myklebustbe3a5d22015-06-23 19:51:55 +08007593 PROC(LAYOUTSTATS, enc_layoutstats, dec_layoutstats),
Peng Tao36022772015-09-26 02:24:34 +08007594 PROC(CLONE, enc_clone, dec_clone),
Anna Schumaker2e724482013-05-21 16:53:03 -04007595 PROC(COPY, enc_copy, dec_copy),
Anna Schumaker1c6dcbe2014-09-26 13:58:48 -04007596#endif /* CONFIG_NFS_V4_2 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07007597};
7598
Trond Myklebusta613fa12012-01-20 13:53:56 -05007599const struct rpc_version nfs_version4 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07007600 .number = 4,
Tobias Klausere8c96f82006-03-24 03:15:34 -08007601 .nrprocs = ARRAY_SIZE(nfs4_procedures),
Linus Torvalds1da177e2005-04-16 15:20:36 -07007602 .procs = nfs4_procedures
7603};
7604
7605/*
7606 * Local variables:
7607 * c-basic-offset: 8
7608 * End:
7609 */