blob: 3bcde49fbea8f6ddf5af0c570b9213138ad2af68 [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>
41#include <linux/slab.h>
42#include <linux/utsname.h>
43#include <linux/errno.h>
44#include <linux/string.h>
45#include <linux/in.h>
46#include <linux/pagemap.h>
47#include <linux/proc_fs.h>
48#include <linux/kdev_t.h>
49#include <linux/sunrpc/clnt.h>
50#include <linux/nfs.h>
51#include <linux/nfs4.h>
52#include <linux/nfs_fs.h>
53#include <linux/nfs_idmap.h>
Trond Myklebust4ce79712005-06-22 17:16:21 +000054#include "nfs4_fs.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
56#define NFSDBG_FACILITY NFSDBG_XDR
57
58/* Mapping from NFS error code to "errno" error code. */
59#define errno_NFSERR_IO EIO
60
David Howells0a8ea432006-08-22 20:06:08 -040061static int nfs4_stat_to_errno(int);
Linus Torvalds1da177e2005-04-16 15:20:36 -070062
63/* NFSv4 COMPOUND tags are only wanted for debugging purposes */
64#ifdef DEBUG
65#define NFS4_MAXTAGLEN 20
66#else
67#define NFS4_MAXTAGLEN 0
68#endif
69
Andy Adamson6c0195a2008-12-23 16:06:15 -050070/* lock,open owner id:
Trond Myklebust9f958ab2007-07-02 13:58:33 -040071 * we currently use size 2 (u64) out of (NFS4_OPAQUE_LIMIT >> 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -070072 */
Trond Myklebust9f958ab2007-07-02 13:58:33 -040073#define open_owner_id_maxsz (1 + 4)
74#define lock_owner_id_maxsz (1 + 4)
Trond Myklebust9104a552007-07-17 21:52:42 -040075#define decode_lockowner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
Linus Torvalds1da177e2005-04-16 15:20:36 -070076#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
77#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
78#define op_encode_hdr_maxsz (1)
79#define op_decode_hdr_maxsz (2)
Trond Myklebust9104a552007-07-17 21:52:42 -040080#define encode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
81#define decode_stateid_maxsz (XDR_QUADLEN(NFS4_STATEID_SIZE))
82#define encode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
83#define decode_verifier_maxsz (XDR_QUADLEN(NFS4_VERIFIER_SIZE))
Linus Torvalds1da177e2005-04-16 15:20:36 -070084#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
85 (NFS4_FHSIZE >> 2))
86#define decode_putfh_maxsz (op_decode_hdr_maxsz)
87#define encode_putrootfh_maxsz (op_encode_hdr_maxsz)
88#define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
89#define encode_getfh_maxsz (op_encode_hdr_maxsz)
90#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
91 ((3+NFS4_FHSIZE) >> 2))
J. Bruce Fields96928202005-06-22 17:16:22 +000092#define nfs4_fattr_bitmap_maxsz 3
93#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070094#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
95#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
Trond Myklebustbd625ba2007-07-08 18:38:23 -040096#define nfs4_owner_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
97#define nfs4_group_maxsz (1 + XDR_QUADLEN(IDMAP_NAMESZ))
J. Bruce Fields96928202005-06-22 17:16:22 +000098/* This is based on getfattr, which uses the most attributes: */
99#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
Trond Myklebustbd625ba2007-07-08 18:38:23 -0400100 3 + 3 + 3 + nfs4_owner_maxsz + nfs4_group_maxsz))
J. Bruce Fields96928202005-06-22 17:16:22 +0000101#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
102 nfs4_fattr_value_maxsz)
103#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400104#define encode_attrs_maxsz (nfs4_fattr_bitmap_maxsz + \
105 1 + 2 + 1 + \
106 nfs4_owner_maxsz + \
107 nfs4_group_maxsz + \
108 4 + 4)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700109#define encode_savefh_maxsz (op_encode_hdr_maxsz)
110#define decode_savefh_maxsz (op_decode_hdr_maxsz)
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400111#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
112#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
Fred Isaman2f42b5d2008-03-13 15:26:30 +0200113#define encode_fsinfo_maxsz (encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
115#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
116#define decode_renew_maxsz (op_decode_hdr_maxsz)
117#define encode_setclientid_maxsz \
118 (op_encode_hdr_maxsz + \
Chuck Levercc38bac2007-12-10 14:56:54 -0500119 XDR_QUADLEN(NFS4_VERIFIER_SIZE) + \
120 XDR_QUADLEN(NFS4_SETCLIENTID_NAMELEN) + \
121 1 /* sc_prog */ + \
122 XDR_QUADLEN(RPCBIND_MAXNETIDLEN) + \
123 XDR_QUADLEN(RPCBIND_MAXUADDRLEN) + \
124 1) /* sc_cb_ident */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125#define decode_setclientid_maxsz \
126 (op_decode_hdr_maxsz + \
127 2 + \
128 1024) /* large value for CLID_INUSE */
129#define encode_setclientid_confirm_maxsz \
130 (op_encode_hdr_maxsz + \
131 3 + (NFS4_VERIFIER_SIZE >> 2))
132#define decode_setclientid_confirm_maxsz \
133 (op_decode_hdr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400134#define encode_lookup_maxsz (op_encode_hdr_maxsz + nfs4_name_maxsz)
135#define decode_lookup_maxsz (op_decode_hdr_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400136#define encode_share_access_maxsz \
137 (2)
Trond Myklebust9104a552007-07-17 21:52:42 -0400138#define encode_createmode_maxsz (1 + encode_attrs_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400139#define encode_opentype_maxsz (1 + encode_createmode_maxsz)
140#define encode_claim_null_maxsz (1 + nfs4_name_maxsz)
141#define encode_open_maxsz (op_encode_hdr_maxsz + \
142 2 + encode_share_access_maxsz + 2 + \
143 open_owner_id_maxsz + \
144 encode_opentype_maxsz + \
145 encode_claim_null_maxsz)
146#define decode_ace_maxsz (3 + nfs4_owner_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400147#define decode_delegation_maxsz (1 + decode_stateid_maxsz + 1 + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400148 decode_ace_maxsz)
149#define decode_change_info_maxsz (5)
150#define decode_open_maxsz (op_decode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400151 decode_stateid_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400152 decode_change_info_maxsz + 1 + \
153 nfs4_fattr_bitmap_maxsz + \
154 decode_delegation_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400155#define encode_open_confirm_maxsz \
156 (op_encode_hdr_maxsz + \
157 encode_stateid_maxsz + 1)
158#define decode_open_confirm_maxsz \
159 (op_decode_hdr_maxsz + \
160 decode_stateid_maxsz)
161#define encode_open_downgrade_maxsz \
162 (op_encode_hdr_maxsz + \
163 encode_stateid_maxsz + 1 + \
164 encode_share_access_maxsz)
165#define decode_open_downgrade_maxsz \
166 (op_decode_hdr_maxsz + \
167 decode_stateid_maxsz)
168#define encode_close_maxsz (op_encode_hdr_maxsz + \
169 1 + encode_stateid_maxsz)
170#define decode_close_maxsz (op_decode_hdr_maxsz + \
171 decode_stateid_maxsz)
172#define encode_setattr_maxsz (op_encode_hdr_maxsz + \
173 encode_stateid_maxsz + \
174 encode_attrs_maxsz)
175#define decode_setattr_maxsz (op_decode_hdr_maxsz + \
176 nfs4_fattr_bitmap_maxsz)
177#define encode_read_maxsz (op_encode_hdr_maxsz + \
178 encode_stateid_maxsz + 3)
179#define decode_read_maxsz (op_decode_hdr_maxsz + 2)
180#define encode_readdir_maxsz (op_encode_hdr_maxsz + \
181 2 + encode_verifier_maxsz + 5)
182#define decode_readdir_maxsz (op_decode_hdr_maxsz + \
183 decode_verifier_maxsz)
184#define encode_readlink_maxsz (op_encode_hdr_maxsz)
185#define decode_readlink_maxsz (op_decode_hdr_maxsz + 1)
186#define encode_write_maxsz (op_encode_hdr_maxsz + \
187 encode_stateid_maxsz + 4)
188#define decode_write_maxsz (op_decode_hdr_maxsz + \
189 2 + decode_verifier_maxsz)
190#define encode_commit_maxsz (op_encode_hdr_maxsz + 3)
191#define decode_commit_maxsz (op_decode_hdr_maxsz + \
192 decode_verifier_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700193#define encode_remove_maxsz (op_encode_hdr_maxsz + \
194 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400195#define decode_remove_maxsz (op_decode_hdr_maxsz + \
196 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700197#define encode_rename_maxsz (op_encode_hdr_maxsz + \
198 2 * nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400199#define decode_rename_maxsz (op_decode_hdr_maxsz + \
200 decode_change_info_maxsz + \
201 decode_change_info_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700202#define encode_link_maxsz (op_encode_hdr_maxsz + \
203 nfs4_name_maxsz)
Benny Halevy6ce18392009-04-01 09:22:06 -0400204#define decode_link_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400205#define encode_lock_maxsz (op_encode_hdr_maxsz + \
206 7 + \
207 1 + encode_stateid_maxsz + 8)
208#define decode_lock_denied_maxsz \
209 (8 + decode_lockowner_maxsz)
210#define decode_lock_maxsz (op_decode_hdr_maxsz + \
211 decode_lock_denied_maxsz)
212#define encode_lockt_maxsz (op_encode_hdr_maxsz + 12)
213#define decode_lockt_maxsz (op_decode_hdr_maxsz + \
214 decode_lock_denied_maxsz)
215#define encode_locku_maxsz (op_encode_hdr_maxsz + 3 + \
216 encode_stateid_maxsz + \
217 4)
218#define decode_locku_maxsz (op_decode_hdr_maxsz + \
219 decode_stateid_maxsz)
220#define encode_access_maxsz (op_encode_hdr_maxsz + 1)
221#define decode_access_maxsz (op_decode_hdr_maxsz + 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700222#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
223 1 + nfs4_name_maxsz + \
Chuck Lever94a6d752006-08-22 20:06:23 -0400224 1 + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000225 nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700226#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
227#define encode_create_maxsz (op_encode_hdr_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400228 1 + 2 + nfs4_name_maxsz + \
229 encode_attrs_maxsz)
Trond Myklebust2cebf822007-07-02 13:57:28 -0400230#define decode_create_maxsz (op_decode_hdr_maxsz + \
231 decode_change_info_maxsz + \
232 nfs4_fattr_bitmap_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400233#define encode_statfs_maxsz (encode_getattr_maxsz)
234#define decode_statfs_maxsz (decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700235#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
236#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400237#define encode_getacl_maxsz (encode_getattr_maxsz)
238#define decode_getacl_maxsz (op_decode_hdr_maxsz + \
239 nfs4_fattr_bitmap_maxsz + 1)
240#define encode_setacl_maxsz (op_encode_hdr_maxsz + \
241 encode_stateid_maxsz + 3)
242#define decode_setacl_maxsz (decode_setattr_maxsz)
Trond Myklebuste6889622007-07-02 13:58:30 -0400243#define encode_fs_locations_maxsz \
244 (encode_getattr_maxsz)
245#define decode_fs_locations_maxsz \
246 (0)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400247
248#if defined(CONFIG_NFS_V4_1)
Andy Adamsonfc931582009-04-01 09:22:31 -0400249#define NFS4_MAX_MACHINE_NAME_LEN (64)
250
Benny Halevy99fe60d2009-04-01 09:22:29 -0400251#define encode_exchange_id_maxsz (op_encode_hdr_maxsz + \
252 encode_verifier_maxsz + \
253 1 /* co_ownerid.len */ + \
254 XDR_QUADLEN(NFS4_EXCHANGE_ID_LEN) + \
255 1 /* flags */ + \
256 1 /* spa_how */ + \
257 0 /* SP4_NONE (for now) */ + \
258 1 /* zero implemetation id array */)
259#define decode_exchange_id_maxsz (op_decode_hdr_maxsz + \
260 2 /* eir_clientid */ + \
261 1 /* eir_sequenceid */ + \
262 1 /* eir_flags */ + \
263 1 /* spr_how */ + \
264 0 /* SP4_NONE (for now) */ + \
265 2 /* eir_server_owner.so_minor_id */ + \
266 /* eir_server_owner.so_major_id<> */ \
267 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
268 /* eir_server_scope<> */ \
269 XDR_QUADLEN(NFS4_OPAQUE_LIMIT) + 1 + \
270 1 /* eir_server_impl_id array length */ + \
271 0 /* ignored eir_server_impl_id contents */)
Andy Adamsonfc931582009-04-01 09:22:31 -0400272#define encode_channel_attrs_maxsz (6 + 1 /* ca_rdma_ird.len (0) */)
273#define decode_channel_attrs_maxsz (6 + \
274 1 /* ca_rdma_ird.len */ + \
275 1 /* ca_rdma_ird */)
276#define encode_create_session_maxsz (op_encode_hdr_maxsz + \
277 2 /* csa_clientid */ + \
278 1 /* csa_sequence */ + \
279 1 /* csa_flags */ + \
280 encode_channel_attrs_maxsz + \
281 encode_channel_attrs_maxsz + \
282 1 /* csa_cb_program */ + \
283 1 /* csa_sec_parms.len (1) */ + \
284 1 /* cb_secflavor (AUTH_SYS) */ + \
285 1 /* stamp */ + \
286 1 /* machinename.len */ + \
287 XDR_QUADLEN(NFS4_MAX_MACHINE_NAME_LEN) + \
288 1 /* uid */ + \
289 1 /* gid */ + \
290 1 /* gids.len (0) */)
291#define decode_create_session_maxsz (op_decode_hdr_maxsz + \
292 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + \
293 1 /* csr_sequence */ + \
294 1 /* csr_flags */ + \
295 decode_channel_attrs_maxsz + \
296 decode_channel_attrs_maxsz)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400297#define encode_destroy_session_maxsz (op_encode_hdr_maxsz + 4)
298#define decode_destroy_session_maxsz (op_decode_hdr_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400299#define encode_sequence_maxsz (op_encode_hdr_maxsz + \
300 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 4)
301#define decode_sequence_maxsz (op_decode_hdr_maxsz + \
302 XDR_QUADLEN(NFS4_MAX_SESSIONID_LEN) + 5)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400303#else /* CONFIG_NFS_V4_1 */
304#define encode_sequence_maxsz 0
305#define decode_sequence_maxsz 0
306#endif /* CONFIG_NFS_V4_1 */
307
Linus Torvalds1da177e2005-04-16 15:20:36 -0700308#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
309#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
310#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400311 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700312 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400313 encode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700314#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400315 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700316 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400317 decode_read_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700318#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400319 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700320 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400321 encode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700322#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400323 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700324 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400325 decode_readlink_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700326#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400327 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700328 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400329 encode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700330#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400331 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700332 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400333 decode_readdir_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700334#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400335 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700336 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400337 encode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400338 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700339#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400340 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700341 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400342 decode_write_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400343 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700344#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400345 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400347 encode_commit_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400348 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700349#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400350 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400352 decode_commit_maxsz + \
Trond Myklebust4f9838c2005-10-27 22:12:44 -0400353 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400355 encode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400356 encode_putfh_maxsz + \
357 encode_savefh_maxsz + \
358 encode_open_maxsz + \
359 encode_getfh_maxsz + \
360 encode_getattr_maxsz + \
361 encode_restorefh_maxsz + \
362 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700363#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400364 decode_sequence_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400365 decode_putfh_maxsz + \
366 decode_savefh_maxsz + \
367 decode_open_maxsz + \
368 decode_getfh_maxsz + \
369 decode_getattr_maxsz + \
370 decode_restorefh_maxsz + \
371 decode_getattr_maxsz)
Trond Myklebust9104a552007-07-17 21:52:42 -0400372#define NFS4_enc_open_confirm_sz \
373 (compound_encode_hdr_maxsz + \
374 encode_putfh_maxsz + \
375 encode_open_confirm_maxsz)
376#define NFS4_dec_open_confirm_sz \
377 (compound_decode_hdr_maxsz + \
378 decode_putfh_maxsz + \
379 decode_open_confirm_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700380#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400381 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700382 encode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400383 encode_open_maxsz + \
384 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700385#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400386 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700387 decode_putfh_maxsz + \
Trond Myklebust2cebf822007-07-02 13:57:28 -0400388 decode_open_maxsz + \
389 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700390#define NFS4_enc_open_downgrade_sz \
391 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400392 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400393 encode_putfh_maxsz + \
394 encode_open_downgrade_maxsz + \
395 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700396#define NFS4_dec_open_downgrade_sz \
397 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400398 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400399 decode_putfh_maxsz + \
400 decode_open_downgrade_maxsz + \
401 decode_getattr_maxsz)
402#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400403 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400404 encode_putfh_maxsz + \
405 encode_close_maxsz + \
406 encode_getattr_maxsz)
407#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400408 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400409 decode_putfh_maxsz + \
410 decode_close_maxsz + \
411 decode_getattr_maxsz)
412#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400413 encode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400414 encode_putfh_maxsz + \
415 encode_setattr_maxsz + \
416 encode_getattr_maxsz)
417#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400418 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400419 decode_putfh_maxsz + \
420 decode_setattr_maxsz + \
421 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700422#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400423 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700424 encode_putfh_maxsz + \
425 encode_fsinfo_maxsz)
426#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400427 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700428 decode_putfh_maxsz + \
429 decode_fsinfo_maxsz)
430#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
431 encode_renew_maxsz)
432#define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \
433 decode_renew_maxsz)
434#define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \
435 encode_setclientid_maxsz)
436#define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \
437 decode_setclientid_maxsz)
438#define NFS4_enc_setclientid_confirm_sz \
439 (compound_encode_hdr_maxsz + \
440 encode_setclientid_confirm_maxsz + \
441 encode_putrootfh_maxsz + \
442 encode_fsinfo_maxsz)
443#define NFS4_dec_setclientid_confirm_sz \
444 (compound_decode_hdr_maxsz + \
445 decode_setclientid_confirm_maxsz + \
446 decode_putrootfh_maxsz + \
447 decode_fsinfo_maxsz)
448#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400449 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700450 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400451 encode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700452#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400453 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700454 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400455 decode_lock_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700456#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400457 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700458 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400459 encode_lockt_maxsz)
460#define NFS4_dec_lockt_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400461 decode_sequence_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400462 decode_putfh_maxsz + \
463 decode_lockt_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700464#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400465 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700466 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400467 encode_locku_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700468#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400469 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700470 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400471 decode_locku_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700472#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400473 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700474 encode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400475 encode_access_maxsz + \
476 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700477#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400478 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700479 decode_putfh_maxsz + \
Trond Myklebust76b32992007-08-10 17:45:11 -0400480 decode_access_maxsz + \
481 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700482#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400483 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700484 encode_putfh_maxsz + \
485 encode_getattr_maxsz)
486#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400487 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700488 decode_putfh_maxsz + \
489 decode_getattr_maxsz)
490#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400491 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700492 encode_putfh_maxsz + \
493 encode_lookup_maxsz + \
494 encode_getattr_maxsz + \
495 encode_getfh_maxsz)
496#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400497 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700498 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400499 decode_lookup_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700500 decode_getattr_maxsz + \
501 decode_getfh_maxsz)
502#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400503 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700504 encode_putrootfh_maxsz + \
505 encode_getattr_maxsz + \
506 encode_getfh_maxsz)
507#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400508 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700509 decode_putrootfh_maxsz + \
510 decode_getattr_maxsz + \
511 decode_getfh_maxsz)
512#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400513 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700514 encode_putfh_maxsz + \
Trond Myklebust16e42952005-10-27 22:12:44 -0400515 encode_remove_maxsz + \
516 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700517#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400518 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700519 decode_putfh_maxsz + \
Benny Halevy6ce18392009-04-01 09:22:06 -0400520 decode_remove_maxsz + \
Trond Myklebust16e42952005-10-27 22:12:44 -0400521 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700522#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400523 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700524 encode_putfh_maxsz + \
525 encode_savefh_maxsz + \
526 encode_putfh_maxsz + \
Trond Myklebust6caf2c82005-10-27 22:12:43 -0400527 encode_rename_maxsz + \
528 encode_getattr_maxsz + \
529 encode_restorefh_maxsz + \
530 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700531#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400532 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700533 decode_putfh_maxsz + \
534 decode_savefh_maxsz + \
535 decode_putfh_maxsz + \
Trond Myklebust6caf2c82005-10-27 22:12:43 -0400536 decode_rename_maxsz + \
537 decode_getattr_maxsz + \
538 decode_restorefh_maxsz + \
539 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700540#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400541 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700542 encode_putfh_maxsz + \
543 encode_savefh_maxsz + \
544 encode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400545 encode_link_maxsz + \
546 decode_getattr_maxsz + \
547 encode_restorefh_maxsz + \
548 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700549#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400550 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700551 decode_putfh_maxsz + \
552 decode_savefh_maxsz + \
553 decode_putfh_maxsz + \
Trond Myklebust91ba2ee2005-10-27 22:12:42 -0400554 decode_link_maxsz + \
555 decode_getattr_maxsz + \
556 decode_restorefh_maxsz + \
557 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700558#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400559 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700560 encode_putfh_maxsz + \
561 encode_symlink_maxsz + \
562 encode_getattr_maxsz + \
563 encode_getfh_maxsz)
564#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400565 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700566 decode_putfh_maxsz + \
567 decode_symlink_maxsz + \
568 decode_getattr_maxsz + \
569 decode_getfh_maxsz)
570#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400571 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700572 encode_putfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400573 encode_savefh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700574 encode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400575 encode_getfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700576 encode_getattr_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400577 encode_restorefh_maxsz + \
578 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700579#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400580 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700581 decode_putfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400582 decode_savefh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700583 decode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400584 decode_getfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700585 decode_getattr_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400586 decode_restorefh_maxsz + \
587 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700588#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400589 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700590 encode_putfh_maxsz + \
591 encode_getattr_maxsz)
592#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400593 decode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700594 decode_putfh_maxsz + \
595 decode_getattr_maxsz)
596#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400597 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700598 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400599 encode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700600#define NFS4_dec_statfs_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 + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400603 decode_statfs_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700604#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400605 encode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800606 encode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700607 encode_getattr_maxsz)
608#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400609 decode_sequence_maxsz + \
Trond Myklebustab91f262007-02-02 14:47:17 -0800610 decode_putfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700611 decode_getattr_maxsz)
612#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400613 encode_sequence_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700614 encode_putfh_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100615 encode_delegreturn_maxsz + \
616 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700617#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400618 decode_sequence_maxsz + \
Trond Myklebustfa178f22006-01-03 09:55:38 +0100619 decode_delegreturn_maxsz + \
620 decode_getattr_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000621#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400622 encode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000623 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400624 encode_getacl_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000625#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400626 decode_sequence_maxsz + \
J. Bruce Fields029d1052005-06-22 17:16:22 +0000627 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400628 decode_getacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000629#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400630 encode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000631 encode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400632 encode_setacl_maxsz)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000633#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400634 decode_sequence_maxsz + \
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000635 decode_putfh_maxsz + \
Trond Myklebust9104a552007-07-17 21:52:42 -0400636 decode_setacl_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400637#define NFS4_enc_fs_locations_sz \
638 (compound_encode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400639 encode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400640 encode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400641 encode_lookup_maxsz + \
642 encode_fs_locations_maxsz)
Trond Myklebust683b57b2006-06-09 09:34:22 -0400643#define NFS4_dec_fs_locations_sz \
644 (compound_decode_hdr_maxsz + \
Andy Adamson9b7b9fc2009-04-01 09:22:11 -0400645 decode_sequence_maxsz + \
Trond Myklebust683b57b2006-06-09 09:34:22 -0400646 decode_putfh_maxsz + \
Trond Myklebuste6889622007-07-02 13:58:30 -0400647 decode_lookup_maxsz + \
648 decode_fs_locations_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400649#if defined(CONFIG_NFS_V4_1)
650#define NFS4_enc_exchange_id_sz \
651 (compound_encode_hdr_maxsz + \
652 encode_exchange_id_maxsz)
653#define NFS4_dec_exchange_id_sz \
654 (compound_decode_hdr_maxsz + \
655 decode_exchange_id_maxsz)
Andy Adamsonfc931582009-04-01 09:22:31 -0400656#define NFS4_enc_create_session_sz \
657 (compound_encode_hdr_maxsz + \
658 encode_create_session_maxsz)
659#define NFS4_dec_create_session_sz \
660 (compound_decode_hdr_maxsz + \
661 decode_create_session_maxsz)
Andy Adamson0f3e66c2009-04-01 09:22:34 -0400662#define NFS4_enc_destroy_session_sz (compound_encode_hdr_maxsz + \
663 encode_destroy_session_maxsz)
664#define NFS4_dec_destroy_session_sz (compound_decode_hdr_maxsz + \
665 decode_destroy_session_maxsz)
Andy Adamsonfc01cea2009-04-01 09:22:36 -0400666#define NFS4_enc_sequence_sz \
667 (compound_decode_hdr_maxsz + \
668 encode_sequence_maxsz)
669#define NFS4_dec_sequence_sz \
670 (compound_decode_hdr_maxsz + \
671 decode_sequence_maxsz)
Andy Adamson2050f0c2009-04-01 09:22:30 -0400672#define NFS4_enc_get_lease_time_sz (compound_encode_hdr_maxsz + \
673 encode_sequence_maxsz + \
674 encode_putrootfh_maxsz + \
675 encode_fsinfo_maxsz)
676#define NFS4_dec_get_lease_time_sz (compound_decode_hdr_maxsz + \
677 decode_sequence_maxsz + \
678 decode_putrootfh_maxsz + \
679 decode_fsinfo_maxsz)
Benny Halevy99fe60d2009-04-01 09:22:29 -0400680#endif /* CONFIG_NFS_V4_1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700681
Trond Myklebustbca79472009-03-11 14:10:26 -0400682static const umode_t nfs_type2fmt[] = {
683 [NF4BAD] = 0,
684 [NF4REG] = S_IFREG,
685 [NF4DIR] = S_IFDIR,
686 [NF4BLK] = S_IFBLK,
687 [NF4CHR] = S_IFCHR,
688 [NF4LNK] = S_IFLNK,
689 [NF4SOCK] = S_IFSOCK,
690 [NF4FIFO] = S_IFIFO,
691 [NF4ATTRDIR] = 0,
692 [NF4NAMEDATTR] = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700693};
694
695struct compound_hdr {
696 int32_t status;
697 uint32_t nops;
Andy Adamsond0179312008-12-23 16:06:17 -0500698 __be32 * nops_p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700699 uint32_t taglen;
700 char * tag;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400701 uint32_t replen; /* expected reply words */
Benny Halevy66cc0422009-04-01 09:22:10 -0400702 u32 minorversion;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700703};
704
Benny Halevy13c65ce2009-08-14 17:19:25 +0300705static __be32 *reserve_space(struct xdr_stream *xdr, size_t nbytes)
706{
707 __be32 *p = xdr_reserve_space(xdr, nbytes);
708 BUG_ON(!p);
709 return p;
710}
Linus Torvalds1da177e2005-04-16 15:20:36 -0700711
712static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
713{
Al Viro8687b632006-10-19 23:28:48 -0700714 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700715
716 p = xdr_reserve_space(xdr, 4 + len);
717 BUG_ON(p == NULL);
718 xdr_encode_opaque(p, str, len);
719}
720
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400721static void encode_compound_hdr(struct xdr_stream *xdr,
722 struct rpc_rqst *req,
723 struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700724{
Al Viro8687b632006-10-19 23:28:48 -0700725 __be32 *p;
Benny Halevy0c4e8c12009-04-01 09:22:07 -0400726 struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
727
728 /* initialize running count of expected bytes in reply.
729 * NOTE: the replied tag SHOULD be the same is the one sent,
730 * but this is not required as a MUST for the server to do so. */
731 hdr->replen = RPC_REPHDRSIZE + auth->au_rslack + 3 + hdr->taglen;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700732
733 dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
734 BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
Benny Halevy13c65ce2009-08-14 17:19:25 +0300735 p = reserve_space(xdr, 12 + hdr->taglen);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300736 *p++ = cpu_to_be32(hdr->taglen);
Benny Halevy93f0cf22009-08-14 17:19:06 +0300737 p = xdr_encode_opaque_fixed(p, hdr->tag, hdr->taglen);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300738 *p++ = cpu_to_be32(hdr->minorversion);
Andy Adamsond0179312008-12-23 16:06:17 -0500739 hdr->nops_p = p;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300740 *p++ = cpu_to_be32(hdr->nops);
Andy Adamsond0179312008-12-23 16:06:17 -0500741}
742
743static void encode_nops(struct compound_hdr *hdr)
744{
Andy Adamsonfc931582009-04-01 09:22:31 -0400745 BUG_ON(hdr->nops > NFS4_MAX_OPS);
Andy Adamsond0179312008-12-23 16:06:17 -0500746 *hdr->nops_p = htonl(hdr->nops);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700747}
748
749static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
750{
Al Viro8687b632006-10-19 23:28:48 -0700751 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700752
753 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
754 BUG_ON(p == NULL);
755 xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
756}
757
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500758static void encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700759{
760 char owner_name[IDMAP_NAMESZ];
761 char owner_group[IDMAP_NAMESZ];
762 int owner_namelen = 0;
763 int owner_grouplen = 0;
Al Viro8687b632006-10-19 23:28:48 -0700764 __be32 *p;
765 __be32 *q;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700766 int len;
767 uint32_t bmval0 = 0;
768 uint32_t bmval1 = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700769
770 /*
771 * We reserve enough space to write the entire attribute buffer at once.
772 * In the worst-case, this would be
773 * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
774 * = 36 bytes, plus any contribution from variable-length fields
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000775 * such as owner/group.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700776 */
777 len = 16;
778
779 /* Sigh */
780 if (iap->ia_valid & ATTR_SIZE)
781 len += 8;
782 if (iap->ia_valid & ATTR_MODE)
783 len += 4;
784 if (iap->ia_valid & ATTR_UID) {
David Howells7539bba2006-08-22 20:06:09 -0400785 owner_namelen = nfs_map_uid_to_name(server->nfs_client, iap->ia_uid, owner_name);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700786 if (owner_namelen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -0400787 dprintk("nfs: couldn't resolve uid %d to string\n",
788 iap->ia_uid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700789 /* XXX */
790 strcpy(owner_name, "nobody");
791 owner_namelen = sizeof("nobody") - 1;
792 /* goto out; */
793 }
794 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
795 }
796 if (iap->ia_valid & ATTR_GID) {
David Howells7539bba2006-08-22 20:06:09 -0400797 owner_grouplen = nfs_map_gid_to_group(server->nfs_client, iap->ia_gid, owner_group);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700798 if (owner_grouplen < 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -0400799 dprintk("nfs: couldn't resolve gid %d to string\n",
800 iap->ia_gid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700801 strcpy(owner_group, "nobody");
802 owner_grouplen = sizeof("nobody") - 1;
803 /* goto out; */
804 }
805 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
806 }
807 if (iap->ia_valid & ATTR_ATIME_SET)
808 len += 16;
809 else if (iap->ia_valid & ATTR_ATIME)
810 len += 4;
811 if (iap->ia_valid & ATTR_MTIME_SET)
812 len += 16;
813 else if (iap->ia_valid & ATTR_MTIME)
814 len += 4;
Benny Halevy13c65ce2009-08-14 17:19:25 +0300815 p = reserve_space(xdr, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700816
817 /*
818 * We write the bitmap length now, but leave the bitmap and the attribute
819 * buffer length to be backfilled at the end of this routine.
820 */
Benny Halevye75bc1c2009-08-14 17:18:54 +0300821 *p++ = cpu_to_be32(2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700822 q = p;
823 p += 3;
824
825 if (iap->ia_valid & ATTR_SIZE) {
826 bmval0 |= FATTR4_WORD0_SIZE;
Benny Halevyb95be5a2009-08-14 17:19:01 +0300827 p = xdr_encode_hyper(p, iap->ia_size);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700828 }
829 if (iap->ia_valid & ATTR_MODE) {
830 bmval1 |= FATTR4_WORD1_MODE;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300831 *p++ = cpu_to_be32(iap->ia_mode & S_IALLUGO);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700832 }
833 if (iap->ia_valid & ATTR_UID) {
834 bmval1 |= FATTR4_WORD1_OWNER;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300835 *p++ = cpu_to_be32(owner_namelen);
Benny Halevy93f0cf22009-08-14 17:19:06 +0300836 p = xdr_encode_opaque_fixed(p, owner_name, owner_namelen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700837 }
838 if (iap->ia_valid & ATTR_GID) {
839 bmval1 |= FATTR4_WORD1_OWNER_GROUP;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300840 *p++ = cpu_to_be32(owner_grouplen);
Benny Halevy93f0cf22009-08-14 17:19:06 +0300841 p = xdr_encode_opaque_fixed(p, owner_group, owner_grouplen);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700842 }
843 if (iap->ia_valid & ATTR_ATIME_SET) {
844 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300845 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
846 *p++ = cpu_to_be32(0);
847 *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
848 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700849 }
850 else if (iap->ia_valid & ATTR_ATIME) {
851 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300852 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700853 }
854 if (iap->ia_valid & ATTR_MTIME_SET) {
855 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300856 *p++ = cpu_to_be32(NFS4_SET_TO_CLIENT_TIME);
857 *p++ = cpu_to_be32(0);
858 *p++ = cpu_to_be32(iap->ia_mtime.tv_sec);
859 *p++ = cpu_to_be32(iap->ia_mtime.tv_nsec);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700860 }
861 else if (iap->ia_valid & ATTR_MTIME) {
862 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
Benny Halevye75bc1c2009-08-14 17:18:54 +0300863 *p++ = cpu_to_be32(NFS4_SET_TO_SERVER_TIME);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700864 }
Andy Adamson6c0195a2008-12-23 16:06:15 -0500865
Linus Torvalds1da177e2005-04-16 15:20:36 -0700866 /*
867 * Now we backfill the bitmap and the attribute buffer length.
868 */
869 if (len != ((char *)p - (char *)q) + 4) {
Chuck Leverfe82a182007-09-11 18:01:10 -0400870 printk(KERN_ERR "nfs: Attr length error, %u != %Zu\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -0700871 len, ((char *)p - (char *)q) + 4);
872 BUG();
873 }
874 len = (char *)p - (char *)q - 12;
875 *q++ = htonl(bmval0);
876 *q++ = htonl(bmval1);
877 *q++ = htonl(len);
878
Linus Torvalds1da177e2005-04-16 15:20:36 -0700879/* out: */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700880}
881
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500882static void encode_access(struct xdr_stream *xdr, u32 access, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700883{
Al Viro8687b632006-10-19 23:28:48 -0700884 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700885
Benny Halevy13c65ce2009-08-14 17:19:25 +0300886 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300887 *p++ = cpu_to_be32(OP_ACCESS);
888 *p++ = cpu_to_be32(access);
Andy Adamsond0179312008-12-23 16:06:17 -0500889 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400890 hdr->replen += decode_access_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700891}
892
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500893static void encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700894{
Al Viro8687b632006-10-19 23:28:48 -0700895 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700896
Benny Halevy13c65ce2009-08-14 17:19:25 +0300897 p = reserve_space(xdr, 8+NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300898 *p++ = cpu_to_be32(OP_CLOSE);
899 *p++ = cpu_to_be32(arg->seqid->sequence->counter);
Benny Halevy93f0cf22009-08-14 17:19:06 +0300900 p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -0500901 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400902 hdr->replen += decode_close_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700903}
904
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500905static void encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700906{
Al Viro8687b632006-10-19 23:28:48 -0700907 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -0500908
Benny Halevy13c65ce2009-08-14 17:19:25 +0300909 p = reserve_space(xdr, 16);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300910 *p++ = cpu_to_be32(OP_COMMIT);
Benny Halevyb95be5a2009-08-14 17:19:01 +0300911 p = xdr_encode_hyper(p, args->offset);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300912 *p++ = cpu_to_be32(args->count);
Andy Adamsond0179312008-12-23 16:06:17 -0500913 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400914 hdr->replen += decode_commit_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700915}
916
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500917static void encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700918{
Al Viro8687b632006-10-19 23:28:48 -0700919 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -0500920
Benny Halevy13c65ce2009-08-14 17:19:25 +0300921 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300922 *p++ = cpu_to_be32(OP_CREATE);
923 *p++ = cpu_to_be32(create->ftype);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700924
925 switch (create->ftype) {
926 case NF4LNK:
Benny Halevy13c65ce2009-08-14 17:19:25 +0300927 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300928 *p++ = cpu_to_be32(create->u.symlink.len);
Chuck Lever94a6d752006-08-22 20:06:23 -0400929 xdr_write_pages(xdr, create->u.symlink.pages, 0, create->u.symlink.len);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700930 break;
931
932 case NF4BLK: case NF4CHR:
Benny Halevy13c65ce2009-08-14 17:19:25 +0300933 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300934 *p++ = cpu_to_be32(create->u.device.specdata1);
935 *p++ = cpu_to_be32(create->u.device.specdata2);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700936 break;
937
938 default:
939 break;
940 }
941
Benny Halevy13c65ce2009-08-14 17:19:25 +0300942 p = reserve_space(xdr, 4 + create->name->len);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300943 *p++ = cpu_to_be32(create->name->len);
Benny Halevy93f0cf22009-08-14 17:19:06 +0300944 p = xdr_encode_opaque_fixed(p, create->name->name, create->name->len);
Andy Adamsond0179312008-12-23 16:06:17 -0500945 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400946 hdr->replen += decode_create_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700947
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500948 encode_attrs(xdr, create->attrs, create->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700949}
950
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500951static void encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700952{
Andy Adamson05d564f2008-12-23 16:06:15 -0500953 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700954
Benny Halevy13c65ce2009-08-14 17:19:25 +0300955 p = reserve_space(xdr, 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300956 *p++ = cpu_to_be32(OP_GETATTR);
957 *p++ = cpu_to_be32(1);
958 *p++ = cpu_to_be32(bitmap);
Andy Adamsond0179312008-12-23 16:06:17 -0500959 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400960 hdr->replen += decode_getattr_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700961}
962
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500963static 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 -0700964{
Andy Adamson05d564f2008-12-23 16:06:15 -0500965 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700966
Benny Halevy13c65ce2009-08-14 17:19:25 +0300967 p = reserve_space(xdr, 16);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300968 *p++ = cpu_to_be32(OP_GETATTR);
969 *p++ = cpu_to_be32(2);
970 *p++ = cpu_to_be32(bm0);
971 *p++ = cpu_to_be32(bm1);
Andy Adamsond0179312008-12-23 16:06:17 -0500972 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -0400973 hdr->replen += decode_getattr_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700974}
975
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500976static void encode_getfattr(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700977{
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500978 encode_getattr_two(xdr, bitmask[0] & nfs4_fattr_bitmap[0],
979 bitmask[1] & nfs4_fattr_bitmap[1], hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700980}
981
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500982static void encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700983{
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500984 encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
985 bitmask[1] & nfs4_fsinfo_bitmap[1], hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700986}
987
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500988static void encode_fs_locations(struct xdr_stream *xdr, const u32* bitmask, struct compound_hdr *hdr)
Manoj Naik830b8e32006-06-09 09:34:25 -0400989{
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500990 encode_getattr_two(xdr, bitmask[0] & nfs4_fs_locations_bitmap[0],
991 bitmask[1] & nfs4_fs_locations_bitmap[1], hdr);
Manoj Naik830b8e32006-06-09 09:34:25 -0400992}
993
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -0500994static void encode_getfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995{
Al Viro8687b632006-10-19 23:28:48 -0700996 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -0700997
Benny Halevy13c65ce2009-08-14 17:19:25 +0300998 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +0300999 *p++ = cpu_to_be32(OP_GETFH);
Andy Adamsond0179312008-12-23 16:06:17 -05001000 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001001 hdr->replen += decode_getfh_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001002}
1003
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001004static void encode_link(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001005{
Al Viro8687b632006-10-19 23:28:48 -07001006 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001007
Benny Halevy13c65ce2009-08-14 17:19:25 +03001008 p = reserve_space(xdr, 8 + name->len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001009 *p++ = cpu_to_be32(OP_LINK);
1010 *p++ = cpu_to_be32(name->len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001011 p = xdr_encode_opaque_fixed(p, name->name, name->len);
Andy Adamsond0179312008-12-23 16:06:17 -05001012 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001013 hdr->replen += decode_link_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001014}
1015
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001016static inline int nfs4_lock_type(struct file_lock *fl, int block)
1017{
1018 if ((fl->fl_type & (F_RDLCK|F_WRLCK|F_UNLCK)) == F_RDLCK)
1019 return block ? NFS4_READW_LT : NFS4_READ_LT;
1020 return block ? NFS4_WRITEW_LT : NFS4_WRITE_LT;
1021}
1022
1023static inline uint64_t nfs4_lock_length(struct file_lock *fl)
1024{
1025 if (fl->fl_end == OFFSET_MAX)
1026 return ~(uint64_t)0;
1027 return fl->fl_end - fl->fl_start + 1;
1028}
1029
Linus Torvalds1da177e2005-04-16 15:20:36 -07001030/*
1031 * opcode,type,reclaim,offset,length,new_lock_owner = 32
1032 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
1033 */
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001034static void encode_lock(struct xdr_stream *xdr, const struct nfs_lock_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001035{
Al Viro8687b632006-10-19 23:28:48 -07001036 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001037
Benny Halevy13c65ce2009-08-14 17:19:25 +03001038 p = reserve_space(xdr, 32);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001039 *p++ = cpu_to_be32(OP_LOCK);
1040 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, args->block));
1041 *p++ = cpu_to_be32(args->reclaim);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001042 p = xdr_encode_hyper(p, args->fl->fl_start);
1043 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Benny Halevye75bc1c2009-08-14 17:18:54 +03001044 *p++ = cpu_to_be32(args->new_lock_owner);
Trond Myklebust911d1aa2006-01-03 09:55:16 +01001045 if (args->new_lock_owner){
Benny Halevy13c65ce2009-08-14 17:19:25 +03001046 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+32);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001047 *p++ = cpu_to_be32(args->open_seqid->sequence->counter);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001048 p = xdr_encode_opaque_fixed(p, args->open_stateid->data, NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001049 *p++ = cpu_to_be32(args->lock_seqid->sequence->counter);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001050 p = xdr_encode_hyper(p, args->lock_owner.clientid);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001051 *p++ = cpu_to_be32(16);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001052 p = xdr_encode_opaque_fixed(p, "lock id:", 8);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001053 p = xdr_encode_hyper(p, args->lock_owner.id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001054 }
1055 else {
Benny Halevy13c65ce2009-08-14 17:19:25 +03001056 p = reserve_space(xdr, NFS4_STATEID_SIZE+4);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001057 p = xdr_encode_opaque_fixed(p, args->lock_stateid->data, NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001058 *p++ = cpu_to_be32(args->lock_seqid->sequence->counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001059 }
Andy Adamsond0179312008-12-23 16:06:17 -05001060 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001061 hdr->replen += decode_lock_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001062}
1063
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001064static void encode_lockt(struct xdr_stream *xdr, const struct nfs_lockt_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001065{
Al Viro8687b632006-10-19 23:28:48 -07001066 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001067
Benny Halevy13c65ce2009-08-14 17:19:25 +03001068 p = reserve_space(xdr, 52);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001069 *p++ = cpu_to_be32(OP_LOCKT);
1070 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
Benny Halevyb95be5a2009-08-14 17:19:01 +03001071 p = xdr_encode_hyper(p, args->fl->fl_start);
1072 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
1073 p = xdr_encode_hyper(p, args->lock_owner.clientid);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001074 *p++ = cpu_to_be32(16);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001075 p = xdr_encode_opaque_fixed(p, "lock id:", 8);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001076 p = xdr_encode_hyper(p, args->lock_owner.id);
Andy Adamsond0179312008-12-23 16:06:17 -05001077 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001078 hdr->replen += decode_lockt_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001079}
1080
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001081static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082{
Al Viro8687b632006-10-19 23:28:48 -07001083 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001084
Benny Halevy13c65ce2009-08-14 17:19:25 +03001085 p = reserve_space(xdr, 12+NFS4_STATEID_SIZE+16);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001086 *p++ = cpu_to_be32(OP_LOCKU);
1087 *p++ = cpu_to_be32(nfs4_lock_type(args->fl, 0));
1088 *p++ = cpu_to_be32(args->seqid->sequence->counter);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001089 p = xdr_encode_opaque_fixed(p, args->stateid->data, NFS4_STATEID_SIZE);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001090 p = xdr_encode_hyper(p, args->fl->fl_start);
1091 p = xdr_encode_hyper(p, nfs4_lock_length(args->fl));
Andy Adamsond0179312008-12-23 16:06:17 -05001092 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001093 hdr->replen += decode_locku_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001094}
1095
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001096static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097{
1098 int len = name->len;
Al Viro8687b632006-10-19 23:28:48 -07001099 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100
Benny Halevy13c65ce2009-08-14 17:19:25 +03001101 p = reserve_space(xdr, 8 + len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001102 *p++ = cpu_to_be32(OP_LOOKUP);
1103 *p++ = cpu_to_be32(len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001104 p = xdr_encode_opaque_fixed(p, name->name, len);
Andy Adamsond0179312008-12-23 16:06:17 -05001105 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001106 hdr->replen += decode_lookup_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001107}
1108
Trond Myklebustdc0b0272008-12-23 15:21:56 -05001109static void encode_share_access(struct xdr_stream *xdr, fmode_t fmode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001110{
Al Viro8687b632006-10-19 23:28:48 -07001111 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001112
Benny Halevy13c65ce2009-08-14 17:19:25 +03001113 p = reserve_space(xdr, 8);
Trond Myklebustdc0b0272008-12-23 15:21:56 -05001114 switch (fmode & (FMODE_READ|FMODE_WRITE)) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001115 case FMODE_READ:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001116 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_READ);
Andy Adamson05d564f2008-12-23 16:06:15 -05001117 break;
1118 case FMODE_WRITE:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001119 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_WRITE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001120 break;
1121 case FMODE_READ|FMODE_WRITE:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001122 *p++ = cpu_to_be32(NFS4_SHARE_ACCESS_BOTH);
Andy Adamson05d564f2008-12-23 16:06:15 -05001123 break;
1124 default:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001125 *p++ = cpu_to_be32(0);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001126 }
Benny Halevye75bc1c2009-08-14 17:18:54 +03001127 *p++ = cpu_to_be32(0); /* for linux, share_deny = 0 always */
Linus Torvalds1da177e2005-04-16 15:20:36 -07001128}
1129
1130static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1131{
Al Viro8687b632006-10-19 23:28:48 -07001132 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 /*
1134 * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
1135 * owner 4 = 32
1136 */
Benny Halevy13c65ce2009-08-14 17:19:25 +03001137 p = reserve_space(xdr, 8);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001138 *p++ = cpu_to_be32(OP_OPEN);
1139 *p++ = cpu_to_be32(arg->seqid->sequence->counter);
Trond Myklebustdc0b0272008-12-23 15:21:56 -05001140 encode_share_access(xdr, arg->fmode);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001141 p = reserve_space(xdr, 28);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001142 p = xdr_encode_hyper(p, arg->clientid);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001143 *p++ = cpu_to_be32(16);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001144 p = xdr_encode_opaque_fixed(p, "open id:", 8);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001145 p = xdr_encode_hyper(p, arg->id);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001146}
1147
1148static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1149{
Al Viro8687b632006-10-19 23:28:48 -07001150 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001151
Benny Halevy13c65ce2009-08-14 17:19:25 +03001152 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001153 switch(arg->open_flags & O_EXCL) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001154 case 0:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001155 *p++ = cpu_to_be32(NFS4_CREATE_UNCHECKED);
Andy Adamson05d564f2008-12-23 16:06:15 -05001156 encode_attrs(xdr, arg->u.attrs, arg->server);
1157 break;
1158 default:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001159 *p++ = cpu_to_be32(NFS4_CREATE_EXCLUSIVE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001160 encode_nfs4_verifier(xdr, &arg->u.verifier);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001161 }
1162}
1163
1164static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
1165{
Al Viro8687b632006-10-19 23:28:48 -07001166 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001167
Benny Halevy13c65ce2009-08-14 17:19:25 +03001168 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001169 switch (arg->open_flags & O_CREAT) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001170 case 0:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001171 *p++ = cpu_to_be32(NFS4_OPEN_NOCREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001172 break;
1173 default:
1174 BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001175 *p++ = cpu_to_be32(NFS4_OPEN_CREATE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001176 encode_createmode(xdr, arg);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001177 }
1178}
1179
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001180static inline void encode_delegation_type(struct xdr_stream *xdr, fmode_t delegation_type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001181{
Al Viro8687b632006-10-19 23:28:48 -07001182 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001183
Benny Halevy13c65ce2009-08-14 17:19:25 +03001184 p = reserve_space(xdr, 4);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001185 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001186 case 0:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001187 *p++ = cpu_to_be32(NFS4_OPEN_DELEGATE_NONE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001188 break;
1189 case FMODE_READ:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001190 *p++ = cpu_to_be32(NFS4_OPEN_DELEGATE_READ);
Andy Adamson05d564f2008-12-23 16:06:15 -05001191 break;
1192 case FMODE_WRITE|FMODE_READ:
Benny Halevye75bc1c2009-08-14 17:18:54 +03001193 *p++ = cpu_to_be32(NFS4_OPEN_DELEGATE_WRITE);
Andy Adamson05d564f2008-12-23 16:06:15 -05001194 break;
1195 default:
1196 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001197 }
1198}
1199
1200static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
1201{
Al Viro8687b632006-10-19 23:28:48 -07001202 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001203
Benny Halevy13c65ce2009-08-14 17:19:25 +03001204 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001205 *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_NULL);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001206 encode_string(xdr, name->len, name->name);
1207}
1208
Trond Myklebustbd7bf9d2008-12-23 15:21:53 -05001209static inline void encode_claim_previous(struct xdr_stream *xdr, fmode_t type)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001210{
Al Viro8687b632006-10-19 23:28:48 -07001211 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001212
Benny Halevy13c65ce2009-08-14 17:19:25 +03001213 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001214 *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_PREVIOUS);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001215 encode_delegation_type(xdr, type);
1216}
1217
1218static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
1219{
Al Viro8687b632006-10-19 23:28:48 -07001220 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001221
Benny Halevy13c65ce2009-08-14 17:19:25 +03001222 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001223 *p++ = cpu_to_be32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001224 p = xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001225 encode_string(xdr, name->len, name->name);
1226}
1227
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001228static void encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001229{
1230 encode_openhdr(xdr, arg);
1231 encode_opentype(xdr, arg);
1232 switch (arg->claim) {
Andy Adamson05d564f2008-12-23 16:06:15 -05001233 case NFS4_OPEN_CLAIM_NULL:
1234 encode_claim_null(xdr, arg->name);
1235 break;
1236 case NFS4_OPEN_CLAIM_PREVIOUS:
1237 encode_claim_previous(xdr, arg->u.delegation_type);
1238 break;
1239 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
1240 encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
1241 break;
1242 default:
1243 BUG();
Linus Torvalds1da177e2005-04-16 15:20:36 -07001244 }
Andy Adamsond0179312008-12-23 16:06:17 -05001245 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001246 hdr->replen += decode_open_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001247}
1248
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001249static 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 -07001250{
Al Viro8687b632006-10-19 23:28:48 -07001251 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001252
Benny Halevy13c65ce2009-08-14 17:19:25 +03001253 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001254 *p++ = cpu_to_be32(OP_OPEN_CONFIRM);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001255 p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001256 *p++ = cpu_to_be32(arg->seqid->sequence->counter);
Andy Adamsond0179312008-12-23 16:06:17 -05001257 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001258 hdr->replen += decode_open_confirm_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001259}
1260
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001261static void encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001262{
Al Viro8687b632006-10-19 23:28:48 -07001263 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001264
Benny Halevy13c65ce2009-08-14 17:19:25 +03001265 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE+4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001266 *p++ = cpu_to_be32(OP_OPEN_DOWNGRADE);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001267 p = xdr_encode_opaque_fixed(p, arg->stateid->data, NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001268 *p++ = cpu_to_be32(arg->seqid->sequence->counter);
Trond Myklebustdc0b0272008-12-23 15:21:56 -05001269 encode_share_access(xdr, arg->fmode);
Andy Adamsond0179312008-12-23 16:06:17 -05001270 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001271 hdr->replen += decode_open_downgrade_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001272}
1273
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001274static void
Andy Adamsond0179312008-12-23 16:06:17 -05001275encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001276{
1277 int len = fh->size;
Al Viro8687b632006-10-19 23:28:48 -07001278 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001279
Benny Halevy13c65ce2009-08-14 17:19:25 +03001280 p = reserve_space(xdr, 8 + len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001281 *p++ = cpu_to_be32(OP_PUTFH);
1282 *p++ = cpu_to_be32(len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001283 p = xdr_encode_opaque_fixed(p, fh->data, len);
Andy Adamsond0179312008-12-23 16:06:17 -05001284 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001285 hdr->replen += decode_putfh_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001286}
1287
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001288static void encode_putrootfh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001289{
Andy Adamson05d564f2008-12-23 16:06:15 -05001290 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001291
Benny Halevy13c65ce2009-08-14 17:19:25 +03001292 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001293 *p++ = cpu_to_be32(OP_PUTROOTFH);
Andy Adamsond0179312008-12-23 16:06:17 -05001294 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001295 hdr->replen += decode_putrootfh_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001296}
1297
1298static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
1299{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001300 nfs4_stateid stateid;
Al Viro8687b632006-10-19 23:28:48 -07001301 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001302
Benny Halevy13c65ce2009-08-14 17:19:25 +03001303 p = reserve_space(xdr, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001304 if (ctx->state != NULL) {
1305 nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001306 p = xdr_encode_opaque_fixed(p, stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001307 } else
Benny Halevy93f0cf22009-08-14 17:19:06 +03001308 p = xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001309}
1310
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001311static void encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001312{
Al Viro8687b632006-10-19 23:28:48 -07001313 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001314
Benny Halevy13c65ce2009-08-14 17:19:25 +03001315 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001316 *p++ = cpu_to_be32(OP_READ);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001317
1318 encode_stateid(xdr, args->context);
1319
Benny Halevy13c65ce2009-08-14 17:19:25 +03001320 p = reserve_space(xdr, 12);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001321 p = xdr_encode_hyper(p, args->offset);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001322 *p++ = cpu_to_be32(args->count);
Andy Adamsond0179312008-12-23 16:06:17 -05001323 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001324 hdr->replen += decode_read_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001325}
1326
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001327static 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 -07001328{
Manoj Naik97d312d2005-06-22 17:16:39 +00001329 uint32_t attrs[2] = {
1330 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
1331 FATTR4_WORD1_MOUNTED_ON_FILEID,
1332 };
Al Viro8687b632006-10-19 23:28:48 -07001333 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001334
Benny Halevy13c65ce2009-08-14 17:19:25 +03001335 p = reserve_space(xdr, 12+NFS4_VERIFIER_SIZE+20);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001336 *p++ = cpu_to_be32(OP_READDIR);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001337 p = xdr_encode_hyper(p, readdir->cookie);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001338 p = xdr_encode_opaque_fixed(p, readdir->verifier.data, NFS4_VERIFIER_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001339 *p++ = cpu_to_be32(readdir->count >> 1); /* We're not doing readdirplus */
1340 *p++ = cpu_to_be32(readdir->count);
1341 *p++ = cpu_to_be32(2);
Manoj Naik97d312d2005-06-22 17:16:39 +00001342 /* Switch to mounted_on_fileid if the server supports it */
1343 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
1344 attrs[0] &= ~FATTR4_WORD0_FILEID;
1345 else
1346 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
Benny Halevye75bc1c2009-08-14 17:18:54 +03001347 *p++ = cpu_to_be32(attrs[0] & readdir->bitmask[0]);
1348 *p++ = cpu_to_be32(attrs[1] & readdir->bitmask[1]);
Andy Adamsond0179312008-12-23 16:06:17 -05001349 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001350 hdr->replen += decode_readdir_maxsz;
Fred Isaman44109242008-04-02 15:21:15 +03001351 dprintk("%s: cookie = %Lu, verifier = %08x:%08x, bitmap = %08x:%08x\n",
1352 __func__,
Trond Myklebusteadf4592005-06-22 17:16:39 +00001353 (unsigned long long)readdir->cookie,
1354 ((u32 *)readdir->verifier.data)[0],
1355 ((u32 *)readdir->verifier.data)[1],
1356 attrs[0] & readdir->bitmask[0],
1357 attrs[1] & readdir->bitmask[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001358}
1359
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001360static 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 -07001361{
Al Viro8687b632006-10-19 23:28:48 -07001362 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001363
Benny Halevy13c65ce2009-08-14 17:19:25 +03001364 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001365 *p++ = cpu_to_be32(OP_READLINK);
Andy Adamsond0179312008-12-23 16:06:17 -05001366 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001367 hdr->replen += decode_readlink_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001368}
1369
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001370static void encode_remove(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001371{
Al Viro8687b632006-10-19 23:28:48 -07001372 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001373
Benny Halevy13c65ce2009-08-14 17:19:25 +03001374 p = reserve_space(xdr, 8 + name->len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001375 *p++ = cpu_to_be32(OP_REMOVE);
1376 *p++ = cpu_to_be32(name->len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001377 p = xdr_encode_opaque_fixed(p, name->name, name->len);
Andy Adamsond0179312008-12-23 16:06:17 -05001378 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001379 hdr->replen += decode_remove_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001380}
1381
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001382static 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 -07001383{
Al Viro8687b632006-10-19 23:28:48 -07001384 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385
Benny Halevy13c65ce2009-08-14 17:19:25 +03001386 p = reserve_space(xdr, 8 + oldname->len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001387 *p++ = cpu_to_be32(OP_RENAME);
1388 *p++ = cpu_to_be32(oldname->len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001389 p = xdr_encode_opaque_fixed(p, oldname->name, oldname->len);
Andy Adamson6c0195a2008-12-23 16:06:15 -05001390
Benny Halevy13c65ce2009-08-14 17:19:25 +03001391 p = reserve_space(xdr, 4 + newname->len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001392 *p++ = cpu_to_be32(newname->len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001393 p = xdr_encode_opaque_fixed(p, newname->name, newname->len);
Andy Adamsond0179312008-12-23 16:06:17 -05001394 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001395 hdr->replen += decode_rename_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001396}
1397
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001398static void encode_renew(struct xdr_stream *xdr, const struct nfs_client *client_stateid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001399{
Al Viro8687b632006-10-19 23:28:48 -07001400 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001401
Benny Halevy13c65ce2009-08-14 17:19:25 +03001402 p = reserve_space(xdr, 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001403 *p++ = cpu_to_be32(OP_RENEW);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001404 p = xdr_encode_hyper(p, client_stateid->cl_clientid);
Andy Adamsond0179312008-12-23 16:06:17 -05001405 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001406 hdr->replen += decode_renew_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001407}
1408
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001409static void
Andy Adamsond0179312008-12-23 16:06:17 -05001410encode_restorefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001411{
Al Viro8687b632006-10-19 23:28:48 -07001412 __be32 *p;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001413
Benny Halevy13c65ce2009-08-14 17:19:25 +03001414 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001415 *p++ = cpu_to_be32(OP_RESTOREFH);
Andy Adamsond0179312008-12-23 16:06:17 -05001416 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001417 hdr->replen += decode_restorefh_maxsz;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001418}
1419
1420static int
Andy Adamsond0179312008-12-23 16:06:17 -05001421encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg, struct compound_hdr *hdr)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001422{
Al Viro8687b632006-10-19 23:28:48 -07001423 __be32 *p;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001424
Benny Halevy13c65ce2009-08-14 17:19:25 +03001425 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001426 *p++ = cpu_to_be32(OP_SETATTR);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001427 p = xdr_encode_opaque_fixed(p, zero_stateid.data, NFS4_STATEID_SIZE);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001428 p = reserve_space(xdr, 2*4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001429 *p++ = cpu_to_be32(1);
1430 *p++ = cpu_to_be32(FATTR4_WORD0_ACL);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001431 if (arg->acl_len % 4)
1432 return -EINVAL;
Benny Halevy13c65ce2009-08-14 17:19:25 +03001433 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001434 *p++ = cpu_to_be32(arg->acl_len);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001435 xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
Andy Adamsond0179312008-12-23 16:06:17 -05001436 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001437 hdr->replen += decode_setacl_maxsz;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001438 return 0;
1439}
1440
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001441static void
Andy Adamsond0179312008-12-23 16:06:17 -05001442encode_savefh(struct xdr_stream *xdr, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001443{
Al Viro8687b632006-10-19 23:28:48 -07001444 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001445
Benny Halevy13c65ce2009-08-14 17:19:25 +03001446 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001447 *p++ = cpu_to_be32(OP_SAVEFH);
Andy Adamsond0179312008-12-23 16:06:17 -05001448 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001449 hdr->replen += decode_savefh_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001450}
1451
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001452static 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 -07001453{
Al Viro8687b632006-10-19 23:28:48 -07001454 __be32 *p;
Andy Adamson6c0195a2008-12-23 16:06:15 -05001455
Benny Halevy13c65ce2009-08-14 17:19:25 +03001456 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001457 *p++ = cpu_to_be32(OP_SETATTR);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001458 p = xdr_encode_opaque_fixed(p, arg->stateid.data, NFS4_STATEID_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05001459 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001460 hdr->replen += decode_setattr_maxsz;
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001461 encode_attrs(xdr, arg->iap, server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001462}
1463
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001464static void encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465{
Al Viro8687b632006-10-19 23:28:48 -07001466 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001467
Benny Halevy13c65ce2009-08-14 17:19:25 +03001468 p = reserve_space(xdr, 4 + NFS4_VERIFIER_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001469 *p++ = cpu_to_be32(OP_SETCLIENTID);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001470 p = xdr_encode_opaque_fixed(p, setclientid->sc_verifier->data, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471
1472 encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001473 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001474 *p++ = cpu_to_be32(setclientid->sc_prog);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001475 encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
1476 encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
Benny Halevy13c65ce2009-08-14 17:19:25 +03001477 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001478 *p++ = cpu_to_be32(setclientid->sc_cb_ident);
Andy Adamsond0179312008-12-23 16:06:17 -05001479 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001480 hdr->replen += decode_setclientid_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001481}
1482
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001483static void encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs_client *client_state, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484{
Andy Adamson05d564f2008-12-23 16:06:15 -05001485 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001486
Benny Halevy13c65ce2009-08-14 17:19:25 +03001487 p = reserve_space(xdr, 12 + NFS4_VERIFIER_SIZE);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001488 *p++ = cpu_to_be32(OP_SETCLIENTID_CONFIRM);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001489 p = xdr_encode_hyper(p, client_state->cl_clientid);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001490 p = xdr_encode_opaque_fixed(p, client_state->cl_confirm.data, NFS4_VERIFIER_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05001491 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001492 hdr->replen += decode_setclientid_confirm_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001493}
1494
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001495static void encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001496{
Al Viro8687b632006-10-19 23:28:48 -07001497 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001498
Benny Halevy13c65ce2009-08-14 17:19:25 +03001499 p = reserve_space(xdr, 4);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001500 *p++ = cpu_to_be32(OP_WRITE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001501
1502 encode_stateid(xdr, args->context);
1503
Benny Halevy13c65ce2009-08-14 17:19:25 +03001504 p = reserve_space(xdr, 16);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001505 p = xdr_encode_hyper(p, args->offset);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001506 *p++ = cpu_to_be32(args->stable);
1507 *p++ = cpu_to_be32(args->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001508
1509 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
Andy Adamsond0179312008-12-23 16:06:17 -05001510 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001511 hdr->replen += decode_write_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001512}
1513
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001514static void encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid, struct compound_hdr *hdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001515{
Al Viro8687b632006-10-19 23:28:48 -07001516 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001517
Benny Halevy13c65ce2009-08-14 17:19:25 +03001518 p = reserve_space(xdr, 4+NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001519
Benny Halevye75bc1c2009-08-14 17:18:54 +03001520 *p++ = cpu_to_be32(OP_DELEGRETURN);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001521 p = xdr_encode_opaque_fixed(p, stateid->data, NFS4_STATEID_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05001522 hdr->nops++;
Benny Halevydadf0c22009-04-01 09:22:08 -04001523 hdr->replen += decode_delegreturn_maxsz;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001524}
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001525
Benny Halevy99fe60d2009-04-01 09:22:29 -04001526#if defined(CONFIG_NFS_V4_1)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001527/* NFSv4.1 operations */
Benny Halevy99fe60d2009-04-01 09:22:29 -04001528static void encode_exchange_id(struct xdr_stream *xdr,
1529 struct nfs41_exchange_id_args *args,
1530 struct compound_hdr *hdr)
1531{
1532 __be32 *p;
1533
Benny Halevy13c65ce2009-08-14 17:19:25 +03001534 p = reserve_space(xdr, 4 + sizeof(args->verifier->data));
Benny Halevye75bc1c2009-08-14 17:18:54 +03001535 *p++ = cpu_to_be32(OP_EXCHANGE_ID);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001536 p = xdr_encode_opaque_fixed(p, args->verifier->data, sizeof(args->verifier->data));
Benny Halevy99fe60d2009-04-01 09:22:29 -04001537
1538 encode_string(xdr, args->id_len, args->id);
1539
Benny Halevy13c65ce2009-08-14 17:19:25 +03001540 p = reserve_space(xdr, 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001541 *p++ = cpu_to_be32(args->flags);
1542 *p++ = cpu_to_be32(0); /* zero length state_protect4_a */
1543 *p++ = cpu_to_be32(0); /* zero length implementation id array */
Benny Halevy99fe60d2009-04-01 09:22:29 -04001544 hdr->nops++;
1545 hdr->replen += decode_exchange_id_maxsz;
1546}
Andy Adamsonfc931582009-04-01 09:22:31 -04001547
1548static void encode_create_session(struct xdr_stream *xdr,
1549 struct nfs41_create_session_args *args,
1550 struct compound_hdr *hdr)
1551{
1552 __be32 *p;
1553 char machine_name[NFS4_MAX_MACHINE_NAME_LEN];
1554 uint32_t len;
1555 struct nfs_client *clp = args->client;
1556
Benny Halevy42edd692009-08-14 17:19:13 +03001557 len = scnprintf(machine_name, sizeof(machine_name), "%s",
1558 clp->cl_ipaddr);
1559
Benny Halevy13c65ce2009-08-14 17:19:25 +03001560 p = reserve_space(xdr, 20 + 2*28 + 20 + len + 12);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001561 *p++ = cpu_to_be32(OP_CREATE_SESSION);
Benny Halevyb95be5a2009-08-14 17:19:01 +03001562 p = xdr_encode_hyper(p, clp->cl_ex_clid);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001563 *p++ = cpu_to_be32(clp->cl_seqid); /*Sequence id */
1564 *p++ = cpu_to_be32(args->flags); /*flags */
Andy Adamsonfc931582009-04-01 09:22:31 -04001565
Andy Adamsonfc931582009-04-01 09:22:31 -04001566 /* Fore Channel */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001567 *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
1568 *p++ = cpu_to_be32(args->fc_attrs.max_rqst_sz); /* max req size */
1569 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz); /* max resp size */
1570 *p++ = cpu_to_be32(args->fc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1571 *p++ = cpu_to_be32(args->fc_attrs.max_ops); /* max operations */
1572 *p++ = cpu_to_be32(args->fc_attrs.max_reqs); /* max requests */
1573 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001574
1575 /* Back Channel */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001576 *p++ = cpu_to_be32(args->fc_attrs.headerpadsz); /* header padding size */
1577 *p++ = cpu_to_be32(args->bc_attrs.max_rqst_sz); /* max req size */
1578 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz); /* max resp size */
1579 *p++ = cpu_to_be32(args->bc_attrs.max_resp_sz_cached); /* Max resp sz cached */
1580 *p++ = cpu_to_be32(args->bc_attrs.max_ops); /* max operations */
1581 *p++ = cpu_to_be32(args->bc_attrs.max_reqs); /* max requests */
1582 *p++ = cpu_to_be32(0); /* rdmachannel_attrs */
Andy Adamsonfc931582009-04-01 09:22:31 -04001583
Benny Halevye75bc1c2009-08-14 17:18:54 +03001584 *p++ = cpu_to_be32(args->cb_program); /* cb_program */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001585 *p++ = cpu_to_be32(1);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001586 *p++ = cpu_to_be32(RPC_AUTH_UNIX); /* auth_sys */
Andy Adamsonfc931582009-04-01 09:22:31 -04001587
1588 /* authsys_parms rfc1831 */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001589 *p++ = cpu_to_be32((u32)clp->cl_boot_time.tv_nsec); /* stamp */
Benny Halevye75bc1c2009-08-14 17:18:54 +03001590 *p++ = cpu_to_be32(len);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001591 p = xdr_encode_opaque_fixed(p, machine_name, len);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001592 *p++ = cpu_to_be32(0); /* UID */
1593 *p++ = cpu_to_be32(0); /* GID */
1594 *p++ = cpu_to_be32(0); /* No more gids */
Andy Adamsonfc931582009-04-01 09:22:31 -04001595 hdr->nops++;
1596 hdr->replen += decode_create_session_maxsz;
1597}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001598
1599static void encode_destroy_session(struct xdr_stream *xdr,
1600 struct nfs4_session *session,
1601 struct compound_hdr *hdr)
1602{
1603 __be32 *p;
Benny Halevy13c65ce2009-08-14 17:19:25 +03001604 p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001605 *p++ = cpu_to_be32(OP_DESTROY_SESSION);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001606 p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Andy Adamson0f3e66c2009-04-01 09:22:34 -04001607 hdr->nops++;
1608 hdr->replen += decode_destroy_session_maxsz;
1609}
Benny Halevy99fe60d2009-04-01 09:22:29 -04001610#endif /* CONFIG_NFS_V4_1 */
1611
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001612static void encode_sequence(struct xdr_stream *xdr,
1613 const struct nfs4_sequence_args *args,
1614 struct compound_hdr *hdr)
1615{
1616#if defined(CONFIG_NFS_V4_1)
1617 struct nfs4_session *session = args->sa_session;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001618 struct nfs4_slot_table *tp;
1619 struct nfs4_slot *slot;
1620 __be32 *p;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001621
1622 if (!session)
1623 return;
1624
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001625 tp = &session->fc_slot_table;
1626
1627 WARN_ON(args->sa_slotid == NFS4_MAX_SLOT_TABLE);
1628 slot = tp->slots + args->sa_slotid;
1629
Benny Halevy13c65ce2009-08-14 17:19:25 +03001630 p = reserve_space(xdr, 4 + NFS4_MAX_SESSIONID_LEN + 16);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001631 *p++ = cpu_to_be32(OP_SEQUENCE);
Andy Adamsonfc01cea2009-04-01 09:22:36 -04001632
1633 /*
1634 * Sessionid + seqid + slotid + max slotid + cache_this
1635 */
1636 dprintk("%s: sessionid=%u:%u:%u:%u seqid=%d slotid=%d "
1637 "max_slotid=%d cache_this=%d\n",
1638 __func__,
1639 ((u32 *)session->sess_id.data)[0],
1640 ((u32 *)session->sess_id.data)[1],
1641 ((u32 *)session->sess_id.data)[2],
1642 ((u32 *)session->sess_id.data)[3],
1643 slot->seq_nr, args->sa_slotid,
1644 tp->highest_used_slotid, args->sa_cache_this);
Benny Halevy93f0cf22009-08-14 17:19:06 +03001645 p = xdr_encode_opaque_fixed(p, session->sess_id.data, NFS4_MAX_SESSIONID_LEN);
Benny Halevye75bc1c2009-08-14 17:18:54 +03001646 *p++ = cpu_to_be32(slot->seq_nr);
1647 *p++ = cpu_to_be32(args->sa_slotid);
1648 *p++ = cpu_to_be32(tp->highest_used_slotid);
1649 *p++ = cpu_to_be32(args->sa_cache_this);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001650 hdr->nops++;
1651 hdr->replen += decode_sequence_maxsz;
1652#endif /* CONFIG_NFS_V4_1 */
1653}
1654
Linus Torvalds1da177e2005-04-16 15:20:36 -07001655/*
1656 * END OF "GENERIC" ENCODE ROUTINES.
1657 */
1658
Benny Halevy66cc0422009-04-01 09:22:10 -04001659static u32 nfs4_xdr_minorversion(const struct nfs4_sequence_args *args)
1660{
1661#if defined(CONFIG_NFS_V4_1)
1662 if (args->sa_session)
1663 return args->sa_session->clp->cl_minorversion;
1664#endif /* CONFIG_NFS_V4_1 */
1665 return 0;
1666}
1667
Linus Torvalds1da177e2005-04-16 15:20:36 -07001668/*
1669 * Encode an ACCESS request
1670 */
Al Viro8687b632006-10-19 23:28:48 -07001671static int nfs4_xdr_enc_access(struct rpc_rqst *req, __be32 *p, const struct nfs4_accessargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001672{
1673 struct xdr_stream xdr;
1674 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001675 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001676 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001677
1678 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001679 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001680 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001681 encode_putfh(&xdr, args->fh, &hdr);
1682 encode_access(&xdr, args->access, &hdr);
1683 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001684 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001685 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001686}
1687
1688/*
1689 * Encode LOOKUP request
1690 */
Al Viro8687b632006-10-19 23:28:48 -07001691static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001692{
1693 struct xdr_stream xdr;
1694 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001695 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001696 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001697
1698 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001699 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001700 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001701 encode_putfh(&xdr, args->dir_fh, &hdr);
1702 encode_lookup(&xdr, args->name, &hdr);
1703 encode_getfh(&xdr, &hdr);
1704 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001705 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001706 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001707}
1708
1709/*
1710 * Encode LOOKUP_ROOT request
1711 */
Al Viro8687b632006-10-19 23:28:48 -07001712static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, __be32 *p, const struct nfs4_lookup_root_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001713{
1714 struct xdr_stream xdr;
1715 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001716 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001717 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001718
1719 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001720 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001721 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001722 encode_putrootfh(&xdr, &hdr);
1723 encode_getfh(&xdr, &hdr);
1724 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001725 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001726 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001727}
1728
1729/*
1730 * Encode REMOVE request
1731 */
Trond Myklebust4fdc17b2007-07-14 15:39:57 -04001732static int nfs4_xdr_enc_remove(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001733{
1734 struct xdr_stream xdr;
1735 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001736 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001737 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001738
1739 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001740 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001741 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001742 encode_putfh(&xdr, args->fh, &hdr);
1743 encode_remove(&xdr, &args->name, &hdr);
1744 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001745 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001746 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001747}
1748
1749/*
1750 * Encode RENAME request
1751 */
Al Viro8687b632006-10-19 23:28:48 -07001752static int nfs4_xdr_enc_rename(struct rpc_rqst *req, __be32 *p, const struct nfs4_rename_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001753{
1754 struct xdr_stream xdr;
1755 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001756 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001757 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001758
1759 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001760 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001761 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001762 encode_putfh(&xdr, args->old_dir, &hdr);
1763 encode_savefh(&xdr, &hdr);
1764 encode_putfh(&xdr, args->new_dir, &hdr);
1765 encode_rename(&xdr, args->old_name, args->new_name, &hdr);
1766 encode_getfattr(&xdr, args->bitmask, &hdr);
1767 encode_restorefh(&xdr, &hdr);
1768 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001769 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001770 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001771}
1772
1773/*
1774 * Encode LINK request
1775 */
Al Viro8687b632006-10-19 23:28:48 -07001776static int nfs4_xdr_enc_link(struct rpc_rqst *req, __be32 *p, const struct nfs4_link_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001777{
1778 struct xdr_stream xdr;
1779 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001780 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001781 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001782
1783 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001784 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001785 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001786 encode_putfh(&xdr, args->fh, &hdr);
1787 encode_savefh(&xdr, &hdr);
1788 encode_putfh(&xdr, args->dir_fh, &hdr);
1789 encode_link(&xdr, args->name, &hdr);
1790 encode_getfattr(&xdr, args->bitmask, &hdr);
1791 encode_restorefh(&xdr, &hdr);
1792 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001793 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001794 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001795}
1796
1797/*
1798 * Encode CREATE request
1799 */
Al Viro8687b632006-10-19 23:28:48 -07001800static int nfs4_xdr_enc_create(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001801{
1802 struct xdr_stream xdr;
1803 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001804 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001805 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001806
1807 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001808 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001809 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001810 encode_putfh(&xdr, args->dir_fh, &hdr);
1811 encode_savefh(&xdr, &hdr);
1812 encode_create(&xdr, args, &hdr);
1813 encode_getfh(&xdr, &hdr);
1814 encode_getfattr(&xdr, args->bitmask, &hdr);
1815 encode_restorefh(&xdr, &hdr);
1816 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001817 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001818 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001819}
1820
1821/*
1822 * Encode SYMLINK request
1823 */
Al Viro8687b632006-10-19 23:28:48 -07001824static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_create_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001825{
1826 return nfs4_xdr_enc_create(req, p, args);
1827}
1828
1829/*
1830 * Encode GETATTR request
1831 */
Al Viro8687b632006-10-19 23:28:48 -07001832static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, __be32 *p, const struct nfs4_getattr_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001833{
1834 struct xdr_stream xdr;
1835 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001836 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001837 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001838
1839 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001840 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001841 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001842 encode_putfh(&xdr, args->fh, &hdr);
1843 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001844 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001845 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001846}
1847
1848/*
1849 * Encode a CLOSE request
1850 */
Al Viro8687b632006-10-19 23:28:48 -07001851static int nfs4_xdr_enc_close(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001852{
Andy Adamson05d564f2008-12-23 16:06:15 -05001853 struct xdr_stream xdr;
1854 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001855 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05001856 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001857
Andy Adamson05d564f2008-12-23 16:06:15 -05001858 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001859 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001860 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001861 encode_putfh(&xdr, args->fh, &hdr);
1862 encode_close(&xdr, args, &hdr);
1863 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001864 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001865 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001866}
1867
1868/*
1869 * Encode an OPEN request
1870 */
Al Viro8687b632006-10-19 23:28:48 -07001871static int nfs4_xdr_enc_open(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001872{
1873 struct xdr_stream xdr;
1874 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001875 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001876 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001877
1878 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001879 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001880 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001881 encode_putfh(&xdr, args->fh, &hdr);
1882 encode_savefh(&xdr, &hdr);
1883 encode_open(&xdr, args, &hdr);
1884 encode_getfh(&xdr, &hdr);
1885 encode_getfattr(&xdr, args->bitmask, &hdr);
1886 encode_restorefh(&xdr, &hdr);
1887 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001888 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001889 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001890}
1891
1892/*
1893 * Encode an OPEN_CONFIRM request
1894 */
Al Viro8687b632006-10-19 23:28:48 -07001895static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_open_confirmargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001896{
1897 struct xdr_stream xdr;
1898 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05001899 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001900 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001901
1902 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001903 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001904 encode_putfh(&xdr, args->fh, &hdr);
1905 encode_open_confirm(&xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001906 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001907 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001908}
1909
1910/*
1911 * Encode an OPEN request with no attributes.
1912 */
Al Viro8687b632006-10-19 23:28:48 -07001913static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, __be32 *p, struct nfs_openargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001914{
1915 struct xdr_stream xdr;
1916 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001917 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001918 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001919
1920 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001921 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001922 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001923 encode_putfh(&xdr, args->fh, &hdr);
1924 encode_open(&xdr, args, &hdr);
1925 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001926 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001927 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001928}
1929
1930/*
1931 * Encode an OPEN_DOWNGRADE request
1932 */
Al Viro8687b632006-10-19 23:28:48 -07001933static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, __be32 *p, struct nfs_closeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001934{
1935 struct xdr_stream xdr;
1936 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001937 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001938 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001939
1940 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001941 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001942 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001943 encode_putfh(&xdr, args->fh, &hdr);
1944 encode_open_downgrade(&xdr, args, &hdr);
1945 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001946 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001947 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001948}
1949
1950/*
1951 * Encode a LOCK request
1952 */
Al Viro8687b632006-10-19 23:28:48 -07001953static int nfs4_xdr_enc_lock(struct rpc_rqst *req, __be32 *p, struct nfs_lock_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001954{
1955 struct xdr_stream xdr;
1956 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001957 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001958 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001959
1960 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001961 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001962 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001963 encode_putfh(&xdr, args->fh, &hdr);
1964 encode_lock(&xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001965 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001966 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001967}
1968
1969/*
1970 * Encode a LOCKT request
1971 */
Al Viro8687b632006-10-19 23:28:48 -07001972static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, __be32 *p, struct nfs_lockt_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001973{
1974 struct xdr_stream xdr;
1975 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001976 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001977 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001978
1979 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001980 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04001981 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001982 encode_putfh(&xdr, args->fh, &hdr);
1983 encode_lockt(&xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05001984 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05001985 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001986}
1987
1988/*
1989 * Encode a LOCKU request
1990 */
Al Viro8687b632006-10-19 23:28:48 -07001991static int nfs4_xdr_enc_locku(struct rpc_rqst *req, __be32 *p, struct nfs_locku_args *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001992{
1993 struct xdr_stream xdr;
1994 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04001995 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001996 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001997
1998 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04001999 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002000 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002001 encode_putfh(&xdr, args->fh, &hdr);
2002 encode_locku(&xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002003 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002004 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002005}
2006
2007/*
2008 * Encode a READLINK request
2009 */
Al Viro8687b632006-10-19 23:28:48 -07002010static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, __be32 *p, const struct nfs4_readlink *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002011{
2012 struct xdr_stream xdr;
2013 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002014 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002015 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002016
2017 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002018 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002019 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002020 encode_putfh(&xdr, args->fh, &hdr);
2021 encode_readlink(&xdr, args, req, &hdr);
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002022
Benny Halevy28f56692009-04-01 09:22:09 -04002023 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebuste3a535e2007-07-19 10:03:38 -04002024 args->pgbase, args->pglen);
Andy Adamsond0179312008-12-23 16:06:17 -05002025 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002026 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002027}
2028
2029/*
2030 * Encode a READDIR request
2031 */
Al Viro8687b632006-10-19 23:28:48 -07002032static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, __be32 *p, const struct nfs4_readdir_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002033{
2034 struct xdr_stream xdr;
2035 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002036 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002037 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002038
2039 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002040 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002041 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002042 encode_putfh(&xdr, args->fh, &hdr);
2043 encode_readdir(&xdr, args, req, &hdr);
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002044
Benny Halevy28f56692009-04-01 09:22:09 -04002045 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002046 args->pgbase, args->count);
2047 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
Benny Halevy28f56692009-04-01 09:22:09 -04002048 __func__, hdr.replen << 2, args->pages,
Trond Myklebustd6ac02d2007-07-19 10:03:37 -04002049 args->pgbase, args->count);
Andy Adamsond0179312008-12-23 16:06:17 -05002050 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002051 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002052}
2053
2054/*
2055 * Encode a READ request
2056 */
Al Viro8687b632006-10-19 23:28:48 -07002057static int nfs4_xdr_enc_read(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002058{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002059 struct xdr_stream xdr;
2060 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002061 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002062 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002063
2064 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002065 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002066 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002067 encode_putfh(&xdr, args->fh, &hdr);
2068 encode_read(&xdr, args, &hdr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002069
Benny Halevy28f56692009-04-01 09:22:09 -04002070 xdr_inline_pages(&req->rq_rcv_buf, hdr.replen << 2,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002071 args->pages, args->pgbase, args->count);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002072 req->rq_rcv_buf.flags |= XDRBUF_READ;
Andy Adamsond0179312008-12-23 16:06:17 -05002073 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002074 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002075}
2076
2077/*
2078 * Encode an SETATTR request
2079 */
Al Viro8687b632006-10-19 23:28:48 -07002080static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, __be32 *p, struct nfs_setattrargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002081{
Andy Adamson05d564f2008-12-23 16:06:15 -05002082 struct xdr_stream xdr;
2083 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002084 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05002085 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002086
Andy Adamson05d564f2008-12-23 16:06:15 -05002087 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002088 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002089 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002090 encode_putfh(&xdr, args->fh, &hdr);
2091 encode_setattr(&xdr, args, args->server, &hdr);
2092 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002093 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002094 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002095}
2096
2097/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00002098 * Encode a GETACL request
2099 */
2100static int
Al Viro8687b632006-10-19 23:28:48 -07002101nfs4_xdr_enc_getacl(struct rpc_rqst *req, __be32 *p,
J. Bruce Fields029d1052005-06-22 17:16:22 +00002102 struct nfs_getaclargs *args)
2103{
2104 struct xdr_stream xdr;
J. Bruce Fields029d1052005-06-22 17:16:22 +00002105 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002106 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
J. Bruce Fields029d1052005-06-22 17:16:22 +00002107 };
Benny Halevy28f56692009-04-01 09:22:09 -04002108 uint32_t replen;
J. Bruce Fields029d1052005-06-22 17:16:22 +00002109
2110 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002111 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002112 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002113 encode_putfh(&xdr, args->fh, &hdr);
Benny Halevy28f56692009-04-01 09:22:09 -04002114 replen = hdr.replen + nfs4_fattr_bitmap_maxsz + 1;
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002115 encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0, &hdr);
2116
Benny Halevy28f56692009-04-01 09:22:09 -04002117 xdr_inline_pages(&req->rq_rcv_buf, replen << 2,
J. Bruce Fields029d1052005-06-22 17:16:22 +00002118 args->acl_pages, args->acl_pgbase, args->acl_len);
Andy Adamsond0179312008-12-23 16:06:17 -05002119 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002120 return 0;
J. Bruce Fields029d1052005-06-22 17:16:22 +00002121}
2122
2123/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002124 * Encode a WRITE request
2125 */
Al Viro8687b632006-10-19 23:28:48 -07002126static int nfs4_xdr_enc_write(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002127{
2128 struct xdr_stream xdr;
2129 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002130 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002131 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002132
2133 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002134 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002135 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002136 encode_putfh(&xdr, args->fh, &hdr);
2137 encode_write(&xdr, args, &hdr);
\"Talpey, Thomas\4f22ccc2007-09-10 13:44:58 -04002138 req->rq_snd_buf.flags |= XDRBUF_WRITE;
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002139 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002140 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002141 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002142}
2143
2144/*
2145 * a COMMIT request
2146 */
Al Viro8687b632006-10-19 23:28:48 -07002147static int nfs4_xdr_enc_commit(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002148{
2149 struct xdr_stream xdr;
2150 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002151 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002152 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002153
2154 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002155 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002156 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002157 encode_putfh(&xdr, args->fh, &hdr);
2158 encode_commit(&xdr, args, &hdr);
2159 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002160 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002161 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002162}
2163
2164/*
2165 * FSINFO request
2166 */
Al Viro8687b632006-10-19 23:28:48 -07002167static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, __be32 *p, struct nfs4_fsinfo_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002168{
2169 struct xdr_stream xdr;
2170 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002171 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002172 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002173
2174 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002175 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002176 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002177 encode_putfh(&xdr, args->fh, &hdr);
2178 encode_fsinfo(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002179 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002180 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002181}
2182
2183/*
2184 * a PATHCONF request
2185 */
Al Viro8687b632006-10-19 23:28:48 -07002186static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, __be32 *p, const struct nfs4_pathconf_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002187{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002188 struct xdr_stream xdr;
2189 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002190 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002191 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002192
2193 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002194 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002195 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002196 encode_putfh(&xdr, args->fh, &hdr);
2197 encode_getattr_one(&xdr, args->bitmask[0] & nfs4_pathconf_bitmap[0],
2198 &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002199 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002200 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002201}
2202
2203/*
2204 * a STATFS request
2205 */
Al Viro8687b632006-10-19 23:28:48 -07002206static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, __be32 *p, const struct nfs4_statfs_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002207{
Linus Torvalds1da177e2005-04-16 15:20:36 -07002208 struct xdr_stream xdr;
2209 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002210 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002211 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002212
2213 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002214 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002215 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002216 encode_putfh(&xdr, args->fh, &hdr);
2217 encode_getattr_two(&xdr, args->bitmask[0] & nfs4_statfs_bitmap[0],
2218 args->bitmask[1] & nfs4_statfs_bitmap[1], &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002219 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002220 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002221}
2222
2223/*
2224 * GETATTR_BITMAP request
2225 */
Benny Halevy43652ad2009-04-01 09:21:54 -04002226static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, __be32 *p,
2227 struct nfs4_server_caps_arg *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002228{
2229 struct xdr_stream xdr;
2230 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002231 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002232 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002233
2234 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002235 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002236 encode_sequence(&xdr, &args->seq_args, &hdr);
Benny Halevy43652ad2009-04-01 09:21:54 -04002237 encode_putfh(&xdr, args->fhandle, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002238 encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
2239 FATTR4_WORD0_LINK_SUPPORT|
2240 FATTR4_WORD0_SYMLINK_SUPPORT|
2241 FATTR4_WORD0_ACLSUPPORT, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002242 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002243 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002244}
2245
2246/*
2247 * a RENEW request
2248 */
Al Viro8687b632006-10-19 23:28:48 -07002249static int nfs4_xdr_enc_renew(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002250{
2251 struct xdr_stream xdr;
2252 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002253 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002254 };
2255
2256 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002257 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002258 encode_renew(&xdr, clp, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002259 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002260 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002261}
2262
2263/*
2264 * a SETCLIENTID request
2265 */
Al Viro8687b632006-10-19 23:28:48 -07002266static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, __be32 *p, struct nfs4_setclientid *sc)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002267{
2268 struct xdr_stream xdr;
2269 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002270 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002271 };
2272
2273 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002274 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002275 encode_setclientid(&xdr, sc, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002276 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002277 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002278}
2279
2280/*
2281 * a SETCLIENTID_CONFIRM request
2282 */
Al Viro8687b632006-10-19 23:28:48 -07002283static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002284{
2285 struct xdr_stream xdr;
2286 struct compound_hdr hdr = {
Andy Adamsond0179312008-12-23 16:06:17 -05002287 .nops = 0,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002288 };
2289 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002290
2291 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002292 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002293 encode_setclientid_confirm(&xdr, clp, &hdr);
2294 encode_putrootfh(&xdr, &hdr);
2295 encode_fsinfo(&xdr, lease_bitmap, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002296 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002297 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002298}
2299
2300/*
2301 * DELEGRETURN request
2302 */
Al Viro8687b632006-10-19 23:28:48 -07002303static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, __be32 *p, const struct nfs4_delegreturnargs *args)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002304{
2305 struct xdr_stream xdr;
2306 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002307 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002308 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07002309
2310 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002311 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002312 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002313 encode_putfh(&xdr, args->fhandle, &hdr);
2314 encode_delegreturn(&xdr, args->stateid, &hdr);
2315 encode_getfattr(&xdr, args->bitmask, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05002316 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002317 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002318}
2319
2320/*
Trond Myklebust683b57b2006-06-09 09:34:22 -04002321 * Encode FS_LOCATIONS request
2322 */
Al Viro8687b632006-10-19 23:28:48 -07002323static int nfs4_xdr_enc_fs_locations(struct rpc_rqst *req, __be32 *p, struct nfs4_fs_locations_arg *args)
Trond Myklebust683b57b2006-06-09 09:34:22 -04002324{
2325 struct xdr_stream xdr;
2326 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04002327 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Trond Myklebust683b57b2006-06-09 09:34:22 -04002328 };
Benny Halevy28f56692009-04-01 09:22:09 -04002329 uint32_t replen;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002330
2331 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04002332 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04002333 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002334 encode_putfh(&xdr, args->dir_fh, &hdr);
2335 encode_lookup(&xdr, args->name, &hdr);
Benny Halevy28f56692009-04-01 09:22:09 -04002336 replen = hdr.replen; /* get the attribute into args->page */
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002337 encode_fs_locations(&xdr, args->bitmask, &hdr);
2338
Benny Halevy28f56692009-04-01 09:22:09 -04002339 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, &args->page,
Trond Myklebust683b57b2006-06-09 09:34:22 -04002340 0, PAGE_SIZE);
Andy Adamsond0179312008-12-23 16:06:17 -05002341 encode_nops(&hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05002342 return 0;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002343}
2344
Benny Halevy99fe60d2009-04-01 09:22:29 -04002345#if defined(CONFIG_NFS_V4_1)
2346/*
2347 * EXCHANGE_ID request
2348 */
2349static int nfs4_xdr_enc_exchange_id(struct rpc_rqst *req, uint32_t *p,
2350 struct nfs41_exchange_id_args *args)
2351{
2352 struct xdr_stream xdr;
2353 struct compound_hdr hdr = {
2354 .minorversion = args->client->cl_minorversion,
2355 };
2356
2357 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2358 encode_compound_hdr(&xdr, req, &hdr);
2359 encode_exchange_id(&xdr, args, &hdr);
2360 encode_nops(&hdr);
2361 return 0;
2362}
Andy Adamson2050f0c2009-04-01 09:22:30 -04002363
2364/*
Andy Adamsonfc931582009-04-01 09:22:31 -04002365 * a CREATE_SESSION request
2366 */
2367static int nfs4_xdr_enc_create_session(struct rpc_rqst *req, uint32_t *p,
2368 struct nfs41_create_session_args *args)
2369{
2370 struct xdr_stream xdr;
2371 struct compound_hdr hdr = {
2372 .minorversion = args->client->cl_minorversion,
2373 };
2374
2375 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2376 encode_compound_hdr(&xdr, req, &hdr);
2377 encode_create_session(&xdr, args, &hdr);
2378 encode_nops(&hdr);
2379 return 0;
2380}
2381
2382/*
Andy Adamson0f3e66c2009-04-01 09:22:34 -04002383 * a DESTROY_SESSION request
2384 */
2385static int nfs4_xdr_enc_destroy_session(struct rpc_rqst *req, uint32_t *p,
2386 struct nfs4_session *session)
2387{
2388 struct xdr_stream xdr;
2389 struct compound_hdr hdr = {
2390 .minorversion = session->clp->cl_minorversion,
2391 };
2392
2393 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2394 encode_compound_hdr(&xdr, req, &hdr);
2395 encode_destroy_session(&xdr, session, &hdr);
2396 encode_nops(&hdr);
2397 return 0;
2398}
2399
2400/*
Andy Adamsonfc01cea2009-04-01 09:22:36 -04002401 * a SEQUENCE request
2402 */
2403static int nfs4_xdr_enc_sequence(struct rpc_rqst *req, uint32_t *p,
2404 struct nfs4_sequence_args *args)
2405{
2406 struct xdr_stream xdr;
2407 struct compound_hdr hdr = {
2408 .minorversion = nfs4_xdr_minorversion(args),
2409 };
2410
2411 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2412 encode_compound_hdr(&xdr, req, &hdr);
2413 encode_sequence(&xdr, args, &hdr);
2414 encode_nops(&hdr);
2415 return 0;
2416}
2417
2418/*
Andy Adamson2050f0c2009-04-01 09:22:30 -04002419 * a GET_LEASE_TIME request
2420 */
2421static int nfs4_xdr_enc_get_lease_time(struct rpc_rqst *req, uint32_t *p,
2422 struct nfs4_get_lease_time_args *args)
2423{
2424 struct xdr_stream xdr;
2425 struct compound_hdr hdr = {
2426 .minorversion = nfs4_xdr_minorversion(&args->la_seq_args),
2427 };
2428 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
2429
2430 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
2431 encode_compound_hdr(&xdr, req, &hdr);
2432 encode_sequence(&xdr, &args->la_seq_args, &hdr);
2433 encode_putrootfh(&xdr, &hdr);
2434 encode_fsinfo(&xdr, lease_bitmap, &hdr);
2435 encode_nops(&hdr);
2436 return 0;
2437}
Benny Halevy99fe60d2009-04-01 09:22:29 -04002438#endif /* CONFIG_NFS_V4_1 */
2439
Trond Myklebust683b57b2006-06-09 09:34:22 -04002440/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07002441 * START OF "GENERIC" DECODE ROUTINES.
2442 * These may look a little ugly since they are imported from a "generic"
2443 * set of XDR encode/decode routines which are intended to be shared by
2444 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
2445 *
2446 * If the pain of reading these is too great, it should be a straightforward
2447 * task to translate them into Linux-specific versions which are more
2448 * consistent with the style used in NFSv2/v3...
2449 */
2450#define READ32(x) (x) = ntohl(*p++)
2451#define READ64(x) do { \
2452 (x) = (u64)ntohl(*p++) << 32; \
2453 (x) |= ntohl(*p++); \
2454} while (0)
2455#define READTIME(x) do { \
2456 p++; \
2457 (x.tv_sec) = ntohl(*p++); \
2458 (x.tv_nsec) = ntohl(*p++); \
2459} while (0)
2460#define COPYMEM(x,nbytes) do { \
2461 memcpy((x), p, nbytes); \
2462 p += XDR_QUADLEN(nbytes); \
2463} while (0)
2464
2465#define READ_BUF(nbytes) do { \
2466 p = xdr_inline_decode(xdr, nbytes); \
Chuck Levere4cc6ee2007-05-08 18:23:28 -04002467 if (unlikely(!p)) { \
Chuck Leverfe82a182007-09-11 18:01:10 -04002468 dprintk("nfs: %s: prematurely hit end of receive" \
Harvey Harrison3110ff82008-05-02 13:42:44 -07002469 " buffer\n", __func__); \
Chuck Leverfe82a182007-09-11 18:01:10 -04002470 dprintk("nfs: %s: xdr->p=%p, bytes=%u, xdr->end=%p\n", \
Harvey Harrison3110ff82008-05-02 13:42:44 -07002471 __func__, xdr->p, nbytes, xdr->end); \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002472 return -EIO; \
2473 } \
2474} while (0)
2475
Trond Myklebust683b57b2006-06-09 09:34:22 -04002476static int decode_opaque_inline(struct xdr_stream *xdr, unsigned int *len, char **string)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002477{
Al Viro8687b632006-10-19 23:28:48 -07002478 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002479
2480 READ_BUF(4);
2481 READ32(*len);
2482 READ_BUF(*len);
2483 *string = (char *)p;
2484 return 0;
2485}
2486
2487static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
2488{
Al Viro8687b632006-10-19 23:28:48 -07002489 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002490
2491 READ_BUF(8);
2492 READ32(hdr->status);
2493 READ32(hdr->taglen);
Andy Adamson6c0195a2008-12-23 16:06:15 -05002494
Linus Torvalds1da177e2005-04-16 15:20:36 -07002495 READ_BUF(hdr->taglen + 4);
2496 hdr->tag = (char *)p;
2497 p += XDR_QUADLEN(hdr->taglen);
2498 READ32(hdr->nops);
Benny Halevyaadf6152008-12-23 16:06:13 -05002499 if (unlikely(hdr->nops < 1))
2500 return nfs4_stat_to_errno(hdr->status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002501 return 0;
2502}
2503
2504static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
2505{
Al Viro8687b632006-10-19 23:28:48 -07002506 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002507 uint32_t opnum;
2508 int32_t nfserr;
2509
2510 READ_BUF(8);
2511 READ32(opnum);
2512 if (opnum != expected) {
Chuck Leverfe82a182007-09-11 18:01:10 -04002513 dprintk("nfs: Server returned operation"
2514 " %d but we issued a request for %d\n",
Linus Torvalds1da177e2005-04-16 15:20:36 -07002515 opnum, expected);
2516 return -EIO;
2517 }
2518 READ32(nfserr);
2519 if (nfserr != NFS_OK)
Benny Halevy856dff32008-03-31 17:39:06 +03002520 return nfs4_stat_to_errno(nfserr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002521 return 0;
2522}
2523
2524/* Dummy routine */
David Howellsadfa6f92006-08-22 20:06:08 -04002525static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002526{
Al Viro8687b632006-10-19 23:28:48 -07002527 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002528 unsigned int strlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002529 char *str;
2530
2531 READ_BUF(12);
2532 return decode_opaque_inline(xdr, &strlen, &str);
2533}
2534
2535static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
2536{
Al Viro8687b632006-10-19 23:28:48 -07002537 uint32_t bmlen;
2538 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002539
2540 READ_BUF(4);
2541 READ32(bmlen);
2542
2543 bitmap[0] = bitmap[1] = 0;
2544 READ_BUF((bmlen << 2));
2545 if (bmlen > 0) {
2546 READ32(bitmap[0]);
2547 if (bmlen > 1)
2548 READ32(bitmap[1]);
2549 }
2550 return 0;
2551}
2552
Al Viro8687b632006-10-19 23:28:48 -07002553static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, __be32 **savep)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002554{
Al Viro8687b632006-10-19 23:28:48 -07002555 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002556
2557 READ_BUF(4);
2558 READ32(*attrlen);
2559 *savep = xdr->p;
2560 return 0;
2561}
2562
2563static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
2564{
2565 if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
2566 decode_attr_bitmap(xdr, bitmask);
2567 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
2568 } else
2569 bitmask[0] = bitmask[1] = 0;
Fred Isaman44109242008-04-02 15:21:15 +03002570 dprintk("%s: bitmask=%08x:%08x\n", __func__, bitmask[0], bitmask[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002571 return 0;
2572}
2573
2574static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
2575{
Al Viro8687b632006-10-19 23:28:48 -07002576 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002577 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002578
2579 *type = 0;
2580 if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
2581 return -EIO;
2582 if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
2583 READ_BUF(4);
2584 READ32(*type);
2585 if (*type < NF4REG || *type > NF4NAMEDATTR) {
Harvey Harrison3110ff82008-05-02 13:42:44 -07002586 dprintk("%s: bad type %d\n", __func__, *type);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002587 return -EIO;
2588 }
2589 bitmap[0] &= ~FATTR4_WORD0_TYPE;
Trond Myklebust409924e2009-03-11 14:10:27 -04002590 ret = NFS_ATTR_FATTR_TYPE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002591 }
Trond Myklebustbca79472009-03-11 14:10:26 -04002592 dprintk("%s: type=0%o\n", __func__, nfs_type2fmt[*type]);
Trond Myklebust409924e2009-03-11 14:10:27 -04002593 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002594}
2595
2596static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
2597{
Al Viro8687b632006-10-19 23:28:48 -07002598 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002599 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002600
2601 *change = 0;
2602 if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
2603 return -EIO;
2604 if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
2605 READ_BUF(8);
2606 READ64(*change);
2607 bitmap[0] &= ~FATTR4_WORD0_CHANGE;
Trond Myklebust409924e2009-03-11 14:10:27 -04002608 ret = NFS_ATTR_FATTR_CHANGE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002609 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002610 dprintk("%s: change attribute=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002611 (unsigned long long)*change);
Trond Myklebust409924e2009-03-11 14:10:27 -04002612 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002613}
2614
2615static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
2616{
Al Viro8687b632006-10-19 23:28:48 -07002617 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002618 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002619
2620 *size = 0;
2621 if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
2622 return -EIO;
2623 if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
2624 READ_BUF(8);
2625 READ64(*size);
2626 bitmap[0] &= ~FATTR4_WORD0_SIZE;
Trond Myklebust409924e2009-03-11 14:10:27 -04002627 ret = NFS_ATTR_FATTR_SIZE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002628 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002629 dprintk("%s: file size=%Lu\n", __func__, (unsigned long long)*size);
Trond Myklebust409924e2009-03-11 14:10:27 -04002630 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002631}
2632
2633static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2634{
Al Viro8687b632006-10-19 23:28:48 -07002635 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002636
2637 *res = 0;
2638 if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
2639 return -EIO;
2640 if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
2641 READ_BUF(4);
2642 READ32(*res);
2643 bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
2644 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002645 dprintk("%s: link support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002646 return 0;
2647}
2648
2649static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2650{
Al Viro8687b632006-10-19 23:28:48 -07002651 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002652
2653 *res = 0;
2654 if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
2655 return -EIO;
2656 if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
2657 READ_BUF(4);
2658 READ32(*res);
2659 bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
2660 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002661 dprintk("%s: symlink support=%s\n", __func__, *res == 0 ? "false" : "true");
Linus Torvalds1da177e2005-04-16 15:20:36 -07002662 return 0;
2663}
2664
Trond Myklebust8b4bdcf2006-06-09 09:34:19 -04002665static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_fsid *fsid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002666{
Al Viro8687b632006-10-19 23:28:48 -07002667 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002668 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002669
2670 fsid->major = 0;
2671 fsid->minor = 0;
2672 if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
2673 return -EIO;
2674 if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
2675 READ_BUF(16);
2676 READ64(fsid->major);
2677 READ64(fsid->minor);
2678 bitmap[0] &= ~FATTR4_WORD0_FSID;
Trond Myklebust409924e2009-03-11 14:10:27 -04002679 ret = NFS_ATTR_FATTR_FSID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002680 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002681 dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07002682 (unsigned long long)fsid->major,
2683 (unsigned long long)fsid->minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04002684 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002685}
2686
2687static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2688{
Al Viro8687b632006-10-19 23:28:48 -07002689 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002690
2691 *res = 60;
2692 if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
2693 return -EIO;
2694 if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
2695 READ_BUF(4);
2696 READ32(*res);
2697 bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
2698 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002699 dprintk("%s: file size=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002700 return 0;
2701}
2702
2703static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2704{
Al Viro8687b632006-10-19 23:28:48 -07002705 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002706
2707 *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
2708 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
2709 return -EIO;
2710 if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
2711 READ_BUF(4);
2712 READ32(*res);
2713 bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
2714 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002715 dprintk("%s: ACLs supported=%u\n", __func__, (unsigned int)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002716 return 0;
2717}
2718
2719static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
2720{
Al Viro8687b632006-10-19 23:28:48 -07002721 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002722 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002723
2724 *fileid = 0;
2725 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
2726 return -EIO;
2727 if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
2728 READ_BUF(8);
2729 READ64(*fileid);
2730 bitmap[0] &= ~FATTR4_WORD0_FILEID;
Trond Myklebust409924e2009-03-11 14:10:27 -04002731 ret = NFS_ATTR_FATTR_FILEID;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002732 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002733 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04002734 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002735}
2736
Manoj Naik99baf622006-06-09 09:34:24 -04002737static int decode_attr_mounted_on_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
2738{
Al Viro8687b632006-10-19 23:28:48 -07002739 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04002740 int ret = 0;
Manoj Naik99baf622006-06-09 09:34:24 -04002741
2742 *fileid = 0;
2743 if (unlikely(bitmap[1] & (FATTR4_WORD1_MOUNTED_ON_FILEID - 1U)))
2744 return -EIO;
2745 if (likely(bitmap[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)) {
2746 READ_BUF(8);
2747 READ64(*fileid);
2748 bitmap[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
Trond Myklebust409924e2009-03-11 14:10:27 -04002749 ret = NFS_ATTR_FATTR_FILEID;
Manoj Naik99baf622006-06-09 09:34:24 -04002750 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002751 dprintk("%s: fileid=%Lu\n", __func__, (unsigned long long)*fileid);
Trond Myklebust409924e2009-03-11 14:10:27 -04002752 return ret;
Manoj Naik99baf622006-06-09 09:34:24 -04002753}
2754
Linus Torvalds1da177e2005-04-16 15:20:36 -07002755static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2756{
Al Viro8687b632006-10-19 23:28:48 -07002757 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002758 int status = 0;
2759
2760 *res = 0;
2761 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
2762 return -EIO;
2763 if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
2764 READ_BUF(8);
2765 READ64(*res);
2766 bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
2767 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002768 dprintk("%s: files avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002769 return status;
2770}
2771
2772static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2773{
Al Viro8687b632006-10-19 23:28:48 -07002774 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002775 int status = 0;
2776
2777 *res = 0;
2778 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
2779 return -EIO;
2780 if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
2781 READ_BUF(8);
2782 READ64(*res);
2783 bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
2784 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002785 dprintk("%s: files free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002786 return status;
2787}
2788
2789static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2790{
Al Viro8687b632006-10-19 23:28:48 -07002791 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002792 int status = 0;
2793
2794 *res = 0;
2795 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
2796 return -EIO;
2797 if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
2798 READ_BUF(8);
2799 READ64(*res);
2800 bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
2801 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002802 dprintk("%s: files total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002803 return status;
2804}
2805
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002806static int decode_pathname(struct xdr_stream *xdr, struct nfs4_pathname *path)
2807{
Chuck Lever464ad6b2007-10-26 13:32:08 -04002808 u32 n;
Al Viro8687b632006-10-19 23:28:48 -07002809 __be32 *p;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002810 int status = 0;
2811
2812 READ_BUF(4);
2813 READ32(n);
Andy Adamson33a43f22006-06-09 09:34:30 -04002814 if (n == 0)
2815 goto root_path;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002816 dprintk("path ");
2817 path->ncomponents = 0;
2818 while (path->ncomponents < n) {
2819 struct nfs4_string *component = &path->components[path->ncomponents];
2820 status = decode_opaque_inline(xdr, &component->len, &component->data);
2821 if (unlikely(status != 0))
2822 goto out_eio;
2823 if (path->ncomponents != n)
2824 dprintk("/");
2825 dprintk("%s", component->data);
2826 if (path->ncomponents < NFS4_PATHNAME_MAXCOMPONENTS)
2827 path->ncomponents++;
2828 else {
2829 dprintk("cannot parse %d components in path\n", n);
2830 goto out_eio;
2831 }
2832 }
2833out:
2834 dprintk("\n");
2835 return status;
Andy Adamson33a43f22006-06-09 09:34:30 -04002836root_path:
2837/* a root pathname is sent as a zero component4 */
2838 path->ncomponents = 1;
2839 path->components[0].len=0;
2840 path->components[0].data=NULL;
2841 dprintk("path /\n");
2842 goto out;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002843out_eio:
2844 dprintk(" status %d", status);
2845 status = -EIO;
2846 goto out;
2847}
2848
2849static int decode_attr_fs_locations(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fs_locations *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04002850{
2851 int n;
Al Viro8687b632006-10-19 23:28:48 -07002852 __be32 *p;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002853 int status = -EIO;
2854
2855 if (unlikely(bitmap[0] & (FATTR4_WORD0_FS_LOCATIONS -1U)))
2856 goto out;
2857 status = 0;
2858 if (unlikely(!(bitmap[0] & FATTR4_WORD0_FS_LOCATIONS)))
2859 goto out;
Harvey Harrison3110ff82008-05-02 13:42:44 -07002860 dprintk("%s: fsroot ", __func__);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002861 status = decode_pathname(xdr, &res->fs_path);
Trond Myklebust683b57b2006-06-09 09:34:22 -04002862 if (unlikely(status != 0))
2863 goto out;
2864 READ_BUF(4);
2865 READ32(n);
2866 if (n <= 0)
2867 goto out_eio;
2868 res->nlocations = 0;
2869 while (res->nlocations < n) {
Chuck Lever464ad6b2007-10-26 13:32:08 -04002870 u32 m;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002871 struct nfs4_fs_location *loc = &res->locations[res->nlocations];
Trond Myklebust683b57b2006-06-09 09:34:22 -04002872
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002873 READ_BUF(4);
2874 READ32(m);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002875
2876 loc->nservers = 0;
Harvey Harrison3110ff82008-05-02 13:42:44 -07002877 dprintk("%s: servers ", __func__);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002878 while (loc->nservers < m) {
2879 struct nfs4_string *server = &loc->servers[loc->nservers];
2880 status = decode_opaque_inline(xdr, &server->len, &server->data);
2881 if (unlikely(status != 0))
2882 goto out_eio;
2883 dprintk("%s ", server->data);
2884 if (loc->nservers < NFS4_FS_LOCATION_MAXSERVERS)
2885 loc->nservers++;
2886 else {
Chuck Lever464ad6b2007-10-26 13:32:08 -04002887 unsigned int i;
2888 dprintk("%s: using first %u of %u servers "
2889 "returned for location %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07002890 __func__,
Chuck Lever464ad6b2007-10-26 13:32:08 -04002891 NFS4_FS_LOCATION_MAXSERVERS,
2892 m, res->nlocations);
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002893 for (i = loc->nservers; i < m; i++) {
Trond Myklebust2e42c3e2007-05-14 17:20:41 -04002894 unsigned int len;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002895 char *data;
2896 status = decode_opaque_inline(xdr, &len, &data);
2897 if (unlikely(status != 0))
2898 goto out_eio;
2899 }
2900 }
2901 }
2902 status = decode_pathname(xdr, &loc->rootpath);
Trond Myklebust683b57b2006-06-09 09:34:22 -04002903 if (unlikely(status != 0))
2904 goto out_eio;
Manoj Naik7aaa0b32006-06-09 09:34:23 -04002905 if (res->nlocations < NFS4_FS_LOCATIONS_MAXENTRIES)
Trond Myklebust683b57b2006-06-09 09:34:22 -04002906 res->nlocations++;
2907 }
Trond Myklebust409924e2009-03-11 14:10:27 -04002908 if (res->nlocations != 0)
2909 status = NFS_ATTR_FATTR_V4_REFERRAL;
Trond Myklebust683b57b2006-06-09 09:34:22 -04002910out:
Harvey Harrison3110ff82008-05-02 13:42:44 -07002911 dprintk("%s: fs_locations done, error = %d\n", __func__, status);
Trond Myklebust683b57b2006-06-09 09:34:22 -04002912 return status;
2913out_eio:
2914 status = -EIO;
2915 goto out;
2916}
2917
Linus Torvalds1da177e2005-04-16 15:20:36 -07002918static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2919{
Al Viro8687b632006-10-19 23:28:48 -07002920 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002921 int status = 0;
2922
2923 *res = 0;
2924 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
2925 return -EIO;
2926 if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
2927 READ_BUF(8);
2928 READ64(*res);
2929 bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
2930 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002931 dprintk("%s: maxfilesize=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002932 return status;
2933}
2934
2935static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
2936{
Al Viro8687b632006-10-19 23:28:48 -07002937 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002938 int status = 0;
2939
2940 *maxlink = 1;
2941 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
2942 return -EIO;
2943 if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
2944 READ_BUF(4);
2945 READ32(*maxlink);
2946 bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
2947 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002948 dprintk("%s: maxlink=%u\n", __func__, *maxlink);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 return status;
2950}
2951
2952static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
2953{
Al Viro8687b632006-10-19 23:28:48 -07002954 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002955 int status = 0;
2956
2957 *maxname = 1024;
2958 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
2959 return -EIO;
2960 if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
2961 READ_BUF(4);
2962 READ32(*maxname);
2963 bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
2964 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002965 dprintk("%s: maxname=%u\n", __func__, *maxname);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002966 return status;
2967}
2968
2969static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2970{
Al Viro8687b632006-10-19 23:28:48 -07002971 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 int status = 0;
2973
2974 *res = 1024;
2975 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
2976 return -EIO;
2977 if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
2978 uint64_t maxread;
2979 READ_BUF(8);
2980 READ64(maxread);
2981 if (maxread > 0x7FFFFFFF)
2982 maxread = 0x7FFFFFFF;
2983 *res = (uint32_t)maxread;
2984 bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
2985 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07002986 dprintk("%s: maxread=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07002987 return status;
2988}
2989
2990static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2991{
Al Viro8687b632006-10-19 23:28:48 -07002992 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002993 int status = 0;
2994
2995 *res = 1024;
2996 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
2997 return -EIO;
2998 if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
2999 uint64_t maxwrite;
3000 READ_BUF(8);
3001 READ64(maxwrite);
3002 if (maxwrite > 0x7FFFFFFF)
3003 maxwrite = 0x7FFFFFFF;
3004 *res = (uint32_t)maxwrite;
3005 bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
3006 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003007 dprintk("%s: maxwrite=%lu\n", __func__, (unsigned long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003008 return status;
3009}
3010
Trond Myklebustbca79472009-03-11 14:10:26 -04003011static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, umode_t *mode)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003012{
Trond Myklebustbca79472009-03-11 14:10:26 -04003013 uint32_t tmp;
Al Viro8687b632006-10-19 23:28:48 -07003014 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003015 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003016
3017 *mode = 0;
3018 if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
3019 return -EIO;
3020 if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
3021 READ_BUF(4);
Trond Myklebustbca79472009-03-11 14:10:26 -04003022 READ32(tmp);
3023 *mode = tmp & ~S_IFMT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003024 bitmap[1] &= ~FATTR4_WORD1_MODE;
Trond Myklebust409924e2009-03-11 14:10:27 -04003025 ret = NFS_ATTR_FATTR_MODE;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003026 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003027 dprintk("%s: file mode=0%o\n", __func__, (unsigned int)*mode);
Trond Myklebust409924e2009-03-11 14:10:27 -04003028 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003029}
3030
3031static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
3032{
Al Viro8687b632006-10-19 23:28:48 -07003033 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003034 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003035
3036 *nlink = 1;
3037 if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
3038 return -EIO;
3039 if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
3040 READ_BUF(4);
3041 READ32(*nlink);
3042 bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
Trond Myklebust409924e2009-03-11 14:10:27 -04003043 ret = NFS_ATTR_FATTR_NLINK;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003044 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003045 dprintk("%s: nlink=%u\n", __func__, (unsigned int)*nlink);
Trond Myklebust409924e2009-03-11 14:10:27 -04003046 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003047}
3048
Trond Myklebust2e42c3e2007-05-14 17:20:41 -04003049static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *uid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003050{
Al Viro8687b632006-10-19 23:28:48 -07003051 uint32_t len;
3052 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003053 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003054
3055 *uid = -2;
3056 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
3057 return -EIO;
3058 if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
3059 READ_BUF(4);
3060 READ32(len);
3061 READ_BUF(len);
3062 if (len < XDR_MAX_NETOBJ) {
Trond Myklebust409924e2009-03-11 14:10:27 -04003063 if (nfs_map_name_to_uid(clp, (char *)p, len, uid) == 0)
3064 ret = NFS_ATTR_FATTR_OWNER;
3065 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003066 dprintk("%s: nfs_map_name_to_uid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003067 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003068 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003069 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003070 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003071 bitmap[1] &= ~FATTR4_WORD1_OWNER;
3072 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003073 dprintk("%s: uid=%d\n", __func__, (int)*uid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003074 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003075}
3076
Trond Myklebust2e42c3e2007-05-14 17:20:41 -04003077static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs_client *clp, uint32_t *gid)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003078{
Al Viro8687b632006-10-19 23:28:48 -07003079 uint32_t len;
3080 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003081 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003082
3083 *gid = -2;
3084 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
3085 return -EIO;
3086 if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
3087 READ_BUF(4);
3088 READ32(len);
3089 READ_BUF(len);
3090 if (len < XDR_MAX_NETOBJ) {
Trond Myklebust409924e2009-03-11 14:10:27 -04003091 if (nfs_map_group_to_gid(clp, (char *)p, len, gid) == 0)
3092 ret = NFS_ATTR_FATTR_GROUP;
3093 else
Linus Torvalds1da177e2005-04-16 15:20:36 -07003094 dprintk("%s: nfs_map_group_to_gid failed!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003095 __func__);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003096 } else
Chuck Leverfe82a182007-09-11 18:01:10 -04003097 dprintk("%s: name too long (%u)!\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003098 __func__, len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003099 bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
3100 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003101 dprintk("%s: gid=%d\n", __func__, (int)*gid);
Trond Myklebust409924e2009-03-11 14:10:27 -04003102 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003103}
3104
3105static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
3106{
Al Viro8687b632006-10-19 23:28:48 -07003107 uint32_t major = 0, minor = 0;
3108 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003109 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003110
3111 *rdev = MKDEV(0,0);
3112 if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
3113 return -EIO;
3114 if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
3115 dev_t tmp;
3116
3117 READ_BUF(8);
3118 READ32(major);
3119 READ32(minor);
3120 tmp = MKDEV(major, minor);
3121 if (MAJOR(tmp) == major && MINOR(tmp) == minor)
3122 *rdev = tmp;
3123 bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
Trond Myklebust409924e2009-03-11 14:10:27 -04003124 ret = NFS_ATTR_FATTR_RDEV;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003125 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003126 dprintk("%s: rdev=(0x%x:0x%x)\n", __func__, major, minor);
Trond Myklebust409924e2009-03-11 14:10:27 -04003127 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003128}
3129
3130static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3131{
Al Viro8687b632006-10-19 23:28:48 -07003132 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003133 int status = 0;
3134
3135 *res = 0;
3136 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
3137 return -EIO;
3138 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
3139 READ_BUF(8);
3140 READ64(*res);
3141 bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
3142 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003143 dprintk("%s: space avail=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003144 return status;
3145}
3146
3147static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3148{
Al Viro8687b632006-10-19 23:28:48 -07003149 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003150 int status = 0;
3151
3152 *res = 0;
3153 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
3154 return -EIO;
3155 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
3156 READ_BUF(8);
3157 READ64(*res);
3158 bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
3159 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003160 dprintk("%s: space free=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003161 return status;
3162}
3163
3164static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
3165{
Al Viro8687b632006-10-19 23:28:48 -07003166 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003167 int status = 0;
3168
3169 *res = 0;
3170 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
3171 return -EIO;
3172 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
3173 READ_BUF(8);
3174 READ64(*res);
3175 bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
3176 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003177 dprintk("%s: space total=%Lu\n", __func__, (unsigned long long)*res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003178 return status;
3179}
3180
3181static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
3182{
Al Viro8687b632006-10-19 23:28:48 -07003183 __be32 *p;
Trond Myklebust409924e2009-03-11 14:10:27 -04003184 int ret = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003185
3186 *used = 0;
3187 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
3188 return -EIO;
3189 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
3190 READ_BUF(8);
3191 READ64(*used);
3192 bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
Trond Myklebust409924e2009-03-11 14:10:27 -04003193 ret = NFS_ATTR_FATTR_SPACE_USED;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003194 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003195 dprintk("%s: space used=%Lu\n", __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003196 (unsigned long long)*used);
Trond Myklebust409924e2009-03-11 14:10:27 -04003197 return ret;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003198}
3199
3200static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
3201{
Al Viro8687b632006-10-19 23:28:48 -07003202 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003203 uint64_t sec;
3204 uint32_t nsec;
3205
3206 READ_BUF(12);
3207 READ64(sec);
3208 READ32(nsec);
3209 time->tv_sec = (time_t)sec;
3210 time->tv_nsec = (long)nsec;
3211 return 0;
3212}
3213
3214static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
3215{
3216 int status = 0;
3217
3218 time->tv_sec = 0;
3219 time->tv_nsec = 0;
3220 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
3221 return -EIO;
3222 if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
3223 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04003224 if (status == 0)
3225 status = NFS_ATTR_FATTR_ATIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003226 bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
3227 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003228 dprintk("%s: atime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003229 return status;
3230}
3231
3232static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
3233{
3234 int status = 0;
3235
3236 time->tv_sec = 0;
3237 time->tv_nsec = 0;
3238 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
3239 return -EIO;
3240 if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
3241 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04003242 if (status == 0)
3243 status = NFS_ATTR_FATTR_CTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003244 bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
3245 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003246 dprintk("%s: ctime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003247 return status;
3248}
3249
3250static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
3251{
3252 int status = 0;
3253
3254 time->tv_sec = 0;
3255 time->tv_nsec = 0;
3256 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
3257 return -EIO;
3258 if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
3259 status = decode_attr_time(xdr, time);
Trond Myklebust409924e2009-03-11 14:10:27 -04003260 if (status == 0)
3261 status = NFS_ATTR_FATTR_MTIME;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003262 bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
3263 }
Harvey Harrison3110ff82008-05-02 13:42:44 -07003264 dprintk("%s: mtime=%ld\n", __func__, (long)time->tv_sec);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003265 return status;
3266}
3267
Al Viro8687b632006-10-19 23:28:48 -07003268static int verify_attr_len(struct xdr_stream *xdr, __be32 *savep, uint32_t attrlen)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003269{
3270 unsigned int attrwords = XDR_QUADLEN(attrlen);
3271 unsigned int nwords = xdr->p - savep;
3272
3273 if (unlikely(attrwords != nwords)) {
Chuck Leverfe82a182007-09-11 18:01:10 -04003274 dprintk("%s: server returned incorrect attribute length: "
3275 "%u %c %u\n",
Harvey Harrison3110ff82008-05-02 13:42:44 -07003276 __func__,
Linus Torvalds1da177e2005-04-16 15:20:36 -07003277 attrwords << 2,
3278 (attrwords < nwords) ? '<' : '>',
3279 nwords << 2);
3280 return -EIO;
3281 }
3282 return 0;
3283}
3284
3285static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
3286{
Al Viro8687b632006-10-19 23:28:48 -07003287 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003288
3289 READ_BUF(20);
3290 READ32(cinfo->atomic);
3291 READ64(cinfo->before);
3292 READ64(cinfo->after);
3293 return 0;
3294}
3295
3296static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
3297{
Al Viro8687b632006-10-19 23:28:48 -07003298 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003299 uint32_t supp, acc;
3300 int status;
3301
3302 status = decode_op_hdr(xdr, OP_ACCESS);
3303 if (status)
3304 return status;
3305 READ_BUF(8);
3306 READ32(supp);
3307 READ32(acc);
3308 access->supported = supp;
3309 access->access = acc;
3310 return 0;
3311}
3312
3313static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
3314{
Al Viro8687b632006-10-19 23:28:48 -07003315 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003316 int status;
3317
3318 status = decode_op_hdr(xdr, OP_CLOSE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003319 if (status != -EIO)
3320 nfs_increment_open_seqid(status, res->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003321 if (status)
3322 return status;
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04003323 READ_BUF(NFS4_STATEID_SIZE);
3324 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003325 return 0;
3326}
3327
3328static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
3329{
Al Viro8687b632006-10-19 23:28:48 -07003330 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003331 int status;
3332
3333 status = decode_op_hdr(xdr, OP_COMMIT);
3334 if (status)
3335 return status;
3336 READ_BUF(8);
3337 COPYMEM(res->verf->verifier, 8);
3338 return 0;
3339}
3340
3341static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
3342{
Al Viro8687b632006-10-19 23:28:48 -07003343 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003344 uint32_t bmlen;
3345 int status;
3346
3347 status = decode_op_hdr(xdr, OP_CREATE);
3348 if (status)
3349 return status;
3350 if ((status = decode_change_info(xdr, cinfo)))
3351 return status;
3352 READ_BUF(4);
3353 READ32(bmlen);
3354 READ_BUF(bmlen << 2);
3355 return 0;
3356}
3357
3358static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
3359{
Al Viro8687b632006-10-19 23:28:48 -07003360 __be32 *savep;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003361 uint32_t attrlen, bitmap[2] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003362 int status;
3363
3364 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3365 goto xdr_error;
3366 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3367 goto xdr_error;
3368 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3369 goto xdr_error;
3370 if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
3371 goto xdr_error;
3372 if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
3373 goto xdr_error;
3374 if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
3375 goto xdr_error;
3376 if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
3377 goto xdr_error;
3378 status = verify_attr_len(xdr, savep, attrlen);
3379xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003380 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003381 return status;
3382}
Andy Adamson6c0195a2008-12-23 16:06:15 -05003383
Linus Torvalds1da177e2005-04-16 15:20:36 -07003384static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
3385{
Al Viro8687b632006-10-19 23:28:48 -07003386 __be32 *savep;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003387 uint32_t attrlen, bitmap[2] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003388 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003389
Linus Torvalds1da177e2005-04-16 15:20:36 -07003390 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3391 goto xdr_error;
3392 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3393 goto xdr_error;
3394 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3395 goto xdr_error;
3396
3397 if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
3398 goto xdr_error;
3399 if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
3400 goto xdr_error;
3401 if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
3402 goto xdr_error;
3403 if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
3404 goto xdr_error;
3405 if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
3406 goto xdr_error;
3407 if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
3408 goto xdr_error;
3409
3410 status = verify_attr_len(xdr, savep, attrlen);
3411xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003412 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003413 return status;
3414}
3415
3416static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
3417{
Al Viro8687b632006-10-19 23:28:48 -07003418 __be32 *savep;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003419 uint32_t attrlen, bitmap[2] = {0};
Linus Torvalds1da177e2005-04-16 15:20:36 -07003420 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003421
Linus Torvalds1da177e2005-04-16 15:20:36 -07003422 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3423 goto xdr_error;
3424 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3425 goto xdr_error;
3426 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3427 goto xdr_error;
3428
3429 if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
3430 goto xdr_error;
3431 if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
3432 goto xdr_error;
3433
3434 status = verify_attr_len(xdr, savep, attrlen);
3435xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003436 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003437 return status;
3438}
3439
3440static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, const struct nfs_server *server)
3441{
Al Viro8687b632006-10-19 23:28:48 -07003442 __be32 *savep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003443 uint32_t attrlen,
3444 bitmap[2] = {0},
3445 type;
Trond Myklebustbca79472009-03-11 14:10:26 -04003446 int status;
3447 umode_t fmode = 0;
Manoj Naik99baf622006-06-09 09:34:24 -04003448 uint64_t fileid;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003449
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003450 status = decode_op_hdr(xdr, OP_GETATTR);
3451 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003452 goto xdr_error;
3453
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003454 status = decode_attr_bitmap(xdr, bitmap);
3455 if (status < 0)
3456 goto xdr_error;
3457
3458 status = decode_attr_length(xdr, &attrlen, &savep);
3459 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003460 goto xdr_error;
3461
3462
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003463 status = decode_attr_type(xdr, bitmap, &type);
3464 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003465 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003466 fattr->mode = 0;
3467 if (status != 0) {
3468 fattr->mode |= nfs_type2fmt[type];
3469 fattr->valid |= status;
3470 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07003471
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003472 status = decode_attr_change(xdr, bitmap, &fattr->change_attr);
3473 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003474 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003475 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003476
3477 status = decode_attr_size(xdr, bitmap, &fattr->size);
3478 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003479 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003480 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003481
3482 status = decode_attr_fsid(xdr, bitmap, &fattr->fsid);
3483 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003484 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003485 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003486
3487 status = decode_attr_fileid(xdr, bitmap, &fattr->fileid);
3488 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003489 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003490 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003491
3492 status = decode_attr_fs_locations(xdr, bitmap, container_of(fattr,
Manoj Naik7aaa0b32006-06-09 09:34:23 -04003493 struct nfs4_fs_locations,
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003494 fattr));
3495 if (status < 0)
Trond Myklebust683b57b2006-06-09 09:34:22 -04003496 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003497 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003498
3499 status = decode_attr_mode(xdr, bitmap, &fmode);
3500 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003501 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003502 if (status != 0) {
3503 fattr->mode |= fmode;
3504 fattr->valid |= status;
3505 }
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003506
3507 status = decode_attr_nlink(xdr, bitmap, &fattr->nlink);
3508 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003509 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003510 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003511
3512 status = decode_attr_owner(xdr, bitmap, server->nfs_client, &fattr->uid);
3513 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003514 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003515 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003516
3517 status = decode_attr_group(xdr, bitmap, server->nfs_client, &fattr->gid);
3518 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003519 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003520 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003521
3522 status = decode_attr_rdev(xdr, bitmap, &fattr->rdev);
3523 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003524 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003525 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003526
3527 status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used);
3528 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003529 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003530 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003531
3532 status = decode_attr_time_access(xdr, bitmap, &fattr->atime);
3533 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003534 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003535 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003536
3537 status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime);
3538 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003539 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003540 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003541
3542 status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime);
3543 if (status < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003544 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003545 fattr->valid |= status;
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003546
3547 status = decode_attr_mounted_on_fileid(xdr, bitmap, &fileid);
3548 if (status < 0)
Manoj Naik99baf622006-06-09 09:34:24 -04003549 goto xdr_error;
Trond Myklebust409924e2009-03-11 14:10:27 -04003550 if (status != 0 && !(fattr->valid & status)) {
Manoj Naik99baf622006-06-09 09:34:24 -04003551 fattr->fileid = fileid;
Trond Myklebust409924e2009-03-11 14:10:27 -04003552 fattr->valid |= status;
3553 }
Trond Myklebustf26c7a72009-03-11 14:10:26 -04003554
3555 status = verify_attr_len(xdr, savep, attrlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003556xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003557 dprintk("%s: xdr returned %d\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003558 return status;
3559}
3560
3561
3562static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
3563{
Al Viro8687b632006-10-19 23:28:48 -07003564 __be32 *savep;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003565 uint32_t attrlen, bitmap[2];
3566 int status;
3567
3568 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3569 goto xdr_error;
3570 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3571 goto xdr_error;
3572 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3573 goto xdr_error;
3574
3575 fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
3576
3577 if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
3578 goto xdr_error;
3579 if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
3580 goto xdr_error;
3581 if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
3582 goto xdr_error;
3583 fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
3584 if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
3585 goto xdr_error;
3586 fsinfo->wtpref = fsinfo->wtmax;
3587
3588 status = verify_attr_len(xdr, savep, attrlen);
3589xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003590 dprintk("%s: xdr returned %d!\n", __func__, -status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003591 return status;
3592}
3593
3594static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
3595{
Al Viro8687b632006-10-19 23:28:48 -07003596 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003597 uint32_t len;
3598 int status;
3599
Trond Myklebust99367812007-07-17 21:52:41 -04003600 /* Zero handle first to allow comparisons */
3601 memset(fh, 0, sizeof(*fh));
3602
Linus Torvalds1da177e2005-04-16 15:20:36 -07003603 status = decode_op_hdr(xdr, OP_GETFH);
3604 if (status)
3605 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003606
3607 READ_BUF(4);
3608 READ32(len);
3609 if (len > NFS4_FHSIZE)
3610 return -EIO;
3611 fh->size = len;
3612 READ_BUF(len);
3613 COPYMEM(fh->data, len);
3614 return 0;
3615}
3616
3617static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
3618{
3619 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05003620
Linus Torvalds1da177e2005-04-16 15:20:36 -07003621 status = decode_op_hdr(xdr, OP_LINK);
3622 if (status)
3623 return status;
3624 return decode_change_info(xdr, cinfo);
3625}
3626
3627/*
3628 * We create the owner, so we know a proper owner.id length is 4.
3629 */
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003630static int decode_lock_denied (struct xdr_stream *xdr, struct file_lock *fl)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003631{
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003632 uint64_t offset, length, clientid;
Al Viro8687b632006-10-19 23:28:48 -07003633 __be32 *p;
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003634 uint32_t namelen, type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003635
3636 READ_BUF(32);
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003637 READ64(offset);
3638 READ64(length);
3639 READ32(type);
3640 if (fl != NULL) {
3641 fl->fl_start = (loff_t)offset;
3642 fl->fl_end = fl->fl_start + (loff_t)length - 1;
3643 if (length == ~(uint64_t)0)
3644 fl->fl_end = OFFSET_MAX;
3645 fl->fl_type = F_WRLCK;
3646 if (type & 1)
3647 fl->fl_type = F_RDLCK;
3648 fl->fl_pid = 0;
3649 }
3650 READ64(clientid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003651 READ32(namelen);
3652 READ_BUF(namelen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653 return -NFS4ERR_DENIED;
3654}
3655
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003656static int decode_lock(struct xdr_stream *xdr, struct nfs_lock_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003657{
Al Viro8687b632006-10-19 23:28:48 -07003658 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003659 int status;
3660
3661 status = decode_op_hdr(xdr, OP_LOCK);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003662 if (status == -EIO)
3663 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003664 if (status == 0) {
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04003665 READ_BUF(NFS4_STATEID_SIZE);
3666 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003667 } else if (status == -NFS4ERR_DENIED)
Trond Myklebustc1d51932008-04-07 13:20:54 -04003668 status = decode_lock_denied(xdr, NULL);
3669 if (res->open_seqid != NULL)
3670 nfs_increment_open_seqid(status, res->open_seqid);
3671 nfs_increment_lock_seqid(status, res->lock_seqid);
3672out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003673 return status;
3674}
3675
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003676static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003677{
3678 int status;
3679 status = decode_op_hdr(xdr, OP_LOCKT);
3680 if (status == -NFS4ERR_DENIED)
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003681 return decode_lock_denied(xdr, res->denied);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003682 return status;
3683}
3684
Trond Myklebust911d1aa2006-01-03 09:55:16 +01003685static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003686{
Al Viro8687b632006-10-19 23:28:48 -07003687 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003688 int status;
3689
3690 status = decode_op_hdr(xdr, OP_LOCKU);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003691 if (status != -EIO)
3692 nfs_increment_lock_seqid(status, res->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003693 if (status == 0) {
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04003694 READ_BUF(NFS4_STATEID_SIZE);
3695 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003696 }
3697 return status;
3698}
3699
3700static int decode_lookup(struct xdr_stream *xdr)
3701{
3702 return decode_op_hdr(xdr, OP_LOOKUP);
3703}
3704
3705/* This is too sick! */
3706static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
3707{
Andy Adamson05d564f2008-12-23 16:06:15 -05003708 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003709 uint32_t limit_type, nblocks, blocksize;
3710
3711 READ_BUF(12);
3712 READ32(limit_type);
3713 switch (limit_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05003714 case 1:
3715 READ64(*maxsize);
3716 break;
3717 case 2:
3718 READ32(nblocks);
3719 READ32(blocksize);
3720 *maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003721 }
3722 return 0;
3723}
3724
3725static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
3726{
Andy Adamson05d564f2008-12-23 16:06:15 -05003727 __be32 *p;
3728 uint32_t delegation_type;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003729
3730 READ_BUF(4);
3731 READ32(delegation_type);
3732 if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
3733 res->delegation_type = 0;
3734 return 0;
3735 }
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04003736 READ_BUF(NFS4_STATEID_SIZE+4);
3737 COPYMEM(res->delegation.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003738 READ32(res->do_recall);
Andy Adamson05d564f2008-12-23 16:06:15 -05003739
Linus Torvalds1da177e2005-04-16 15:20:36 -07003740 switch (delegation_type) {
Andy Adamson05d564f2008-12-23 16:06:15 -05003741 case NFS4_OPEN_DELEGATE_READ:
3742 res->delegation_type = FMODE_READ;
3743 break;
3744 case NFS4_OPEN_DELEGATE_WRITE:
3745 res->delegation_type = FMODE_WRITE|FMODE_READ;
3746 if (decode_space_limit(xdr, &res->maxsize) < 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003747 return -EIO;
3748 }
David Howells7539bba2006-08-22 20:06:09 -04003749 return decode_ace(xdr, NULL, res->server->nfs_client);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003750}
3751
3752static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
3753{
Andy Adamson05d564f2008-12-23 16:06:15 -05003754 __be32 *p;
Jeff Laytonaa53ed52007-06-05 14:49:03 -04003755 uint32_t savewords, bmlen, i;
Andy Adamson05d564f2008-12-23 16:06:15 -05003756 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003757
Andy Adamson05d564f2008-12-23 16:06:15 -05003758 status = decode_op_hdr(xdr, OP_OPEN);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003759 if (status != -EIO)
3760 nfs_increment_open_seqid(status, res->seqid);
Andy Adamson05d564f2008-12-23 16:06:15 -05003761 if (status)
3762 return status;
3763 READ_BUF(NFS4_STATEID_SIZE);
3764 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003765
Andy Adamson05d564f2008-12-23 16:06:15 -05003766 decode_change_info(xdr, &res->cinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003767
Andy Adamson05d564f2008-12-23 16:06:15 -05003768 READ_BUF(8);
3769 READ32(res->rflags);
3770 READ32(bmlen);
3771 if (bmlen > 10)
3772 goto xdr_error;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003773
Andy Adamson05d564f2008-12-23 16:06:15 -05003774 READ_BUF(bmlen << 2);
Jeff Laytonaa53ed52007-06-05 14:49:03 -04003775 savewords = min_t(uint32_t, bmlen, NFS4_BITMAP_SIZE);
3776 for (i = 0; i < savewords; ++i)
3777 READ32(res->attrset[i]);
3778 for (; i < NFS4_BITMAP_SIZE; i++)
3779 res->attrset[i] = 0;
3780
Linus Torvalds1da177e2005-04-16 15:20:36 -07003781 return decode_delegation(xdr, res);
3782xdr_error:
Harvey Harrison3110ff82008-05-02 13:42:44 -07003783 dprintk("%s: Bitmap too large! Length = %u\n", __func__, bmlen);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003784 return -EIO;
3785}
3786
3787static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
3788{
Andy Adamson05d564f2008-12-23 16:06:15 -05003789 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003790 int status;
3791
Andy Adamson05d564f2008-12-23 16:06:15 -05003792 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003793 if (status != -EIO)
3794 nfs_increment_open_seqid(status, res->seqid);
Andy Adamson05d564f2008-12-23 16:06:15 -05003795 if (status)
3796 return status;
3797 READ_BUF(NFS4_STATEID_SIZE);
3798 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
3799 return 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003800}
3801
3802static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
3803{
Al Viro8687b632006-10-19 23:28:48 -07003804 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003805 int status;
3806
3807 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
Trond Myklebustc1d51932008-04-07 13:20:54 -04003808 if (status != -EIO)
3809 nfs_increment_open_seqid(status, res->seqid);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003810 if (status)
3811 return status;
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04003812 READ_BUF(NFS4_STATEID_SIZE);
3813 COPYMEM(res->stateid.data, NFS4_STATEID_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003814 return 0;
3815}
3816
3817static int decode_putfh(struct xdr_stream *xdr)
3818{
3819 return decode_op_hdr(xdr, OP_PUTFH);
3820}
3821
3822static int decode_putrootfh(struct xdr_stream *xdr)
3823{
3824 return decode_op_hdr(xdr, OP_PUTROOTFH);
3825}
3826
3827static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
3828{
3829 struct kvec *iov = req->rq_rcv_buf.head;
Al Viro8687b632006-10-19 23:28:48 -07003830 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003831 uint32_t count, eof, recvd, hdrlen;
3832 int status;
3833
3834 status = decode_op_hdr(xdr, OP_READ);
3835 if (status)
3836 return status;
3837 READ_BUF(8);
3838 READ32(eof);
3839 READ32(count);
3840 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
3841 recvd = req->rq_rcv_buf.len - hdrlen;
3842 if (count > recvd) {
Chuck Leverfe82a182007-09-11 18:01:10 -04003843 dprintk("NFS: server cheating in read reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07003844 "count %u > recvd %u\n", count, recvd);
3845 count = recvd;
3846 eof = 0;
3847 }
3848 xdr_read_pages(xdr, count);
3849 res->eof = eof;
3850 res->count = count;
3851 return 0;
3852}
3853
3854static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
3855{
3856 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
3857 struct page *page = *rcvbuf->pages;
3858 struct kvec *iov = rcvbuf->head;
Chuck Leverbcecff72007-10-26 13:32:03 -04003859 size_t hdrlen;
3860 u32 recvd, pglen = rcvbuf->page_len;
Al Viro8687b632006-10-19 23:28:48 -07003861 __be32 *end, *entry, *p, *kaddr;
Jeff Layton7bda2cd2008-02-22 14:50:01 -05003862 unsigned int nr = 0;
Chuck Leverbcecff72007-10-26 13:32:03 -04003863 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003864
3865 status = decode_op_hdr(xdr, OP_READDIR);
3866 if (status)
3867 return status;
3868 READ_BUF(8);
3869 COPYMEM(readdir->verifier.data, 8);
Fred Isaman44109242008-04-02 15:21:15 +03003870 dprintk("%s: verifier = %08x:%08x\n",
3871 __func__,
Trond Myklebusteadf4592005-06-22 17:16:39 +00003872 ((u32 *)readdir->verifier.data)[0],
3873 ((u32 *)readdir->verifier.data)[1]);
3874
Linus Torvalds1da177e2005-04-16 15:20:36 -07003875
3876 hdrlen = (char *) p - (char *) iov->iov_base;
3877 recvd = rcvbuf->len - hdrlen;
3878 if (pglen > recvd)
3879 pglen = recvd;
3880 xdr_read_pages(xdr, pglen);
3881
3882 BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
Al Viro8687b632006-10-19 23:28:48 -07003883 kaddr = p = kmap_atomic(page, KM_USER0);
David Howellse8896492006-08-24 15:44:19 -04003884 end = p + ((pglen + readdir->pgbase) >> 2);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003885 entry = p;
Jeff Layton7bda2cd2008-02-22 14:50:01 -05003886
3887 /* Make sure the packet actually has a value_follows and EOF entry */
3888 if ((entry + 1) > end)
3889 goto short_pkt;
3890
3891 for (; *p++; nr++) {
Chuck Leverbcecff72007-10-26 13:32:03 -04003892 u32 len, attrlen, xlen;
David Howellse8896492006-08-24 15:44:19 -04003893 if (end - p < 3)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003894 goto short_pkt;
Trond Myklebusteadf4592005-06-22 17:16:39 +00003895 dprintk("cookie = %Lu, ", *((unsigned long long *)p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003896 p += 2; /* cookie */
3897 len = ntohl(*p++); /* filename length */
3898 if (len > NFS4_MAXNAMLEN) {
Chuck Leverfe82a182007-09-11 18:01:10 -04003899 dprintk("NFS: giant filename in readdir (len 0x%x)\n",
3900 len);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003901 goto err_unmap;
3902 }
David Howellse8896492006-08-24 15:44:19 -04003903 xlen = XDR_QUADLEN(len);
3904 if (end - p < xlen + 1)
3905 goto short_pkt;
Trond Myklebusteadf4592005-06-22 17:16:39 +00003906 dprintk("filename = %*s\n", len, (char *)p);
David Howellse8896492006-08-24 15:44:19 -04003907 p += xlen;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003908 len = ntohl(*p++); /* bitmap length */
David Howellse8896492006-08-24 15:44:19 -04003909 if (end - p < len + 1)
3910 goto short_pkt;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003911 p += len;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003912 attrlen = XDR_QUADLEN(ntohl(*p++));
David Howellse8896492006-08-24 15:44:19 -04003913 if (end - p < attrlen + 2)
Linus Torvalds1da177e2005-04-16 15:20:36 -07003914 goto short_pkt;
David Howellse8896492006-08-24 15:44:19 -04003915 p += attrlen; /* attributes */
Linus Torvalds1da177e2005-04-16 15:20:36 -07003916 entry = p;
3917 }
Jeff Layton7bda2cd2008-02-22 14:50:01 -05003918 /*
3919 * Apparently some server sends responses that are a valid size, but
3920 * contain no entries, and have value_follows==0 and EOF==0. For
3921 * those, just set the EOF marker.
3922 */
3923 if (!nr && entry[1] == 0) {
3924 dprintk("NFS: readdir reply truncated!\n");
3925 entry[1] = 1;
3926 }
Andy Adamson6c0195a2008-12-23 16:06:15 -05003927out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07003928 kunmap_atomic(kaddr, KM_USER0);
3929 return 0;
3930short_pkt:
Jeff Layton7bda2cd2008-02-22 14:50:01 -05003931 /*
3932 * When we get a short packet there are 2 possibilities. We can
3933 * return an error, or fix up the response to look like a valid
3934 * response and return what we have so far. If there are no
3935 * entries and the packet was short, then return -EIO. If there
3936 * are valid entries in the response, return them and pretend that
3937 * the call was successful, but incomplete. The caller can retry the
3938 * readdir starting at the last cookie.
3939 */
Harvey Harrison3110ff82008-05-02 13:42:44 -07003940 dprintk("%s: short packet at entry %d\n", __func__, nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003941 entry[0] = entry[1] = 0;
Jeff Layton7bda2cd2008-02-22 14:50:01 -05003942 if (nr)
3943 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003944err_unmap:
3945 kunmap_atomic(kaddr, KM_USER0);
3946 return -errno_NFSERR_IO;
3947}
3948
3949static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
3950{
3951 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
3952 struct kvec *iov = rcvbuf->head;
Chuck Leverbcecff72007-10-26 13:32:03 -04003953 size_t hdrlen;
3954 u32 len, recvd;
Al Viro8687b632006-10-19 23:28:48 -07003955 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003956 char *kaddr;
3957 int status;
3958
3959 status = decode_op_hdr(xdr, OP_READLINK);
3960 if (status)
3961 return status;
3962
3963 /* Convert length of symlink */
3964 READ_BUF(4);
3965 READ32(len);
3966 if (len >= rcvbuf->page_len || len <= 0) {
Chuck Leverfe82a182007-09-11 18:01:10 -04003967 dprintk("nfs: server returned giant symlink!\n");
Linus Torvalds1da177e2005-04-16 15:20:36 -07003968 return -ENAMETOOLONG;
3969 }
3970 hdrlen = (char *) xdr->p - (char *) iov->iov_base;
3971 recvd = req->rq_rcv_buf.len - hdrlen;
3972 if (recvd < len) {
Chuck Leverfe82a182007-09-11 18:01:10 -04003973 dprintk("NFS: server cheating in readlink reply: "
Linus Torvalds1da177e2005-04-16 15:20:36 -07003974 "count %u > recvd %u\n", len, recvd);
3975 return -EIO;
3976 }
3977 xdr_read_pages(xdr, len);
3978 /*
3979 * The XDR encode routine has set things up so that
3980 * the link text will be copied directly into the
3981 * buffer. We just have to do overflow-checking,
3982 * and and null-terminate the text (the VFS expects
3983 * null-termination).
3984 */
3985 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
3986 kaddr[len+rcvbuf->page_base] = '\0';
3987 kunmap_atomic(kaddr, KM_USER0);
3988 return 0;
3989}
3990
3991static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
3992{
3993 int status;
3994
3995 status = decode_op_hdr(xdr, OP_REMOVE);
3996 if (status)
3997 goto out;
3998 status = decode_change_info(xdr, cinfo);
3999out:
4000 return status;
4001}
4002
4003static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
4004 struct nfs4_change_info *new_cinfo)
4005{
4006 int status;
4007
4008 status = decode_op_hdr(xdr, OP_RENAME);
4009 if (status)
4010 goto out;
4011 if ((status = decode_change_info(xdr, old_cinfo)))
4012 goto out;
4013 status = decode_change_info(xdr, new_cinfo);
4014out:
4015 return status;
4016}
4017
4018static int decode_renew(struct xdr_stream *xdr)
4019{
4020 return decode_op_hdr(xdr, OP_RENEW);
4021}
4022
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004023static int
4024decode_restorefh(struct xdr_stream *xdr)
4025{
4026 return decode_op_hdr(xdr, OP_RESTOREFH);
4027}
4028
J. Bruce Fields029d1052005-06-22 17:16:22 +00004029static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
4030 size_t *acl_len)
4031{
Al Viro8687b632006-10-19 23:28:48 -07004032 __be32 *savep;
J. Bruce Fields029d1052005-06-22 17:16:22 +00004033 uint32_t attrlen,
4034 bitmap[2] = {0};
4035 struct kvec *iov = req->rq_rcv_buf.head;
4036 int status;
4037
4038 *acl_len = 0;
4039 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
4040 goto out;
4041 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
4042 goto out;
4043 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
4044 goto out;
4045
4046 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
4047 return -EIO;
4048 if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
Chuck Leverbcecff72007-10-26 13:32:03 -04004049 size_t hdrlen;
4050 u32 recvd;
J. Bruce Fields029d1052005-06-22 17:16:22 +00004051
4052 /* We ignore &savep and don't do consistency checks on
4053 * the attr length. Let userspace figure it out.... */
4054 hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
4055 recvd = req->rq_rcv_buf.len - hdrlen;
4056 if (attrlen > recvd) {
Chuck Leverfe82a182007-09-11 18:01:10 -04004057 dprintk("NFS: server cheating in getattr"
J. Bruce Fields029d1052005-06-22 17:16:22 +00004058 " acl reply: attrlen %u > recvd %u\n",
4059 attrlen, recvd);
4060 return -EINVAL;
4061 }
J. Bruce Fieldsc04871e2006-05-30 16:28:58 -04004062 xdr_read_pages(xdr, attrlen);
J. Bruce Fields029d1052005-06-22 17:16:22 +00004063 *acl_len = attrlen;
J. Bruce Fields8c233cf2005-10-13 16:54:27 -04004064 } else
4065 status = -EOPNOTSUPP;
J. Bruce Fields029d1052005-06-22 17:16:22 +00004066
4067out:
4068 return status;
4069}
4070
Linus Torvalds1da177e2005-04-16 15:20:36 -07004071static int
4072decode_savefh(struct xdr_stream *xdr)
4073{
4074 return decode_op_hdr(xdr, OP_SAVEFH);
4075}
4076
Benny Halevy9e9ecc02009-04-01 09:22:00 -04004077static int decode_setattr(struct xdr_stream *xdr)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004078{
Al Viro8687b632006-10-19 23:28:48 -07004079 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004080 uint32_t bmlen;
4081 int status;
4082
Linus Torvalds1da177e2005-04-16 15:20:36 -07004083 status = decode_op_hdr(xdr, OP_SETATTR);
4084 if (status)
4085 return status;
4086 READ_BUF(4);
4087 READ32(bmlen);
4088 READ_BUF(bmlen << 2);
4089 return 0;
4090}
4091
David Howellsadfa6f92006-08-22 20:06:08 -04004092static int decode_setclientid(struct xdr_stream *xdr, struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004093{
Al Viro8687b632006-10-19 23:28:48 -07004094 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004095 uint32_t opnum;
4096 int32_t nfserr;
4097
4098 READ_BUF(8);
4099 READ32(opnum);
4100 if (opnum != OP_SETCLIENTID) {
Chuck Leverfe82a182007-09-11 18:01:10 -04004101 dprintk("nfs: decode_setclientid: Server returned operation"
Andy Adamson6c0195a2008-12-23 16:06:15 -05004102 " %d\n", opnum);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004103 return -EIO;
4104 }
4105 READ32(nfserr);
4106 if (nfserr == NFS_OK) {
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04004107 READ_BUF(8 + NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004108 READ64(clp->cl_clientid);
Trond Myklebust8ae20ab2007-05-14 16:50:45 -04004109 COPYMEM(clp->cl_confirm.data, NFS4_VERIFIER_SIZE);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004110 } else if (nfserr == NFSERR_CLID_INUSE) {
4111 uint32_t len;
4112
4113 /* skip netid string */
4114 READ_BUF(4);
4115 READ32(len);
4116 READ_BUF(len);
4117
4118 /* skip uaddr string */
4119 READ_BUF(4);
4120 READ32(len);
4121 READ_BUF(len);
4122 return -NFSERR_CLID_INUSE;
4123 } else
Benny Halevy856dff32008-03-31 17:39:06 +03004124 return nfs4_stat_to_errno(nfserr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004125
4126 return 0;
4127}
4128
4129static int decode_setclientid_confirm(struct xdr_stream *xdr)
4130{
4131 return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
4132}
4133
4134static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
4135{
Al Viro8687b632006-10-19 23:28:48 -07004136 __be32 *p;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004137 int status;
4138
4139 status = decode_op_hdr(xdr, OP_WRITE);
4140 if (status)
4141 return status;
4142
4143 READ_BUF(16);
4144 READ32(res->count);
4145 READ32(res->verf->committed);
4146 COPYMEM(res->verf->verifier, 8);
4147 return 0;
4148}
4149
4150static int decode_delegreturn(struct xdr_stream *xdr)
4151{
4152 return decode_op_hdr(xdr, OP_DELEGRETURN);
4153}
4154
Benny Halevy99fe60d2009-04-01 09:22:29 -04004155#if defined(CONFIG_NFS_V4_1)
4156static int decode_exchange_id(struct xdr_stream *xdr,
4157 struct nfs41_exchange_id_res *res)
4158{
4159 __be32 *p;
4160 uint32_t dummy;
4161 int status;
4162 struct nfs_client *clp = res->client;
4163
4164 status = decode_op_hdr(xdr, OP_EXCHANGE_ID);
4165 if (status)
4166 return status;
4167
4168 READ_BUF(8);
4169 READ64(clp->cl_ex_clid);
4170 READ_BUF(12);
4171 READ32(clp->cl_seqid);
4172 READ32(clp->cl_exchange_flags);
4173
4174 /* We ask for SP4_NONE */
4175 READ32(dummy);
4176 if (dummy != SP4_NONE)
4177 return -EIO;
4178
4179 /* Throw away minor_id */
4180 READ_BUF(8);
4181
4182 /* Throw away Major id */
4183 READ_BUF(4);
4184 READ32(dummy);
4185 READ_BUF(dummy);
4186
4187 /* Throw away server_scope */
4188 READ_BUF(4);
4189 READ32(dummy);
4190 READ_BUF(dummy);
4191
4192 /* Throw away Implementation id array */
4193 READ_BUF(4);
4194 READ32(dummy);
4195 READ_BUF(dummy);
4196
4197 return 0;
4198}
Andy Adamsonfc931582009-04-01 09:22:31 -04004199
4200static int decode_chan_attrs(struct xdr_stream *xdr,
4201 struct nfs4_channel_attrs *attrs)
4202{
4203 __be32 *p;
4204 u32 nr_attrs;
4205
4206 READ_BUF(28);
4207 READ32(attrs->headerpadsz);
4208 READ32(attrs->max_rqst_sz);
4209 READ32(attrs->max_resp_sz);
4210 READ32(attrs->max_resp_sz_cached);
4211 READ32(attrs->max_ops);
4212 READ32(attrs->max_reqs);
4213 READ32(nr_attrs);
4214 if (unlikely(nr_attrs > 1)) {
4215 printk(KERN_WARNING "%s: Invalid rdma channel attrs count %u\n",
4216 __func__, nr_attrs);
4217 return -EINVAL;
4218 }
4219 if (nr_attrs == 1)
4220 READ_BUF(4); /* skip rdma_attrs */
4221 return 0;
4222}
4223
4224static int decode_create_session(struct xdr_stream *xdr,
4225 struct nfs41_create_session_res *res)
4226{
4227 __be32 *p;
4228 int status;
4229 struct nfs_client *clp = res->client;
4230 struct nfs4_session *session = clp->cl_session;
4231
4232 status = decode_op_hdr(xdr, OP_CREATE_SESSION);
4233
4234 if (status)
4235 return status;
4236
4237 /* sessionid */
4238 READ_BUF(NFS4_MAX_SESSIONID_LEN);
4239 COPYMEM(&session->sess_id, NFS4_MAX_SESSIONID_LEN);
4240
4241 /* seqid, flags */
4242 READ_BUF(8);
4243 READ32(clp->cl_seqid);
4244 READ32(session->flags);
4245
4246 /* Channel attributes */
4247 status = decode_chan_attrs(xdr, &session->fc_attrs);
4248 if (!status)
4249 status = decode_chan_attrs(xdr, &session->bc_attrs);
4250 return status;
4251}
Andy Adamson0f3e66c2009-04-01 09:22:34 -04004252
4253static int decode_destroy_session(struct xdr_stream *xdr, void *dummy)
4254{
4255 return decode_op_hdr(xdr, OP_DESTROY_SESSION);
4256}
Benny Halevy99fe60d2009-04-01 09:22:29 -04004257#endif /* CONFIG_NFS_V4_1 */
4258
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004259static int decode_sequence(struct xdr_stream *xdr,
4260 struct nfs4_sequence_res *res,
4261 struct rpc_rqst *rqstp)
4262{
4263#if defined(CONFIG_NFS_V4_1)
Andy Adamsonfc01cea2009-04-01 09:22:36 -04004264 struct nfs4_slot *slot;
4265 struct nfs4_sessionid id;
4266 u32 dummy;
4267 int status;
4268 __be32 *p;
4269
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004270 if (!res->sr_session)
4271 return 0;
4272
Andy Adamsonfc01cea2009-04-01 09:22:36 -04004273 status = decode_op_hdr(xdr, OP_SEQUENCE);
4274 if (status)
4275 goto out_err;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004276
Andy Adamsonfc01cea2009-04-01 09:22:36 -04004277 /*
4278 * If the server returns different values for sessionID, slotID or
4279 * sequence number, the server is looney tunes.
4280 */
4281 status = -ESERVERFAULT;
4282
4283 slot = &res->sr_session->fc_slot_table.slots[res->sr_slotid];
4284 READ_BUF(NFS4_MAX_SESSIONID_LEN + 20);
4285 COPYMEM(id.data, NFS4_MAX_SESSIONID_LEN);
4286 if (memcmp(id.data, res->sr_session->sess_id.data,
4287 NFS4_MAX_SESSIONID_LEN)) {
4288 dprintk("%s Invalid session id\n", __func__);
4289 goto out_err;
4290 }
4291 /* seqid */
4292 READ32(dummy);
4293 if (dummy != slot->seq_nr) {
4294 dprintk("%s Invalid sequence number\n", __func__);
4295 goto out_err;
4296 }
4297 /* slot id */
4298 READ32(dummy);
4299 if (dummy != res->sr_slotid) {
4300 dprintk("%s Invalid slot id\n", __func__);
4301 goto out_err;
4302 }
4303 /* highest slot id - currently not processed */
4304 READ32(dummy);
4305 /* target highest slot id - currently not processed */
4306 READ32(dummy);
4307 /* result flags - currently not processed */
4308 READ32(dummy);
4309 status = 0;
4310out_err:
4311 res->sr_status = status;
4312 return status;
4313#else /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004314 return 0;
Andy Adamsonfc01cea2009-04-01 09:22:36 -04004315#endif /* CONFIG_NFS_V4_1 */
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004316}
4317
Linus Torvalds1da177e2005-04-16 15:20:36 -07004318/*
Benny Halevy49c25592008-12-23 16:06:16 -05004319 * END OF "GENERIC" DECODE ROUTINES.
4320 */
4321
4322/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004323 * Decode OPEN_DOWNGRADE response
4324 */
Al Viro8687b632006-10-19 23:28:48 -07004325static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004326{
Andy Adamson05d564f2008-12-23 16:06:15 -05004327 struct xdr_stream xdr;
4328 struct compound_hdr hdr;
4329 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004330
Andy Adamson05d564f2008-12-23 16:06:15 -05004331 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4332 status = decode_compound_hdr(&xdr, &hdr);
4333 if (status)
4334 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004335 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4336 if (status)
4337 goto out;
Andy Adamson05d564f2008-12-23 16:06:15 -05004338 status = decode_putfh(&xdr);
4339 if (status)
4340 goto out;
4341 status = decode_open_downgrade(&xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04004342 if (status != 0)
4343 goto out;
4344 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004345out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004346 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004347}
4348
4349/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004350 * Decode ACCESS response
4351 */
Al Viro8687b632006-10-19 23:28:48 -07004352static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_accessres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004353{
4354 struct xdr_stream xdr;
4355 struct compound_hdr hdr;
4356 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004357
Linus Torvalds1da177e2005-04-16 15:20:36 -07004358 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004359 status = decode_compound_hdr(&xdr, &hdr);
4360 if (status)
4361 goto out;
4362 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4363 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004364 goto out;
Trond Myklebust76b32992007-08-10 17:45:11 -04004365 status = decode_putfh(&xdr);
4366 if (status != 0)
4367 goto out;
4368 status = decode_access(&xdr, res);
4369 if (status != 0)
4370 goto out;
4371 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004372out:
4373 return status;
4374}
4375
4376/*
4377 * Decode LOOKUP response
4378 */
Al Viro8687b632006-10-19 23:28:48 -07004379static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004380{
4381 struct xdr_stream xdr;
4382 struct compound_hdr hdr;
4383 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004384
Linus Torvalds1da177e2005-04-16 15:20:36 -07004385 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004386 status = decode_compound_hdr(&xdr, &hdr);
4387 if (status)
4388 goto out;
4389 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4390 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004391 goto out;
4392 if ((status = decode_putfh(&xdr)) != 0)
4393 goto out;
4394 if ((status = decode_lookup(&xdr)) != 0)
4395 goto out;
4396 if ((status = decode_getfh(&xdr, res->fh)) != 0)
4397 goto out;
4398 status = decode_getfattr(&xdr, res->fattr, res->server);
4399out:
4400 return status;
4401}
4402
4403/*
4404 * Decode LOOKUP_ROOT response
4405 */
Al Viro8687b632006-10-19 23:28:48 -07004406static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_lookup_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004407{
4408 struct xdr_stream xdr;
4409 struct compound_hdr hdr;
4410 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004411
Linus Torvalds1da177e2005-04-16 15:20:36 -07004412 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004413 status = decode_compound_hdr(&xdr, &hdr);
4414 if (status)
4415 goto out;
4416 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4417 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004418 goto out;
4419 if ((status = decode_putrootfh(&xdr)) != 0)
4420 goto out;
4421 if ((status = decode_getfh(&xdr, res->fh)) == 0)
4422 status = decode_getfattr(&xdr, res->fattr, res->server);
4423out:
4424 return status;
4425}
4426
4427/*
4428 * Decode REMOVE response
4429 */
Trond Myklebust4fdc17b2007-07-14 15:39:57 -04004430static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, __be32 *p, struct nfs_removeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004431{
4432 struct xdr_stream xdr;
4433 struct compound_hdr hdr;
4434 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004435
Linus Torvalds1da177e2005-04-16 15:20:36 -07004436 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004437 status = decode_compound_hdr(&xdr, &hdr);
4438 if (status)
4439 goto out;
4440 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4441 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004442 goto out;
Trond Myklebust16e42952005-10-27 22:12:44 -04004443 if ((status = decode_putfh(&xdr)) != 0)
4444 goto out;
4445 if ((status = decode_remove(&xdr, &res->cinfo)) != 0)
4446 goto out;
Trond Myklebust4fdc17b2007-07-14 15:39:57 -04004447 decode_getfattr(&xdr, &res->dir_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004448out:
4449 return status;
4450}
4451
4452/*
4453 * Decode RENAME response
4454 */
Al Viro8687b632006-10-19 23:28:48 -07004455static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_rename_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004456{
4457 struct xdr_stream xdr;
4458 struct compound_hdr hdr;
4459 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004460
Linus Torvalds1da177e2005-04-16 15:20:36 -07004461 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004462 status = decode_compound_hdr(&xdr, &hdr);
4463 if (status)
4464 goto out;
4465 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4466 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004467 goto out;
4468 if ((status = decode_putfh(&xdr)) != 0)
4469 goto out;
4470 if ((status = decode_savefh(&xdr)) != 0)
4471 goto out;
4472 if ((status = decode_putfh(&xdr)) != 0)
4473 goto out;
Trond Myklebust6caf2c82005-10-27 22:12:43 -04004474 if ((status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo)) != 0)
4475 goto out;
4476 /* Current FH is target directory */
4477 if (decode_getfattr(&xdr, res->new_fattr, res->server) != 0)
4478 goto out;
4479 if ((status = decode_restorefh(&xdr)) != 0)
4480 goto out;
4481 decode_getfattr(&xdr, res->old_fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004482out:
4483 return status;
4484}
4485
4486/*
4487 * Decode LINK response
4488 */
Al Viro8687b632006-10-19 23:28:48 -07004489static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_link_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004490{
4491 struct xdr_stream xdr;
4492 struct compound_hdr hdr;
4493 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004494
Linus Torvalds1da177e2005-04-16 15:20:36 -07004495 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004496 status = decode_compound_hdr(&xdr, &hdr);
4497 if (status)
4498 goto out;
4499 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4500 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004501 goto out;
4502 if ((status = decode_putfh(&xdr)) != 0)
4503 goto out;
4504 if ((status = decode_savefh(&xdr)) != 0)
4505 goto out;
4506 if ((status = decode_putfh(&xdr)) != 0)
4507 goto out;
Trond Myklebust91ba2ee2005-10-27 22:12:42 -04004508 if ((status = decode_link(&xdr, &res->cinfo)) != 0)
4509 goto out;
4510 /*
4511 * Note order: OP_LINK leaves the directory as the current
4512 * filehandle.
4513 */
4514 if (decode_getfattr(&xdr, res->dir_attr, res->server) != 0)
4515 goto out;
4516 if ((status = decode_restorefh(&xdr)) != 0)
4517 goto out;
4518 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004519out:
4520 return status;
4521}
4522
4523/*
4524 * Decode CREATE response
4525 */
Al Viro8687b632006-10-19 23:28:48 -07004526static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004527{
4528 struct xdr_stream xdr;
4529 struct compound_hdr hdr;
4530 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004531
Linus Torvalds1da177e2005-04-16 15:20:36 -07004532 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004533 status = decode_compound_hdr(&xdr, &hdr);
4534 if (status)
4535 goto out;
4536 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4537 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004538 goto out;
4539 if ((status = decode_putfh(&xdr)) != 0)
4540 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004541 if ((status = decode_savefh(&xdr)) != 0)
4542 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004543 if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
4544 goto out;
4545 if ((status = decode_getfh(&xdr, res->fh)) != 0)
4546 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004547 if (decode_getfattr(&xdr, res->fattr, res->server) != 0)
4548 goto out;
4549 if ((status = decode_restorefh(&xdr)) != 0)
4550 goto out;
4551 decode_getfattr(&xdr, res->dir_fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004552out:
4553 return status;
4554}
4555
4556/*
4557 * Decode SYMLINK response
4558 */
Al Viro8687b632006-10-19 23:28:48 -07004559static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_create_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004560{
4561 return nfs4_xdr_dec_create(rqstp, p, res);
4562}
4563
4564/*
4565 * Decode GETATTR response
4566 */
Al Viro8687b632006-10-19 23:28:48 -07004567static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_getattr_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004568{
4569 struct xdr_stream xdr;
4570 struct compound_hdr hdr;
4571 int status;
Andy Adamson6c0195a2008-12-23 16:06:15 -05004572
Linus Torvalds1da177e2005-04-16 15:20:36 -07004573 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4574 status = decode_compound_hdr(&xdr, &hdr);
4575 if (status)
4576 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004577 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4578 if (status)
4579 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004580 status = decode_putfh(&xdr);
4581 if (status)
4582 goto out;
4583 status = decode_getfattr(&xdr, res->fattr, res->server);
4584out:
4585 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004586}
4587
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004588/*
4589 * Encode an SETACL request
4590 */
4591static int
Al Viro8687b632006-10-19 23:28:48 -07004592nfs4_xdr_enc_setacl(struct rpc_rqst *req, __be32 *p, struct nfs_setaclargs *args)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004593{
Andy Adamson05d564f2008-12-23 16:06:15 -05004594 struct xdr_stream xdr;
4595 struct compound_hdr hdr = {
Benny Halevy66cc0422009-04-01 09:22:10 -04004596 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
Andy Adamson05d564f2008-12-23 16:06:15 -05004597 };
4598 int status;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004599
Andy Adamson05d564f2008-12-23 16:06:15 -05004600 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
Benny Halevy0c4e8c12009-04-01 09:22:07 -04004601 encode_compound_hdr(&xdr, req, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004602 encode_sequence(&xdr, &args->seq_args, &hdr);
Andy Adamsoncf8cdbe2008-12-23 16:06:18 -05004603 encode_putfh(&xdr, args->fh, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05004604 status = encode_setacl(&xdr, args, &hdr);
Andy Adamsond0179312008-12-23 16:06:17 -05004605 encode_nops(&hdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05004606 return status;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004607}
Andy Adamson05d564f2008-12-23 16:06:15 -05004608
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004609/*
4610 * Decode SETACL response
4611 */
4612static int
Benny Halevy73c403a2009-04-01 09:22:01 -04004613nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, __be32 *p,
4614 struct nfs_setaclres *res)
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004615{
4616 struct xdr_stream xdr;
4617 struct compound_hdr hdr;
4618 int status;
4619
4620 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4621 status = decode_compound_hdr(&xdr, &hdr);
4622 if (status)
4623 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004624 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4625 if (status)
4626 goto out;
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004627 status = decode_putfh(&xdr);
4628 if (status)
4629 goto out;
Benny Halevy9e9ecc02009-04-01 09:22:00 -04004630 status = decode_setattr(&xdr);
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004631out:
4632 return status;
4633}
Linus Torvalds1da177e2005-04-16 15:20:36 -07004634
4635/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00004636 * Decode GETACL response
4637 */
4638static int
Benny Halevy663c79b2009-04-01 09:21:59 -04004639nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, __be32 *p,
4640 struct nfs_getaclres *res)
J. Bruce Fields029d1052005-06-22 17:16:22 +00004641{
4642 struct xdr_stream xdr;
4643 struct compound_hdr hdr;
4644 int status;
4645
4646 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4647 status = decode_compound_hdr(&xdr, &hdr);
4648 if (status)
4649 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004650 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4651 if (status)
4652 goto out;
J. Bruce Fields029d1052005-06-22 17:16:22 +00004653 status = decode_putfh(&xdr);
4654 if (status)
4655 goto out;
Benny Halevy663c79b2009-04-01 09:21:59 -04004656 status = decode_getacl(&xdr, rqstp, &res->acl_len);
J. Bruce Fields029d1052005-06-22 17:16:22 +00004657
4658out:
4659 return status;
4660}
4661
4662/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07004663 * Decode CLOSE response
4664 */
Al Viro8687b632006-10-19 23:28:48 -07004665static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, __be32 *p, struct nfs_closeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004666{
Andy Adamson05d564f2008-12-23 16:06:15 -05004667 struct xdr_stream xdr;
4668 struct compound_hdr hdr;
4669 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004670
Andy Adamson05d564f2008-12-23 16:06:15 -05004671 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4672 status = decode_compound_hdr(&xdr, &hdr);
4673 if (status)
4674 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004675 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4676 if (status)
4677 goto out;
Andy Adamson05d564f2008-12-23 16:06:15 -05004678 status = decode_putfh(&xdr);
4679 if (status)
4680 goto out;
4681 status = decode_close(&xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04004682 if (status != 0)
4683 goto out;
4684 /*
4685 * Note: Server may do delete on close for this file
4686 * in which case the getattr call will fail with
4687 * an ESTALE error. Shouldn't be a problem,
4688 * though, since fattr->valid will remain unset.
4689 */
4690 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004691out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004692 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004693}
4694
4695/*
4696 * Decode OPEN response
4697 */
Al Viro8687b632006-10-19 23:28:48 -07004698static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004699{
Andy Adamson05d564f2008-12-23 16:06:15 -05004700 struct xdr_stream xdr;
4701 struct compound_hdr hdr;
4702 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004703
Andy Adamson05d564f2008-12-23 16:06:15 -05004704 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4705 status = decode_compound_hdr(&xdr, &hdr);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004706 if (status)
4707 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004708 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4709 if (status)
4710 goto out;
Andy Adamson05d564f2008-12-23 16:06:15 -05004711 status = decode_putfh(&xdr);
4712 if (status)
4713 goto out;
4714 status = decode_savefh(&xdr);
4715 if (status)
4716 goto out;
4717 status = decode_open(&xdr, res);
4718 if (status)
4719 goto out;
Trond Myklebust99367812007-07-17 21:52:41 -04004720 if (decode_getfh(&xdr, &res->fh) != 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004721 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004722 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
4723 goto out;
Trond Myklebust365c8f52007-07-17 21:52:37 -04004724 if (decode_restorefh(&xdr) != 0)
Trond Myklebust56ae19f2005-10-27 22:12:40 -04004725 goto out;
4726 decode_getfattr(&xdr, res->dir_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004727out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004728 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004729}
4730
4731/*
4732 * Decode OPEN_CONFIRM response
4733 */
Al Viro8687b632006-10-19 23:28:48 -07004734static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, __be32 *p, struct nfs_open_confirmres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004735{
Andy Adamson05d564f2008-12-23 16:06:15 -05004736 struct xdr_stream xdr;
4737 struct compound_hdr hdr;
4738 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004739
Andy Adamson05d564f2008-12-23 16:06:15 -05004740 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4741 status = decode_compound_hdr(&xdr, &hdr);
4742 if (status)
4743 goto out;
4744 status = decode_putfh(&xdr);
4745 if (status)
4746 goto out;
4747 status = decode_open_confirm(&xdr, res);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004748out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004749 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004750}
4751
4752/*
4753 * Decode OPEN response
4754 */
Al Viro8687b632006-10-19 23:28:48 -07004755static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_openres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004756{
Andy Adamson05d564f2008-12-23 16:06:15 -05004757 struct xdr_stream xdr;
4758 struct compound_hdr hdr;
4759 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004760
Andy Adamson05d564f2008-12-23 16:06:15 -05004761 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4762 status = decode_compound_hdr(&xdr, &hdr);
4763 if (status)
4764 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004765 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4766 if (status)
4767 goto out;
Andy Adamson05d564f2008-12-23 16:06:15 -05004768 status = decode_putfh(&xdr);
4769 if (status)
4770 goto out;
4771 status = decode_open(&xdr, res);
4772 if (status)
4773 goto out;
Trond Myklebust864472e2006-01-03 09:55:15 +01004774 decode_getfattr(&xdr, res->f_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004775out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004776 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004777}
4778
4779/*
4780 * Decode SETATTR response
4781 */
Al Viro8687b632006-10-19 23:28:48 -07004782static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, __be32 *p, struct nfs_setattrres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004783{
Andy Adamson05d564f2008-12-23 16:06:15 -05004784 struct xdr_stream xdr;
4785 struct compound_hdr hdr;
4786 int status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004787
Andy Adamson05d564f2008-12-23 16:06:15 -05004788 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4789 status = decode_compound_hdr(&xdr, &hdr);
4790 if (status)
4791 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004792 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4793 if (status)
4794 goto out;
Andy Adamson05d564f2008-12-23 16:06:15 -05004795 status = decode_putfh(&xdr);
4796 if (status)
4797 goto out;
Benny Halevy9e9ecc02009-04-01 09:22:00 -04004798 status = decode_setattr(&xdr);
Andy Adamson05d564f2008-12-23 16:06:15 -05004799 if (status)
4800 goto out;
Trond Myklebust78f945f2009-03-11 14:10:23 -04004801 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004802out:
Andy Adamson05d564f2008-12-23 16:06:15 -05004803 return status;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004804}
4805
4806/*
4807 * Decode LOCK response
4808 */
Al Viro8687b632006-10-19 23:28:48 -07004809static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lock_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004810{
4811 struct xdr_stream xdr;
4812 struct compound_hdr hdr;
4813 int status;
4814
4815 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4816 status = decode_compound_hdr(&xdr, &hdr);
4817 if (status)
4818 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004819 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4820 if (status)
4821 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004822 status = decode_putfh(&xdr);
4823 if (status)
4824 goto out;
4825 status = decode_lock(&xdr, res);
4826out:
4827 return status;
4828}
4829
4830/*
4831 * Decode LOCKT response
4832 */
Al Viro8687b632006-10-19 23:28:48 -07004833static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, __be32 *p, struct nfs_lockt_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004834{
4835 struct xdr_stream xdr;
4836 struct compound_hdr hdr;
4837 int status;
4838
4839 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4840 status = decode_compound_hdr(&xdr, &hdr);
4841 if (status)
4842 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004843 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4844 if (status)
4845 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004846 status = decode_putfh(&xdr);
4847 if (status)
4848 goto out;
4849 status = decode_lockt(&xdr, res);
4850out:
4851 return status;
4852}
4853
4854/*
4855 * Decode LOCKU response
4856 */
Al Viro8687b632006-10-19 23:28:48 -07004857static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, __be32 *p, struct nfs_locku_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004858{
4859 struct xdr_stream xdr;
4860 struct compound_hdr hdr;
4861 int status;
4862
4863 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4864 status = decode_compound_hdr(&xdr, &hdr);
4865 if (status)
4866 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004867 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4868 if (status)
4869 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004870 status = decode_putfh(&xdr);
4871 if (status)
4872 goto out;
4873 status = decode_locku(&xdr, res);
4874out:
4875 return status;
4876}
4877
4878/*
4879 * Decode READLINK response
4880 */
Benny Halevyf50c7002009-04-01 09:21:55 -04004881static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, __be32 *p,
4882 struct nfs4_readlink_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004883{
4884 struct xdr_stream xdr;
4885 struct compound_hdr hdr;
4886 int status;
4887
4888 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4889 status = decode_compound_hdr(&xdr, &hdr);
4890 if (status)
4891 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004892 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4893 if (status)
4894 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004895 status = decode_putfh(&xdr);
4896 if (status)
4897 goto out;
4898 status = decode_readlink(&xdr, rqstp);
4899out:
4900 return status;
4901}
4902
4903/*
4904 * Decode READDIR response
4905 */
Al Viro8687b632006-10-19 23:28:48 -07004906static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_readdir_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004907{
4908 struct xdr_stream xdr;
4909 struct compound_hdr hdr;
4910 int status;
4911
4912 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4913 status = decode_compound_hdr(&xdr, &hdr);
4914 if (status)
4915 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004916 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4917 if (status)
4918 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004919 status = decode_putfh(&xdr);
4920 if (status)
4921 goto out;
4922 status = decode_readdir(&xdr, rqstp, res);
4923out:
4924 return status;
4925}
4926
4927/*
4928 * Decode Read response
4929 */
Al Viro8687b632006-10-19 23:28:48 -07004930static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, __be32 *p, struct nfs_readres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004931{
4932 struct xdr_stream xdr;
4933 struct compound_hdr hdr;
4934 int status;
4935
4936 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4937 status = decode_compound_hdr(&xdr, &hdr);
4938 if (status)
4939 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004940 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4941 if (status)
4942 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004943 status = decode_putfh(&xdr);
4944 if (status)
4945 goto out;
4946 status = decode_read(&xdr, rqstp, res);
4947 if (!status)
4948 status = res->count;
4949out:
4950 return status;
4951}
4952
4953/*
4954 * Decode WRITE response
4955 */
Al Viro8687b632006-10-19 23:28:48 -07004956static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004957{
4958 struct xdr_stream xdr;
4959 struct compound_hdr hdr;
4960 int status;
4961
4962 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4963 status = decode_compound_hdr(&xdr, &hdr);
4964 if (status)
4965 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004966 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4967 if (status)
4968 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004969 status = decode_putfh(&xdr);
4970 if (status)
4971 goto out;
4972 status = decode_write(&xdr, res);
Trond Myklebust4f9838c2005-10-27 22:12:44 -04004973 if (status)
4974 goto out;
4975 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07004976 if (!status)
4977 status = res->count;
4978out:
4979 return status;
4980}
4981
4982/*
4983 * Decode COMMIT response
4984 */
Al Viro8687b632006-10-19 23:28:48 -07004985static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, __be32 *p, struct nfs_writeres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07004986{
4987 struct xdr_stream xdr;
4988 struct compound_hdr hdr;
4989 int status;
4990
4991 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4992 status = decode_compound_hdr(&xdr, &hdr);
4993 if (status)
4994 goto out;
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04004995 status = decode_sequence(&xdr, &res->seq_res, rqstp);
4996 if (status)
4997 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07004998 status = decode_putfh(&xdr);
4999 if (status)
5000 goto out;
5001 status = decode_commit(&xdr, res);
Trond Myklebust4f9838c2005-10-27 22:12:44 -04005002 if (status)
5003 goto out;
5004 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005005out:
5006 return status;
5007}
5008
5009/*
5010 * FSINFO request
5011 */
Benny Halevy3dda5e42009-04-01 09:21:57 -04005012static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, __be32 *p,
5013 struct nfs4_fsinfo_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005014{
5015 struct xdr_stream xdr;
5016 struct compound_hdr hdr;
5017 int status;
5018
5019 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5020 status = decode_compound_hdr(&xdr, &hdr);
5021 if (!status)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005022 status = decode_sequence(&xdr, &res->seq_res, req);
5023 if (!status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005024 status = decode_putfh(&xdr);
5025 if (!status)
Benny Halevy3dda5e42009-04-01 09:21:57 -04005026 status = decode_fsinfo(&xdr, res->fsinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005027 return status;
5028}
5029
5030/*
5031 * PATHCONF request
5032 */
Benny Halevyd45b2982009-04-01 09:21:58 -04005033static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, __be32 *p,
5034 struct nfs4_pathconf_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005035{
5036 struct xdr_stream xdr;
5037 struct compound_hdr hdr;
5038 int status;
5039
5040 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5041 status = decode_compound_hdr(&xdr, &hdr);
5042 if (!status)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005043 status = decode_sequence(&xdr, &res->seq_res, req);
5044 if (!status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005045 status = decode_putfh(&xdr);
5046 if (!status)
Benny Halevyd45b2982009-04-01 09:21:58 -04005047 status = decode_pathconf(&xdr, res->pathconf);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005048 return status;
5049}
5050
5051/*
5052 * STATFS request
5053 */
Benny Halevy24ad1482009-04-01 09:21:56 -04005054static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, __be32 *p,
5055 struct nfs4_statfs_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005056{
5057 struct xdr_stream xdr;
5058 struct compound_hdr hdr;
5059 int status;
5060
5061 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5062 status = decode_compound_hdr(&xdr, &hdr);
5063 if (!status)
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005064 status = decode_sequence(&xdr, &res->seq_res, req);
5065 if (!status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005066 status = decode_putfh(&xdr);
5067 if (!status)
Benny Halevy24ad1482009-04-01 09:21:56 -04005068 status = decode_statfs(&xdr, res->fsstat);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005069 return status;
5070}
5071
5072/*
5073 * GETATTR_BITMAP request
5074 */
Al Viro8687b632006-10-19 23:28:48 -07005075static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, __be32 *p, struct nfs4_server_caps_res *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005076{
5077 struct xdr_stream xdr;
5078 struct compound_hdr hdr;
5079 int status;
5080
5081 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005082 status = decode_compound_hdr(&xdr, &hdr);
5083 if (status)
5084 goto out;
5085 status = decode_sequence(&xdr, &res->seq_res, req);
5086 if (status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005087 goto out;
5088 if ((status = decode_putfh(&xdr)) != 0)
5089 goto out;
5090 status = decode_server_caps(&xdr, res);
5091out:
5092 return status;
5093}
5094
5095/*
5096 * Decode RENEW response
5097 */
Al Viro8687b632006-10-19 23:28:48 -07005098static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, __be32 *p, void *dummy)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005099{
5100 struct xdr_stream xdr;
5101 struct compound_hdr hdr;
5102 int status;
5103
5104 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5105 status = decode_compound_hdr(&xdr, &hdr);
5106 if (!status)
5107 status = decode_renew(&xdr);
5108 return status;
5109}
5110
5111/*
5112 * a SETCLIENTID request
5113 */
Al Viro8687b632006-10-19 23:28:48 -07005114static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, __be32 *p,
David Howellsadfa6f92006-08-22 20:06:08 -04005115 struct nfs_client *clp)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005116{
5117 struct xdr_stream xdr;
5118 struct compound_hdr hdr;
5119 int status;
5120
5121 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5122 status = decode_compound_hdr(&xdr, &hdr);
5123 if (!status)
5124 status = decode_setclientid(&xdr, clp);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005125 return status;
5126}
5127
5128/*
5129 * a SETCLIENTID_CONFIRM request
5130 */
Al Viro8687b632006-10-19 23:28:48 -07005131static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *fsinfo)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005132{
5133 struct xdr_stream xdr;
5134 struct compound_hdr hdr;
5135 int status;
5136
5137 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5138 status = decode_compound_hdr(&xdr, &hdr);
5139 if (!status)
5140 status = decode_setclientid_confirm(&xdr);
5141 if (!status)
5142 status = decode_putrootfh(&xdr);
5143 if (!status)
5144 status = decode_fsinfo(&xdr, fsinfo);
Linus Torvalds1da177e2005-04-16 15:20:36 -07005145 return status;
5146}
5147
5148/*
5149 * DELEGRETURN request
5150 */
Al Viro8687b632006-10-19 23:28:48 -07005151static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, __be32 *p, struct nfs4_delegreturnres *res)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005152{
5153 struct xdr_stream xdr;
5154 struct compound_hdr hdr;
5155 int status;
5156
5157 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5158 status = decode_compound_hdr(&xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005159 if (status)
5160 goto out;
5161 status = decode_sequence(&xdr, &res->seq_res, rqstp);
5162 if (status)
Trond Myklebustfa178f22006-01-03 09:55:38 +01005163 goto out;
5164 status = decode_putfh(&xdr);
5165 if (status != 0)
5166 goto out;
5167 status = decode_delegreturn(&xdr);
5168 decode_getfattr(&xdr, res->fattr, res->server);
5169out:
Linus Torvalds1da177e2005-04-16 15:20:36 -07005170 return status;
5171}
5172
Trond Myklebust683b57b2006-06-09 09:34:22 -04005173/*
5174 * FS_LOCATIONS request
5175 */
Benny Halevy22958462009-04-01 09:22:02 -04005176static int nfs4_xdr_dec_fs_locations(struct rpc_rqst *req, __be32 *p,
5177 struct nfs4_fs_locations_res *res)
Trond Myklebust683b57b2006-06-09 09:34:22 -04005178{
5179 struct xdr_stream xdr;
5180 struct compound_hdr hdr;
5181 int status;
5182
5183 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
5184 status = decode_compound_hdr(&xdr, &hdr);
Andy Adamson9b7b9fc2009-04-01 09:22:11 -04005185 if (status)
5186 goto out;
5187 status = decode_sequence(&xdr, &res->seq_res, req);
5188 if (status)
Trond Myklebust683b57b2006-06-09 09:34:22 -04005189 goto out;
5190 if ((status = decode_putfh(&xdr)) != 0)
5191 goto out;
5192 if ((status = decode_lookup(&xdr)) != 0)
5193 goto out;
5194 xdr_enter_page(&xdr, PAGE_SIZE);
Benny Halevy22958462009-04-01 09:22:02 -04005195 status = decode_getfattr(&xdr, &res->fs_locations->fattr,
5196 res->fs_locations->server);
Trond Myklebust683b57b2006-06-09 09:34:22 -04005197out:
5198 return status;
5199}
5200
Benny Halevy99fe60d2009-04-01 09:22:29 -04005201#if defined(CONFIG_NFS_V4_1)
5202/*
5203 * EXCHANGE_ID request
5204 */
5205static int nfs4_xdr_dec_exchange_id(struct rpc_rqst *rqstp, uint32_t *p,
5206 void *res)
5207{
5208 struct xdr_stream xdr;
5209 struct compound_hdr hdr;
5210 int status;
5211
5212 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5213 status = decode_compound_hdr(&xdr, &hdr);
5214 if (!status)
5215 status = decode_exchange_id(&xdr, res);
5216 return status;
5217}
Andy Adamson2050f0c2009-04-01 09:22:30 -04005218
5219/*
Andy Adamsonfc931582009-04-01 09:22:31 -04005220 * a CREATE_SESSION request
5221 */
5222static int nfs4_xdr_dec_create_session(struct rpc_rqst *rqstp, uint32_t *p,
5223 struct nfs41_create_session_res *res)
5224{
5225 struct xdr_stream xdr;
5226 struct compound_hdr hdr;
5227 int status;
5228
5229 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5230 status = decode_compound_hdr(&xdr, &hdr);
5231 if (!status)
5232 status = decode_create_session(&xdr, res);
5233 return status;
5234}
5235
5236/*
Andy Adamson0f3e66c2009-04-01 09:22:34 -04005237 * a DESTROY_SESSION request
5238 */
5239static int nfs4_xdr_dec_destroy_session(struct rpc_rqst *rqstp, uint32_t *p,
5240 void *dummy)
5241{
5242 struct xdr_stream xdr;
5243 struct compound_hdr hdr;
5244 int status;
5245
5246 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5247 status = decode_compound_hdr(&xdr, &hdr);
5248 if (!status)
5249 status = decode_destroy_session(&xdr, dummy);
5250 return status;
5251}
5252
5253/*
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005254 * a SEQUENCE request
5255 */
5256static int nfs4_xdr_dec_sequence(struct rpc_rqst *rqstp, uint32_t *p,
5257 struct nfs4_sequence_res *res)
5258{
5259 struct xdr_stream xdr;
5260 struct compound_hdr hdr;
5261 int status;
5262
5263 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5264 status = decode_compound_hdr(&xdr, &hdr);
5265 if (!status)
5266 status = decode_sequence(&xdr, res, rqstp);
5267 return status;
5268}
5269
5270/*
Andy Adamson2050f0c2009-04-01 09:22:30 -04005271 * a GET_LEASE_TIME request
5272 */
5273static int nfs4_xdr_dec_get_lease_time(struct rpc_rqst *rqstp, uint32_t *p,
5274 struct nfs4_get_lease_time_res *res)
5275{
5276 struct xdr_stream xdr;
5277 struct compound_hdr hdr;
5278 int status;
5279
5280 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
5281 status = decode_compound_hdr(&xdr, &hdr);
5282 if (!status)
5283 status = decode_sequence(&xdr, &res->lr_seq_res, rqstp);
5284 if (!status)
5285 status = decode_putrootfh(&xdr);
5286 if (!status)
5287 status = decode_fsinfo(&xdr, res->lr_fsinfo);
5288 return status;
5289}
Benny Halevy99fe60d2009-04-01 09:22:29 -04005290#endif /* CONFIG_NFS_V4_1 */
5291
Al Viro0dbb4c62006-10-19 23:28:49 -07005292__be32 *nfs4_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005293{
5294 uint32_t bitmap[2] = {0};
5295 uint32_t len;
5296
5297 if (!*p++) {
5298 if (!*p)
5299 return ERR_PTR(-EAGAIN);
5300 entry->eof = 1;
5301 return ERR_PTR(-EBADCOOKIE);
5302 }
5303
5304 entry->prev_cookie = entry->cookie;
5305 p = xdr_decode_hyper(p, &entry->cookie);
5306 entry->len = ntohl(*p++);
5307 entry->name = (const char *) p;
5308 p += XDR_QUADLEN(entry->len);
5309
5310 /*
5311 * In case the server doesn't return an inode number,
5312 * we fake one here. (We don't use inode number 0,
5313 * since glibc seems to choke on it...)
5314 */
5315 entry->ino = 1;
5316
5317 len = ntohl(*p++); /* bitmap length */
5318 if (len-- > 0) {
5319 bitmap[0] = ntohl(*p++);
5320 if (len-- > 0) {
5321 bitmap[1] = ntohl(*p++);
5322 p += len;
5323 }
5324 }
5325 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
5326 if (len > 0) {
Manoj Naik97d312d2005-06-22 17:16:39 +00005327 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
5328 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
5329 /* Ignore the return value of rdattr_error for now */
5330 p++;
5331 len--;
5332 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005333 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
5334 xdr_decode_hyper(p, &entry->ino);
5335 else if (bitmap[0] == FATTR4_WORD0_FILEID)
5336 xdr_decode_hyper(p, &entry->ino);
5337 p += len;
5338 }
5339
5340 entry->eof = !p[0] && p[1];
5341 return p;
5342}
5343
5344/*
5345 * We need to translate between nfs status return values and
5346 * the local errno values which may not be the same.
5347 */
5348static struct {
5349 int stat;
5350 int errno;
5351} nfs_errtbl[] = {
5352 { NFS4_OK, 0 },
Benny Halevy856dff32008-03-31 17:39:06 +03005353 { NFS4ERR_PERM, -EPERM },
5354 { NFS4ERR_NOENT, -ENOENT },
5355 { NFS4ERR_IO, -errno_NFSERR_IO},
5356 { NFS4ERR_NXIO, -ENXIO },
5357 { NFS4ERR_ACCESS, -EACCES },
5358 { NFS4ERR_EXIST, -EEXIST },
5359 { NFS4ERR_XDEV, -EXDEV },
5360 { NFS4ERR_NOTDIR, -ENOTDIR },
5361 { NFS4ERR_ISDIR, -EISDIR },
5362 { NFS4ERR_INVAL, -EINVAL },
5363 { NFS4ERR_FBIG, -EFBIG },
5364 { NFS4ERR_NOSPC, -ENOSPC },
5365 { NFS4ERR_ROFS, -EROFS },
5366 { NFS4ERR_MLINK, -EMLINK },
5367 { NFS4ERR_NAMETOOLONG, -ENAMETOOLONG },
5368 { NFS4ERR_NOTEMPTY, -ENOTEMPTY },
5369 { NFS4ERR_DQUOT, -EDQUOT },
5370 { NFS4ERR_STALE, -ESTALE },
5371 { NFS4ERR_BADHANDLE, -EBADHANDLE },
5372 { NFS4ERR_BADOWNER, -EINVAL },
5373 { NFS4ERR_BADNAME, -EINVAL },
5374 { NFS4ERR_BAD_COOKIE, -EBADCOOKIE },
5375 { NFS4ERR_NOTSUPP, -ENOTSUPP },
5376 { NFS4ERR_TOOSMALL, -ETOOSMALL },
5377 { NFS4ERR_SERVERFAULT, -ESERVERFAULT },
5378 { NFS4ERR_BADTYPE, -EBADTYPE },
5379 { NFS4ERR_LOCKED, -EAGAIN },
5380 { NFS4ERR_RESOURCE, -EREMOTEIO },
5381 { NFS4ERR_SYMLINK, -ELOOP },
5382 { NFS4ERR_OP_ILLEGAL, -EOPNOTSUPP },
5383 { NFS4ERR_DEADLOCK, -EDEADLK },
5384 { NFS4ERR_WRONGSEC, -EPERM }, /* FIXME: this needs
Linus Torvalds1da177e2005-04-16 15:20:36 -07005385 * to be handled by a
5386 * middle-layer.
5387 */
Benny Halevy856dff32008-03-31 17:39:06 +03005388 { -1, -EIO }
Linus Torvalds1da177e2005-04-16 15:20:36 -07005389};
5390
5391/*
5392 * Convert an NFS error code to a local one.
5393 * This one is used jointly by NFSv2 and NFSv3.
5394 */
5395static int
David Howells0a8ea432006-08-22 20:06:08 -04005396nfs4_stat_to_errno(int stat)
Linus Torvalds1da177e2005-04-16 15:20:36 -07005397{
5398 int i;
5399 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
5400 if (nfs_errtbl[i].stat == stat)
5401 return nfs_errtbl[i].errno;
5402 }
5403 if (stat <= 10000 || stat > 10100) {
5404 /* The server is looney tunes. */
Benny Halevy856dff32008-03-31 17:39:06 +03005405 return -ESERVERFAULT;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005406 }
5407 /* If we cannot translate the error, the recovery routines should
5408 * handle it.
5409 * Note: remaining NFSv4 error codes have values > 10000, so should
5410 * not conflict with native Linux error codes.
5411 */
Benny Halevy856dff32008-03-31 17:39:06 +03005412 return -stat;
Linus Torvalds1da177e2005-04-16 15:20:36 -07005413}
5414
Linus Torvalds1da177e2005-04-16 15:20:36 -07005415#define PROC(proc, argtype, restype) \
5416[NFSPROC4_CLNT_##proc] = { \
5417 .p_proc = NFSPROC4_COMPOUND, \
5418 .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
5419 .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
Chuck Lever2bea90d2007-03-29 16:47:53 -04005420 .p_arglen = NFS4_##argtype##_sz, \
5421 .p_replen = NFS4_##restype##_sz, \
Chuck Levercc0175c2006-03-20 13:44:22 -05005422 .p_statidx = NFSPROC4_CLNT_##proc, \
5423 .p_name = #proc, \
Andy Adamson05d564f2008-12-23 16:06:15 -05005424}
Linus Torvalds1da177e2005-04-16 15:20:36 -07005425
5426struct rpc_procinfo nfs4_procedures[] = {
5427 PROC(READ, enc_read, dec_read),
5428 PROC(WRITE, enc_write, dec_write),
5429 PROC(COMMIT, enc_commit, dec_commit),
5430 PROC(OPEN, enc_open, dec_open),
5431 PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
5432 PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr),
5433 PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade),
5434 PROC(CLOSE, enc_close, dec_close),
5435 PROC(SETATTR, enc_setattr, dec_setattr),
5436 PROC(FSINFO, enc_fsinfo, dec_fsinfo),
5437 PROC(RENEW, enc_renew, dec_renew),
5438 PROC(SETCLIENTID, enc_setclientid, dec_setclientid),
5439 PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm),
5440 PROC(LOCK, enc_lock, dec_lock),
5441 PROC(LOCKT, enc_lockt, dec_lockt),
5442 PROC(LOCKU, enc_locku, dec_locku),
5443 PROC(ACCESS, enc_access, dec_access),
5444 PROC(GETATTR, enc_getattr, dec_getattr),
5445 PROC(LOOKUP, enc_lookup, dec_lookup),
5446 PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
5447 PROC(REMOVE, enc_remove, dec_remove),
5448 PROC(RENAME, enc_rename, dec_rename),
5449 PROC(LINK, enc_link, dec_link),
5450 PROC(SYMLINK, enc_symlink, dec_symlink),
5451 PROC(CREATE, enc_create, dec_create),
5452 PROC(PATHCONF, enc_pathconf, dec_pathconf),
5453 PROC(STATFS, enc_statfs, dec_statfs),
5454 PROC(READLINK, enc_readlink, dec_readlink),
5455 PROC(READDIR, enc_readdir, dec_readdir),
5456 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
5457 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
J. Bruce Fields029d1052005-06-22 17:16:22 +00005458 PROC(GETACL, enc_getacl, dec_getacl),
J. Bruce Fields23ec6962005-06-22 17:16:22 +00005459 PROC(SETACL, enc_setacl, dec_setacl),
Trond Myklebust683b57b2006-06-09 09:34:22 -04005460 PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations),
Benny Halevy99fe60d2009-04-01 09:22:29 -04005461#if defined(CONFIG_NFS_V4_1)
5462 PROC(EXCHANGE_ID, enc_exchange_id, dec_exchange_id),
Andy Adamsonfc931582009-04-01 09:22:31 -04005463 PROC(CREATE_SESSION, enc_create_session, dec_create_session),
Andy Adamson0f3e66c2009-04-01 09:22:34 -04005464 PROC(DESTROY_SESSION, enc_destroy_session, dec_destroy_session),
Andy Adamsonfc01cea2009-04-01 09:22:36 -04005465 PROC(SEQUENCE, enc_sequence, dec_sequence),
Andy Adamson2050f0c2009-04-01 09:22:30 -04005466 PROC(GET_LEASE_TIME, enc_get_lease_time, dec_get_lease_time),
Benny Halevy99fe60d2009-04-01 09:22:29 -04005467#endif /* CONFIG_NFS_V4_1 */
Linus Torvalds1da177e2005-04-16 15:20:36 -07005468};
5469
5470struct rpc_version nfs_version4 = {
5471 .number = 4,
Tobias Klausere8c96f82006-03-24 03:15:34 -08005472 .nrprocs = ARRAY_SIZE(nfs4_procedures),
Linus Torvalds1da177e2005-04-16 15:20:36 -07005473 .procs = nfs4_procedures
5474};
5475
5476/*
5477 * Local variables:
5478 * c-basic-offset: 8
5479 * End:
5480 */