blob: cd9e26cfa868917c1c393433df32b1fc5892762c [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>
11 *
12 * 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
61static int nfs_stat_to_errno(int);
62
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
70/* lock,open owner id:
71 * we currently use size 1 (u32) out of (NFS4_OPAQUE_LIMIT >> 2)
72 */
73#define owner_id_maxsz (1 + 1)
74#define compound_encode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
75#define compound_decode_hdr_maxsz (3 + (NFS4_MAXTAGLEN >> 2))
76#define op_encode_hdr_maxsz (1)
77#define op_decode_hdr_maxsz (2)
78#define encode_putfh_maxsz (op_encode_hdr_maxsz + 1 + \
79 (NFS4_FHSIZE >> 2))
80#define decode_putfh_maxsz (op_decode_hdr_maxsz)
81#define encode_putrootfh_maxsz (op_encode_hdr_maxsz)
82#define decode_putrootfh_maxsz (op_decode_hdr_maxsz)
83#define encode_getfh_maxsz (op_encode_hdr_maxsz)
84#define decode_getfh_maxsz (op_decode_hdr_maxsz + 1 + \
85 ((3+NFS4_FHSIZE) >> 2))
J. Bruce Fields96928202005-06-22 17:16:22 +000086#define nfs4_fattr_bitmap_maxsz 3
87#define encode_getattr_maxsz (op_encode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070088#define nfs4_name_maxsz (1 + ((3 + NFS4_MAXNAMLEN) >> 2))
89#define nfs4_path_maxsz (1 + ((3 + NFS4_MAXPATHLEN) >> 2))
J. Bruce Fields96928202005-06-22 17:16:22 +000090/* This is based on getfattr, which uses the most attributes: */
91#define nfs4_fattr_value_maxsz (1 + (1 + 2 + 2 + 4 + 2 + 1 + 1 + 2 + 2 + \
92 3 + 3 + 3 + 2 * nfs4_name_maxsz))
93#define nfs4_fattr_maxsz (nfs4_fattr_bitmap_maxsz + \
94 nfs4_fattr_value_maxsz)
95#define decode_getattr_maxsz (op_decode_hdr_maxsz + nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070096#define encode_savefh_maxsz (op_encode_hdr_maxsz)
97#define decode_savefh_maxsz (op_decode_hdr_maxsz)
Trond Myklebust56ae19f2005-10-27 22:12:40 -040098#define encode_restorefh_maxsz (op_encode_hdr_maxsz)
99#define decode_restorefh_maxsz (op_decode_hdr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700100#define encode_fsinfo_maxsz (op_encode_hdr_maxsz + 2)
101#define decode_fsinfo_maxsz (op_decode_hdr_maxsz + 11)
102#define encode_renew_maxsz (op_encode_hdr_maxsz + 3)
103#define decode_renew_maxsz (op_decode_hdr_maxsz)
104#define encode_setclientid_maxsz \
105 (op_encode_hdr_maxsz + \
106 4 /*server->ip_addr*/ + \
107 1 /*Netid*/ + \
108 6 /*uaddr*/ + \
109 6 + (NFS4_VERIFIER_SIZE >> 2))
110#define decode_setclientid_maxsz \
111 (op_decode_hdr_maxsz + \
112 2 + \
113 1024) /* large value for CLID_INUSE */
114#define encode_setclientid_confirm_maxsz \
115 (op_encode_hdr_maxsz + \
116 3 + (NFS4_VERIFIER_SIZE >> 2))
117#define decode_setclientid_confirm_maxsz \
118 (op_decode_hdr_maxsz)
119#define encode_lookup_maxsz (op_encode_hdr_maxsz + \
120 1 + ((3 + NFS4_FHSIZE) >> 2))
121#define encode_remove_maxsz (op_encode_hdr_maxsz + \
122 nfs4_name_maxsz)
123#define encode_rename_maxsz (op_encode_hdr_maxsz + \
124 2 * nfs4_name_maxsz)
125#define decode_rename_maxsz (op_decode_hdr_maxsz + 5 + 5)
126#define encode_link_maxsz (op_encode_hdr_maxsz + \
127 nfs4_name_maxsz)
128#define decode_link_maxsz (op_decode_hdr_maxsz + 5)
129#define encode_symlink_maxsz (op_encode_hdr_maxsz + \
130 1 + nfs4_name_maxsz + \
131 nfs4_path_maxsz + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000132 nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700133#define decode_symlink_maxsz (op_decode_hdr_maxsz + 8)
134#define encode_create_maxsz (op_encode_hdr_maxsz + \
135 2 + nfs4_name_maxsz + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000136 nfs4_fattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700137#define decode_create_maxsz (op_decode_hdr_maxsz + 8)
138#define encode_delegreturn_maxsz (op_encode_hdr_maxsz + 4)
139#define decode_delegreturn_maxsz (op_decode_hdr_maxsz)
140#define NFS4_enc_compound_sz (1024) /* XXX: large enough? */
141#define NFS4_dec_compound_sz (1024) /* XXX: large enough? */
142#define NFS4_enc_read_sz (compound_encode_hdr_maxsz + \
143 encode_putfh_maxsz + \
144 op_encode_hdr_maxsz + 7)
145#define NFS4_dec_read_sz (compound_decode_hdr_maxsz + \
146 decode_putfh_maxsz + \
147 op_decode_hdr_maxsz + 2)
148#define NFS4_enc_readlink_sz (compound_encode_hdr_maxsz + \
149 encode_putfh_maxsz + \
150 op_encode_hdr_maxsz)
151#define NFS4_dec_readlink_sz (compound_decode_hdr_maxsz + \
152 decode_putfh_maxsz + \
153 op_decode_hdr_maxsz)
154#define NFS4_enc_readdir_sz (compound_encode_hdr_maxsz + \
155 encode_putfh_maxsz + \
156 op_encode_hdr_maxsz + 9)
157#define NFS4_dec_readdir_sz (compound_decode_hdr_maxsz + \
158 decode_putfh_maxsz + \
159 op_decode_hdr_maxsz + 2)
160#define NFS4_enc_write_sz (compound_encode_hdr_maxsz + \
161 encode_putfh_maxsz + \
162 op_encode_hdr_maxsz + 8)
163#define NFS4_dec_write_sz (compound_decode_hdr_maxsz + \
164 decode_putfh_maxsz + \
165 op_decode_hdr_maxsz + 4)
166#define NFS4_enc_commit_sz (compound_encode_hdr_maxsz + \
167 encode_putfh_maxsz + \
168 op_encode_hdr_maxsz + 3)
169#define NFS4_dec_commit_sz (compound_decode_hdr_maxsz + \
170 decode_putfh_maxsz + \
171 op_decode_hdr_maxsz + 2)
172#define NFS4_enc_open_sz (compound_encode_hdr_maxsz + \
173 encode_putfh_maxsz + \
174 op_encode_hdr_maxsz + \
175 13 + 3 + 2 + 64 + \
176 encode_getattr_maxsz + \
177 encode_getfh_maxsz)
178#define NFS4_dec_open_sz (compound_decode_hdr_maxsz + \
179 decode_putfh_maxsz + \
180 op_decode_hdr_maxsz + 4 + 5 + 2 + 3 + \
181 decode_getattr_maxsz + \
182 decode_getfh_maxsz)
183#define NFS4_enc_open_confirm_sz \
184 (compound_encode_hdr_maxsz + \
185 encode_putfh_maxsz + \
186 op_encode_hdr_maxsz + 5)
187#define NFS4_dec_open_confirm_sz (compound_decode_hdr_maxsz + \
188 decode_putfh_maxsz + \
189 op_decode_hdr_maxsz + 4)
190#define NFS4_enc_open_noattr_sz (compound_encode_hdr_maxsz + \
191 encode_putfh_maxsz + \
192 op_encode_hdr_maxsz + \
193 11)
194#define NFS4_dec_open_noattr_sz (compound_decode_hdr_maxsz + \
195 decode_putfh_maxsz + \
196 op_decode_hdr_maxsz + \
197 4 + 5 + 2 + 3)
198#define NFS4_enc_open_downgrade_sz \
199 (compound_encode_hdr_maxsz + \
200 encode_putfh_maxsz + \
Trond Myklebust516a6af2005-10-27 22:12:41 -0400201 op_encode_hdr_maxsz + 7 + \
202 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700203#define NFS4_dec_open_downgrade_sz \
204 (compound_decode_hdr_maxsz + \
205 decode_putfh_maxsz + \
Trond Myklebust516a6af2005-10-27 22:12:41 -0400206 op_decode_hdr_maxsz + 4 + \
207 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700208#define NFS4_enc_close_sz (compound_encode_hdr_maxsz + \
209 encode_putfh_maxsz + \
Trond Myklebust516a6af2005-10-27 22:12:41 -0400210 op_encode_hdr_maxsz + 5 + \
211 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700212#define NFS4_dec_close_sz (compound_decode_hdr_maxsz + \
213 decode_putfh_maxsz + \
Trond Myklebust516a6af2005-10-27 22:12:41 -0400214 op_decode_hdr_maxsz + 4 + \
215 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700216#define NFS4_enc_setattr_sz (compound_encode_hdr_maxsz + \
217 encode_putfh_maxsz + \
218 op_encode_hdr_maxsz + 4 + \
J. Bruce Fields96928202005-06-22 17:16:22 +0000219 nfs4_fattr_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700220 encode_getattr_maxsz)
221#define NFS4_dec_setattr_sz (compound_decode_hdr_maxsz + \
222 decode_putfh_maxsz + \
223 op_decode_hdr_maxsz + 3)
224#define NFS4_enc_fsinfo_sz (compound_encode_hdr_maxsz + \
225 encode_putfh_maxsz + \
226 encode_fsinfo_maxsz)
227#define NFS4_dec_fsinfo_sz (compound_decode_hdr_maxsz + \
228 decode_putfh_maxsz + \
229 decode_fsinfo_maxsz)
230#define NFS4_enc_renew_sz (compound_encode_hdr_maxsz + \
231 encode_renew_maxsz)
232#define NFS4_dec_renew_sz (compound_decode_hdr_maxsz + \
233 decode_renew_maxsz)
234#define NFS4_enc_setclientid_sz (compound_encode_hdr_maxsz + \
235 encode_setclientid_maxsz)
236#define NFS4_dec_setclientid_sz (compound_decode_hdr_maxsz + \
237 decode_setclientid_maxsz)
238#define NFS4_enc_setclientid_confirm_sz \
239 (compound_encode_hdr_maxsz + \
240 encode_setclientid_confirm_maxsz + \
241 encode_putrootfh_maxsz + \
242 encode_fsinfo_maxsz)
243#define NFS4_dec_setclientid_confirm_sz \
244 (compound_decode_hdr_maxsz + \
245 decode_setclientid_confirm_maxsz + \
246 decode_putrootfh_maxsz + \
247 decode_fsinfo_maxsz)
248#define NFS4_enc_lock_sz (compound_encode_hdr_maxsz + \
249 encode_putfh_maxsz + \
250 encode_getattr_maxsz + \
251 op_encode_hdr_maxsz + \
252 1 + 1 + 2 + 2 + \
253 1 + 4 + 1 + 2 + \
254 owner_id_maxsz)
255#define NFS4_dec_lock_sz (compound_decode_hdr_maxsz + \
256 decode_putfh_maxsz + \
257 decode_getattr_maxsz + \
258 op_decode_hdr_maxsz + \
259 2 + 2 + 1 + 2 + \
260 owner_id_maxsz)
261#define NFS4_enc_lockt_sz (compound_encode_hdr_maxsz + \
262 encode_putfh_maxsz + \
263 encode_getattr_maxsz + \
264 op_encode_hdr_maxsz + \
265 1 + 2 + 2 + 2 + \
266 owner_id_maxsz)
267#define NFS4_dec_lockt_sz (NFS4_dec_lock_sz)
268#define NFS4_enc_locku_sz (compound_encode_hdr_maxsz + \
269 encode_putfh_maxsz + \
270 encode_getattr_maxsz + \
271 op_encode_hdr_maxsz + \
272 1 + 1 + 4 + 2 + 2)
273#define NFS4_dec_locku_sz (compound_decode_hdr_maxsz + \
274 decode_putfh_maxsz + \
275 decode_getattr_maxsz + \
276 op_decode_hdr_maxsz + 4)
277#define NFS4_enc_access_sz (compound_encode_hdr_maxsz + \
278 encode_putfh_maxsz + \
279 op_encode_hdr_maxsz + 1)
280#define NFS4_dec_access_sz (compound_decode_hdr_maxsz + \
281 decode_putfh_maxsz + \
282 op_decode_hdr_maxsz + 2)
283#define NFS4_enc_getattr_sz (compound_encode_hdr_maxsz + \
284 encode_putfh_maxsz + \
285 encode_getattr_maxsz)
286#define NFS4_dec_getattr_sz (compound_decode_hdr_maxsz + \
287 decode_putfh_maxsz + \
288 decode_getattr_maxsz)
289#define NFS4_enc_lookup_sz (compound_encode_hdr_maxsz + \
290 encode_putfh_maxsz + \
291 encode_lookup_maxsz + \
292 encode_getattr_maxsz + \
293 encode_getfh_maxsz)
294#define NFS4_dec_lookup_sz (compound_decode_hdr_maxsz + \
295 decode_putfh_maxsz + \
296 op_decode_hdr_maxsz + \
297 decode_getattr_maxsz + \
298 decode_getfh_maxsz)
299#define NFS4_enc_lookup_root_sz (compound_encode_hdr_maxsz + \
300 encode_putrootfh_maxsz + \
301 encode_getattr_maxsz + \
302 encode_getfh_maxsz)
303#define NFS4_dec_lookup_root_sz (compound_decode_hdr_maxsz + \
304 decode_putrootfh_maxsz + \
305 decode_getattr_maxsz + \
306 decode_getfh_maxsz)
307#define NFS4_enc_remove_sz (compound_encode_hdr_maxsz + \
308 encode_putfh_maxsz + \
309 encode_remove_maxsz)
310#define NFS4_dec_remove_sz (compound_decode_hdr_maxsz + \
311 decode_putfh_maxsz + \
312 op_decode_hdr_maxsz + 5)
313#define NFS4_enc_rename_sz (compound_encode_hdr_maxsz + \
314 encode_putfh_maxsz + \
315 encode_savefh_maxsz + \
316 encode_putfh_maxsz + \
317 encode_rename_maxsz)
318#define NFS4_dec_rename_sz (compound_decode_hdr_maxsz + \
319 decode_putfh_maxsz + \
320 decode_savefh_maxsz + \
321 decode_putfh_maxsz + \
322 decode_rename_maxsz)
323#define NFS4_enc_link_sz (compound_encode_hdr_maxsz + \
324 encode_putfh_maxsz + \
325 encode_savefh_maxsz + \
326 encode_putfh_maxsz + \
327 encode_link_maxsz)
328#define NFS4_dec_link_sz (compound_decode_hdr_maxsz + \
329 decode_putfh_maxsz + \
330 decode_savefh_maxsz + \
331 decode_putfh_maxsz + \
332 decode_link_maxsz)
333#define NFS4_enc_symlink_sz (compound_encode_hdr_maxsz + \
334 encode_putfh_maxsz + \
335 encode_symlink_maxsz + \
336 encode_getattr_maxsz + \
337 encode_getfh_maxsz)
338#define NFS4_dec_symlink_sz (compound_decode_hdr_maxsz + \
339 decode_putfh_maxsz + \
340 decode_symlink_maxsz + \
341 decode_getattr_maxsz + \
342 decode_getfh_maxsz)
343#define NFS4_enc_create_sz (compound_encode_hdr_maxsz + \
344 encode_putfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400345 encode_savefh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700346 encode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400347 encode_getfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700348 encode_getattr_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400349 encode_restorefh_maxsz + \
350 encode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700351#define NFS4_dec_create_sz (compound_decode_hdr_maxsz + \
352 decode_putfh_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400353 decode_savefh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700354 decode_create_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400355 decode_getfh_maxsz + \
Linus Torvalds1da177e2005-04-16 15:20:36 -0700356 decode_getattr_maxsz + \
Trond Myklebust56ae19f2005-10-27 22:12:40 -0400357 decode_restorefh_maxsz + \
358 decode_getattr_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700359#define NFS4_enc_pathconf_sz (compound_encode_hdr_maxsz + \
360 encode_putfh_maxsz + \
361 encode_getattr_maxsz)
362#define NFS4_dec_pathconf_sz (compound_decode_hdr_maxsz + \
363 decode_putfh_maxsz + \
364 decode_getattr_maxsz)
365#define NFS4_enc_statfs_sz (compound_encode_hdr_maxsz + \
366 encode_putfh_maxsz + \
367 encode_getattr_maxsz)
368#define NFS4_dec_statfs_sz (compound_decode_hdr_maxsz + \
369 decode_putfh_maxsz + \
370 op_decode_hdr_maxsz + 12)
371#define NFS4_enc_server_caps_sz (compound_encode_hdr_maxsz + \
372 encode_getattr_maxsz)
373#define NFS4_dec_server_caps_sz (compound_decode_hdr_maxsz + \
374 decode_getattr_maxsz)
375#define NFS4_enc_delegreturn_sz (compound_encode_hdr_maxsz + \
376 encode_putfh_maxsz + \
377 encode_delegreturn_maxsz)
378#define NFS4_dec_delegreturn_sz (compound_decode_hdr_maxsz + \
379 decode_delegreturn_maxsz)
J. Bruce Fields029d1052005-06-22 17:16:22 +0000380#define NFS4_enc_getacl_sz (compound_encode_hdr_maxsz + \
381 encode_putfh_maxsz + \
382 encode_getattr_maxsz)
383#define NFS4_dec_getacl_sz (compound_decode_hdr_maxsz + \
384 decode_putfh_maxsz + \
385 op_decode_hdr_maxsz + \
386 nfs4_fattr_bitmap_maxsz + 1)
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000387#define NFS4_enc_setacl_sz (compound_encode_hdr_maxsz + \
388 encode_putfh_maxsz + \
389 op_encode_hdr_maxsz + 4 + \
390 nfs4_fattr_bitmap_maxsz + 1)
391#define NFS4_dec_setacl_sz (compound_decode_hdr_maxsz + \
392 decode_putfh_maxsz + \
393 op_decode_hdr_maxsz + nfs4_fattr_bitmap_maxsz)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700394
395static struct {
396 unsigned int mode;
397 unsigned int nfs2type;
398} nfs_type2fmt[] = {
399 { 0, NFNON },
400 { S_IFREG, NFREG },
401 { S_IFDIR, NFDIR },
402 { S_IFBLK, NFBLK },
403 { S_IFCHR, NFCHR },
404 { S_IFLNK, NFLNK },
405 { S_IFSOCK, NFSOCK },
406 { S_IFIFO, NFFIFO },
407 { 0, NFNON },
408 { 0, NFNON },
409};
410
411struct compound_hdr {
412 int32_t status;
413 uint32_t nops;
414 uint32_t taglen;
415 char * tag;
416};
417
418/*
419 * START OF "GENERIC" ENCODE ROUTINES.
420 * These may look a little ugly since they are imported from a "generic"
421 * set of XDR encode/decode routines which are intended to be shared by
422 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
423 *
424 * If the pain of reading these is too great, it should be a straightforward
425 * task to translate them into Linux-specific versions which are more
426 * consistent with the style used in NFSv2/v3...
427 */
428#define WRITE32(n) *p++ = htonl(n)
429#define WRITE64(n) do { \
430 *p++ = htonl((uint32_t)((n) >> 32)); \
431 *p++ = htonl((uint32_t)(n)); \
432} while (0)
433#define WRITEMEM(ptr,nbytes) do { \
434 p = xdr_encode_opaque_fixed(p, ptr, nbytes); \
435} while (0)
436
437#define RESERVE_SPACE(nbytes) do { \
438 p = xdr_reserve_space(xdr, nbytes); \
439 if (!p) printk("RESERVE_SPACE(%d) failed in function %s\n", (int) (nbytes), __FUNCTION__); \
440 BUG_ON(!p); \
441} while (0)
442
443static void encode_string(struct xdr_stream *xdr, unsigned int len, const char *str)
444{
445 uint32_t *p;
446
447 p = xdr_reserve_space(xdr, 4 + len);
448 BUG_ON(p == NULL);
449 xdr_encode_opaque(p, str, len);
450}
451
452static int encode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
453{
454 uint32_t *p;
455
456 dprintk("encode_compound: tag=%.*s\n", (int)hdr->taglen, hdr->tag);
457 BUG_ON(hdr->taglen > NFS4_MAXTAGLEN);
458 RESERVE_SPACE(12+(XDR_QUADLEN(hdr->taglen)<<2));
459 WRITE32(hdr->taglen);
460 WRITEMEM(hdr->tag, hdr->taglen);
461 WRITE32(NFS4_MINOR_VERSION);
462 WRITE32(hdr->nops);
463 return 0;
464}
465
466static void encode_nfs4_verifier(struct xdr_stream *xdr, const nfs4_verifier *verf)
467{
468 uint32_t *p;
469
470 p = xdr_reserve_space(xdr, NFS4_VERIFIER_SIZE);
471 BUG_ON(p == NULL);
472 xdr_encode_opaque_fixed(p, verf->data, NFS4_VERIFIER_SIZE);
473}
474
475static int encode_attrs(struct xdr_stream *xdr, const struct iattr *iap, const struct nfs_server *server)
476{
477 char owner_name[IDMAP_NAMESZ];
478 char owner_group[IDMAP_NAMESZ];
479 int owner_namelen = 0;
480 int owner_grouplen = 0;
481 uint32_t *p;
482 uint32_t *q;
483 int len;
484 uint32_t bmval0 = 0;
485 uint32_t bmval1 = 0;
486 int status;
487
488 /*
489 * We reserve enough space to write the entire attribute buffer at once.
490 * In the worst-case, this would be
491 * 12(bitmap) + 4(attrlen) + 8(size) + 4(mode) + 4(atime) + 4(mtime)
492 * = 36 bytes, plus any contribution from variable-length fields
J. Bruce Fields23ec6962005-06-22 17:16:22 +0000493 * such as owner/group.
Linus Torvalds1da177e2005-04-16 15:20:36 -0700494 */
495 len = 16;
496
497 /* Sigh */
498 if (iap->ia_valid & ATTR_SIZE)
499 len += 8;
500 if (iap->ia_valid & ATTR_MODE)
501 len += 4;
502 if (iap->ia_valid & ATTR_UID) {
503 owner_namelen = nfs_map_uid_to_name(server->nfs4_state, iap->ia_uid, owner_name);
504 if (owner_namelen < 0) {
505 printk(KERN_WARNING "nfs: couldn't resolve uid %d to string\n",
506 iap->ia_uid);
507 /* XXX */
508 strcpy(owner_name, "nobody");
509 owner_namelen = sizeof("nobody") - 1;
510 /* goto out; */
511 }
512 len += 4 + (XDR_QUADLEN(owner_namelen) << 2);
513 }
514 if (iap->ia_valid & ATTR_GID) {
515 owner_grouplen = nfs_map_gid_to_group(server->nfs4_state, iap->ia_gid, owner_group);
516 if (owner_grouplen < 0) {
517 printk(KERN_WARNING "nfs4: couldn't resolve gid %d to string\n",
518 iap->ia_gid);
519 strcpy(owner_group, "nobody");
520 owner_grouplen = sizeof("nobody") - 1;
521 /* goto out; */
522 }
523 len += 4 + (XDR_QUADLEN(owner_grouplen) << 2);
524 }
525 if (iap->ia_valid & ATTR_ATIME_SET)
526 len += 16;
527 else if (iap->ia_valid & ATTR_ATIME)
528 len += 4;
529 if (iap->ia_valid & ATTR_MTIME_SET)
530 len += 16;
531 else if (iap->ia_valid & ATTR_MTIME)
532 len += 4;
533 RESERVE_SPACE(len);
534
535 /*
536 * We write the bitmap length now, but leave the bitmap and the attribute
537 * buffer length to be backfilled at the end of this routine.
538 */
539 WRITE32(2);
540 q = p;
541 p += 3;
542
543 if (iap->ia_valid & ATTR_SIZE) {
544 bmval0 |= FATTR4_WORD0_SIZE;
545 WRITE64(iap->ia_size);
546 }
547 if (iap->ia_valid & ATTR_MODE) {
548 bmval1 |= FATTR4_WORD1_MODE;
549 WRITE32(iap->ia_mode);
550 }
551 if (iap->ia_valid & ATTR_UID) {
552 bmval1 |= FATTR4_WORD1_OWNER;
553 WRITE32(owner_namelen);
554 WRITEMEM(owner_name, owner_namelen);
555 }
556 if (iap->ia_valid & ATTR_GID) {
557 bmval1 |= FATTR4_WORD1_OWNER_GROUP;
558 WRITE32(owner_grouplen);
559 WRITEMEM(owner_group, owner_grouplen);
560 }
561 if (iap->ia_valid & ATTR_ATIME_SET) {
562 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
563 WRITE32(NFS4_SET_TO_CLIENT_TIME);
564 WRITE32(0);
565 WRITE32(iap->ia_mtime.tv_sec);
566 WRITE32(iap->ia_mtime.tv_nsec);
567 }
568 else if (iap->ia_valid & ATTR_ATIME) {
569 bmval1 |= FATTR4_WORD1_TIME_ACCESS_SET;
570 WRITE32(NFS4_SET_TO_SERVER_TIME);
571 }
572 if (iap->ia_valid & ATTR_MTIME_SET) {
573 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
574 WRITE32(NFS4_SET_TO_CLIENT_TIME);
575 WRITE32(0);
576 WRITE32(iap->ia_mtime.tv_sec);
577 WRITE32(iap->ia_mtime.tv_nsec);
578 }
579 else if (iap->ia_valid & ATTR_MTIME) {
580 bmval1 |= FATTR4_WORD1_TIME_MODIFY_SET;
581 WRITE32(NFS4_SET_TO_SERVER_TIME);
582 }
583
584 /*
585 * Now we backfill the bitmap and the attribute buffer length.
586 */
587 if (len != ((char *)p - (char *)q) + 4) {
588 printk ("encode_attr: Attr length calculation error! %u != %Zu\n",
589 len, ((char *)p - (char *)q) + 4);
590 BUG();
591 }
592 len = (char *)p - (char *)q - 12;
593 *q++ = htonl(bmval0);
594 *q++ = htonl(bmval1);
595 *q++ = htonl(len);
596
597 status = 0;
598/* out: */
599 return status;
600}
601
602static int encode_access(struct xdr_stream *xdr, u32 access)
603{
604 uint32_t *p;
605
606 RESERVE_SPACE(8);
607 WRITE32(OP_ACCESS);
608 WRITE32(access);
609
610 return 0;
611}
612
613static int encode_close(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
614{
615 uint32_t *p;
616
Trond Myklebust95121352005-10-18 14:20:12 -0700617 RESERVE_SPACE(8+sizeof(arg->stateid->data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700618 WRITE32(OP_CLOSE);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700619 WRITE32(arg->seqid->sequence->counter);
Trond Myklebust95121352005-10-18 14:20:12 -0700620 WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700621
622 return 0;
623}
624
625static int encode_commit(struct xdr_stream *xdr, const struct nfs_writeargs *args)
626{
627 uint32_t *p;
628
629 RESERVE_SPACE(16);
630 WRITE32(OP_COMMIT);
631 WRITE64(args->offset);
632 WRITE32(args->count);
633
634 return 0;
635}
636
637static int encode_create(struct xdr_stream *xdr, const struct nfs4_create_arg *create)
638{
639 uint32_t *p;
640
641 RESERVE_SPACE(8);
642 WRITE32(OP_CREATE);
643 WRITE32(create->ftype);
644
645 switch (create->ftype) {
646 case NF4LNK:
647 RESERVE_SPACE(4 + create->u.symlink->len);
648 WRITE32(create->u.symlink->len);
649 WRITEMEM(create->u.symlink->name, create->u.symlink->len);
650 break;
651
652 case NF4BLK: case NF4CHR:
653 RESERVE_SPACE(8);
654 WRITE32(create->u.device.specdata1);
655 WRITE32(create->u.device.specdata2);
656 break;
657
658 default:
659 break;
660 }
661
662 RESERVE_SPACE(4 + create->name->len);
663 WRITE32(create->name->len);
664 WRITEMEM(create->name->name, create->name->len);
665
666 return encode_attrs(xdr, create->attrs, create->server);
667}
668
669static int encode_getattr_one(struct xdr_stream *xdr, uint32_t bitmap)
670{
671 uint32_t *p;
672
673 RESERVE_SPACE(12);
674 WRITE32(OP_GETATTR);
675 WRITE32(1);
676 WRITE32(bitmap);
677 return 0;
678}
679
680static int encode_getattr_two(struct xdr_stream *xdr, uint32_t bm0, uint32_t bm1)
681{
682 uint32_t *p;
683
684 RESERVE_SPACE(16);
685 WRITE32(OP_GETATTR);
686 WRITE32(2);
687 WRITE32(bm0);
688 WRITE32(bm1);
689 return 0;
690}
691
692static int encode_getfattr(struct xdr_stream *xdr, const u32* bitmask)
693{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700694 return encode_getattr_two(xdr,
695 bitmask[0] & nfs4_fattr_bitmap[0],
696 bitmask[1] & nfs4_fattr_bitmap[1]);
697}
698
699static int encode_fsinfo(struct xdr_stream *xdr, const u32* bitmask)
700{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700701 return encode_getattr_two(xdr, bitmask[0] & nfs4_fsinfo_bitmap[0],
702 bitmask[1] & nfs4_fsinfo_bitmap[1]);
703}
704
705static int encode_getfh(struct xdr_stream *xdr)
706{
707 uint32_t *p;
708
709 RESERVE_SPACE(4);
710 WRITE32(OP_GETFH);
711
712 return 0;
713}
714
715static int encode_link(struct xdr_stream *xdr, const struct qstr *name)
716{
717 uint32_t *p;
718
719 RESERVE_SPACE(8 + name->len);
720 WRITE32(OP_LINK);
721 WRITE32(name->len);
722 WRITEMEM(name->name, name->len);
723
724 return 0;
725}
726
727/*
728 * opcode,type,reclaim,offset,length,new_lock_owner = 32
729 * open_seqid,open_stateid,lock_seqid,lock_owner.clientid, lock_owner.id = 40
730 */
731static int encode_lock(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
732{
733 uint32_t *p;
734 struct nfs_lock_opargs *opargs = arg->u.lock;
735
736 RESERVE_SPACE(32);
737 WRITE32(OP_LOCK);
738 WRITE32(arg->type);
739 WRITE32(opargs->reclaim);
740 WRITE64(arg->offset);
741 WRITE64(arg->length);
742 WRITE32(opargs->new_lock_owner);
743 if (opargs->new_lock_owner){
Linus Torvalds1da177e2005-04-16 15:20:36 -0700744 RESERVE_SPACE(40);
Trond Myklebust06735b32005-10-18 14:20:15 -0700745 WRITE32(opargs->open_seqid->sequence->counter);
746 WRITEMEM(opargs->open_stateid->data, sizeof(opargs->open_stateid->data));
747 WRITE32(opargs->lock_seqid->sequence->counter);
748 WRITE64(opargs->lock_owner.clientid);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700749 WRITE32(4);
Trond Myklebust06735b32005-10-18 14:20:15 -0700750 WRITE32(opargs->lock_owner.id);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700751 }
752 else {
Linus Torvalds1da177e2005-04-16 15:20:36 -0700753 RESERVE_SPACE(20);
Trond Myklebust06735b32005-10-18 14:20:15 -0700754 WRITEMEM(opargs->lock_stateid->data, sizeof(opargs->lock_stateid->data));
755 WRITE32(opargs->lock_seqid->sequence->counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700756 }
757
758 return 0;
759}
760
761static int encode_lockt(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
762{
763 uint32_t *p;
764 struct nfs_lowner *opargs = arg->u.lockt;
765
766 RESERVE_SPACE(40);
767 WRITE32(OP_LOCKT);
768 WRITE32(arg->type);
769 WRITE64(arg->offset);
770 WRITE64(arg->length);
771 WRITE64(opargs->clientid);
772 WRITE32(4);
773 WRITE32(opargs->id);
774
775 return 0;
776}
777
778static int encode_locku(struct xdr_stream *xdr, const struct nfs_lockargs *arg)
779{
780 uint32_t *p;
781 struct nfs_locku_opargs *opargs = arg->u.locku;
782
783 RESERVE_SPACE(44);
784 WRITE32(OP_LOCKU);
785 WRITE32(arg->type);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700786 WRITE32(opargs->seqid->sequence->counter);
Trond Myklebustfaf5f492005-10-18 14:20:15 -0700787 WRITEMEM(opargs->stateid->data, sizeof(opargs->stateid->data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700788 WRITE64(arg->offset);
789 WRITE64(arg->length);
790
791 return 0;
792}
793
794static int encode_lookup(struct xdr_stream *xdr, const struct qstr *name)
795{
796 int len = name->len;
797 uint32_t *p;
798
799 RESERVE_SPACE(8 + len);
800 WRITE32(OP_LOOKUP);
801 WRITE32(len);
802 WRITEMEM(name->name, len);
803
804 return 0;
805}
806
807static void encode_share_access(struct xdr_stream *xdr, int open_flags)
808{
809 uint32_t *p;
810
811 RESERVE_SPACE(8);
812 switch (open_flags & (FMODE_READ|FMODE_WRITE)) {
813 case FMODE_READ:
814 WRITE32(NFS4_SHARE_ACCESS_READ);
815 break;
816 case FMODE_WRITE:
817 WRITE32(NFS4_SHARE_ACCESS_WRITE);
818 break;
819 case FMODE_READ|FMODE_WRITE:
820 WRITE32(NFS4_SHARE_ACCESS_BOTH);
821 break;
822 default:
823 BUG();
824 }
825 WRITE32(0); /* for linux, share_deny = 0 always */
826}
827
828static inline void encode_openhdr(struct xdr_stream *xdr, const struct nfs_openargs *arg)
829{
830 uint32_t *p;
831 /*
832 * opcode 4, seqid 4, share_access 4, share_deny 4, clientid 8, ownerlen 4,
833 * owner 4 = 32
834 */
835 RESERVE_SPACE(8);
836 WRITE32(OP_OPEN);
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700837 WRITE32(arg->seqid->sequence->counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700838 encode_share_access(xdr, arg->open_flags);
839 RESERVE_SPACE(16);
840 WRITE64(arg->clientid);
841 WRITE32(4);
842 WRITE32(arg->id);
843}
844
845static inline void encode_createmode(struct xdr_stream *xdr, const struct nfs_openargs *arg)
846{
847 uint32_t *p;
848
849 RESERVE_SPACE(4);
850 switch(arg->open_flags & O_EXCL) {
851 case 0:
852 WRITE32(NFS4_CREATE_UNCHECKED);
853 encode_attrs(xdr, arg->u.attrs, arg->server);
854 break;
855 default:
856 WRITE32(NFS4_CREATE_EXCLUSIVE);
857 encode_nfs4_verifier(xdr, &arg->u.verifier);
858 }
859}
860
861static void encode_opentype(struct xdr_stream *xdr, const struct nfs_openargs *arg)
862{
863 uint32_t *p;
864
865 RESERVE_SPACE(4);
866 switch (arg->open_flags & O_CREAT) {
867 case 0:
868 WRITE32(NFS4_OPEN_NOCREATE);
869 break;
870 default:
871 BUG_ON(arg->claim != NFS4_OPEN_CLAIM_NULL);
872 WRITE32(NFS4_OPEN_CREATE);
873 encode_createmode(xdr, arg);
874 }
875}
876
877static inline void encode_delegation_type(struct xdr_stream *xdr, int delegation_type)
878{
879 uint32_t *p;
880
881 RESERVE_SPACE(4);
882 switch (delegation_type) {
883 case 0:
884 WRITE32(NFS4_OPEN_DELEGATE_NONE);
885 break;
886 case FMODE_READ:
887 WRITE32(NFS4_OPEN_DELEGATE_READ);
888 break;
889 case FMODE_WRITE|FMODE_READ:
890 WRITE32(NFS4_OPEN_DELEGATE_WRITE);
891 break;
892 default:
893 BUG();
894 }
895}
896
897static inline void encode_claim_null(struct xdr_stream *xdr, const struct qstr *name)
898{
899 uint32_t *p;
900
901 RESERVE_SPACE(4);
902 WRITE32(NFS4_OPEN_CLAIM_NULL);
903 encode_string(xdr, name->len, name->name);
904}
905
906static inline void encode_claim_previous(struct xdr_stream *xdr, int type)
907{
908 uint32_t *p;
909
910 RESERVE_SPACE(4);
911 WRITE32(NFS4_OPEN_CLAIM_PREVIOUS);
912 encode_delegation_type(xdr, type);
913}
914
915static inline void encode_claim_delegate_cur(struct xdr_stream *xdr, const struct qstr *name, const nfs4_stateid *stateid)
916{
917 uint32_t *p;
918
919 RESERVE_SPACE(4+sizeof(stateid->data));
920 WRITE32(NFS4_OPEN_CLAIM_DELEGATE_CUR);
921 WRITEMEM(stateid->data, sizeof(stateid->data));
922 encode_string(xdr, name->len, name->name);
923}
924
925static int encode_open(struct xdr_stream *xdr, const struct nfs_openargs *arg)
926{
927 encode_openhdr(xdr, arg);
928 encode_opentype(xdr, arg);
929 switch (arg->claim) {
930 case NFS4_OPEN_CLAIM_NULL:
931 encode_claim_null(xdr, arg->name);
932 break;
933 case NFS4_OPEN_CLAIM_PREVIOUS:
934 encode_claim_previous(xdr, arg->u.delegation_type);
935 break;
936 case NFS4_OPEN_CLAIM_DELEGATE_CUR:
937 encode_claim_delegate_cur(xdr, arg->name, &arg->u.delegation);
938 break;
939 default:
940 BUG();
941 }
942 return 0;
943}
944
945static int encode_open_confirm(struct xdr_stream *xdr, const struct nfs_open_confirmargs *arg)
946{
947 uint32_t *p;
948
949 RESERVE_SPACE(8+sizeof(arg->stateid.data));
950 WRITE32(OP_OPEN_CONFIRM);
951 WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700952 WRITE32(arg->seqid->sequence->counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700953
954 return 0;
955}
956
957static int encode_open_downgrade(struct xdr_stream *xdr, const struct nfs_closeargs *arg)
958{
959 uint32_t *p;
960
Trond Myklebust95121352005-10-18 14:20:12 -0700961 RESERVE_SPACE(8+sizeof(arg->stateid->data));
Linus Torvalds1da177e2005-04-16 15:20:36 -0700962 WRITE32(OP_OPEN_DOWNGRADE);
Trond Myklebust95121352005-10-18 14:20:12 -0700963 WRITEMEM(arg->stateid->data, sizeof(arg->stateid->data));
Trond Myklebustcee54fc2005-10-18 14:20:12 -0700964 WRITE32(arg->seqid->sequence->counter);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700965 encode_share_access(xdr, arg->open_flags);
966 return 0;
967}
968
969static int
970encode_putfh(struct xdr_stream *xdr, const struct nfs_fh *fh)
971{
972 int len = fh->size;
973 uint32_t *p;
974
975 RESERVE_SPACE(8 + len);
976 WRITE32(OP_PUTFH);
977 WRITE32(len);
978 WRITEMEM(fh->data, len);
979
980 return 0;
981}
982
983static int encode_putrootfh(struct xdr_stream *xdr)
984{
985 uint32_t *p;
986
987 RESERVE_SPACE(4);
988 WRITE32(OP_PUTROOTFH);
989
990 return 0;
991}
992
993static void encode_stateid(struct xdr_stream *xdr, const struct nfs_open_context *ctx)
994{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700995 nfs4_stateid stateid;
996 uint32_t *p;
997
998 RESERVE_SPACE(16);
999 if (ctx->state != NULL) {
1000 nfs4_copy_stateid(&stateid, ctx->state, ctx->lockowner);
1001 WRITEMEM(stateid.data, sizeof(stateid.data));
1002 } else
1003 WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
1004}
1005
1006static int encode_read(struct xdr_stream *xdr, const struct nfs_readargs *args)
1007{
1008 uint32_t *p;
1009
1010 RESERVE_SPACE(4);
1011 WRITE32(OP_READ);
1012
1013 encode_stateid(xdr, args->context);
1014
1015 RESERVE_SPACE(12);
1016 WRITE64(args->offset);
1017 WRITE32(args->count);
1018
1019 return 0;
1020}
1021
1022static int encode_readdir(struct xdr_stream *xdr, const struct nfs4_readdir_arg *readdir, struct rpc_rqst *req)
1023{
1024 struct rpc_auth *auth = req->rq_task->tk_auth;
Manoj Naik97d312d2005-06-22 17:16:39 +00001025 uint32_t attrs[2] = {
1026 FATTR4_WORD0_RDATTR_ERROR|FATTR4_WORD0_FILEID,
1027 FATTR4_WORD1_MOUNTED_ON_FILEID,
1028 };
Linus Torvalds1da177e2005-04-16 15:20:36 -07001029 int replen;
1030 uint32_t *p;
1031
1032 RESERVE_SPACE(32+sizeof(nfs4_verifier));
1033 WRITE32(OP_READDIR);
1034 WRITE64(readdir->cookie);
1035 WRITEMEM(readdir->verifier.data, sizeof(readdir->verifier.data));
1036 WRITE32(readdir->count >> 1); /* We're not doing readdirplus */
1037 WRITE32(readdir->count);
1038 WRITE32(2);
Manoj Naik97d312d2005-06-22 17:16:39 +00001039 /* Switch to mounted_on_fileid if the server supports it */
1040 if (readdir->bitmask[1] & FATTR4_WORD1_MOUNTED_ON_FILEID)
1041 attrs[0] &= ~FATTR4_WORD0_FILEID;
1042 else
1043 attrs[1] &= ~FATTR4_WORD1_MOUNTED_ON_FILEID;
1044 WRITE32(attrs[0] & readdir->bitmask[0]);
1045 WRITE32(attrs[1] & readdir->bitmask[1]);
Trond Myklebusteadf4592005-06-22 17:16:39 +00001046 dprintk("%s: cookie = %Lu, verifier = 0x%x%x, bitmap = 0x%x%x\n",
1047 __FUNCTION__,
1048 (unsigned long long)readdir->cookie,
1049 ((u32 *)readdir->verifier.data)[0],
1050 ((u32 *)readdir->verifier.data)[1],
1051 attrs[0] & readdir->bitmask[0],
1052 attrs[1] & readdir->bitmask[1]);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001053
1054 /* set up reply kvec
1055 * toplevel_status + taglen + rescount + OP_PUTFH + status
1056 * + OP_READDIR + status + verifer(2) = 9
1057 */
1058 replen = (RPC_REPHDRSIZE + auth->au_rslack + 9) << 2;
1059 xdr_inline_pages(&req->rq_rcv_buf, replen, readdir->pages,
1060 readdir->pgbase, readdir->count);
Trond Myklebusteadf4592005-06-22 17:16:39 +00001061 dprintk("%s: inlined page args = (%u, %p, %u, %u)\n",
1062 __FUNCTION__, replen, readdir->pages,
1063 readdir->pgbase, readdir->count);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001064
1065 return 0;
1066}
1067
1068static int encode_readlink(struct xdr_stream *xdr, const struct nfs4_readlink *readlink, struct rpc_rqst *req)
1069{
1070 struct rpc_auth *auth = req->rq_task->tk_auth;
1071 unsigned int replen;
1072 uint32_t *p;
1073
1074 RESERVE_SPACE(4);
1075 WRITE32(OP_READLINK);
1076
1077 /* set up reply kvec
1078 * toplevel_status + taglen + rescount + OP_PUTFH + status
1079 * + OP_READLINK + status + string length = 8
1080 */
1081 replen = (RPC_REPHDRSIZE + auth->au_rslack + 8) << 2;
1082 xdr_inline_pages(&req->rq_rcv_buf, replen, readlink->pages,
1083 readlink->pgbase, readlink->pglen);
1084
1085 return 0;
1086}
1087
1088static int encode_remove(struct xdr_stream *xdr, const struct qstr *name)
1089{
1090 uint32_t *p;
1091
1092 RESERVE_SPACE(8 + name->len);
1093 WRITE32(OP_REMOVE);
1094 WRITE32(name->len);
1095 WRITEMEM(name->name, name->len);
1096
1097 return 0;
1098}
1099
1100static int encode_rename(struct xdr_stream *xdr, const struct qstr *oldname, const struct qstr *newname)
1101{
1102 uint32_t *p;
1103
1104 RESERVE_SPACE(8 + oldname->len);
1105 WRITE32(OP_RENAME);
1106 WRITE32(oldname->len);
1107 WRITEMEM(oldname->name, oldname->len);
1108
1109 RESERVE_SPACE(4 + newname->len);
1110 WRITE32(newname->len);
1111 WRITEMEM(newname->name, newname->len);
1112
1113 return 0;
1114}
1115
1116static int encode_renew(struct xdr_stream *xdr, const struct nfs4_client *client_stateid)
1117{
1118 uint32_t *p;
1119
1120 RESERVE_SPACE(12);
1121 WRITE32(OP_RENEW);
1122 WRITE64(client_stateid->cl_clientid);
1123
1124 return 0;
1125}
1126
1127static int
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001128encode_restorefh(struct xdr_stream *xdr)
1129{
1130 uint32_t *p;
1131
1132 RESERVE_SPACE(4);
1133 WRITE32(OP_RESTOREFH);
1134
1135 return 0;
1136}
1137
1138static int
J. Bruce Fields23ec6962005-06-22 17:16:22 +00001139encode_setacl(struct xdr_stream *xdr, struct nfs_setaclargs *arg)
1140{
1141 uint32_t *p;
1142
1143 RESERVE_SPACE(4+sizeof(zero_stateid.data));
1144 WRITE32(OP_SETATTR);
1145 WRITEMEM(zero_stateid.data, sizeof(zero_stateid.data));
1146 RESERVE_SPACE(2*4);
1147 WRITE32(1);
1148 WRITE32(FATTR4_WORD0_ACL);
1149 if (arg->acl_len % 4)
1150 return -EINVAL;
1151 RESERVE_SPACE(4);
1152 WRITE32(arg->acl_len);
1153 xdr_write_pages(xdr, arg->acl_pages, arg->acl_pgbase, arg->acl_len);
1154 return 0;
1155}
1156
1157static int
Linus Torvalds1da177e2005-04-16 15:20:36 -07001158encode_savefh(struct xdr_stream *xdr)
1159{
1160 uint32_t *p;
1161
1162 RESERVE_SPACE(4);
1163 WRITE32(OP_SAVEFH);
1164
1165 return 0;
1166}
1167
1168static int encode_setattr(struct xdr_stream *xdr, const struct nfs_setattrargs *arg, const struct nfs_server *server)
1169{
1170 int status;
1171 uint32_t *p;
1172
1173 RESERVE_SPACE(4+sizeof(arg->stateid.data));
1174 WRITE32(OP_SETATTR);
1175 WRITEMEM(arg->stateid.data, sizeof(arg->stateid.data));
1176
1177 if ((status = encode_attrs(xdr, arg->iap, server)))
1178 return status;
1179
1180 return 0;
1181}
1182
1183static int encode_setclientid(struct xdr_stream *xdr, const struct nfs4_setclientid *setclientid)
1184{
1185 uint32_t *p;
1186
1187 RESERVE_SPACE(4 + sizeof(setclientid->sc_verifier->data));
1188 WRITE32(OP_SETCLIENTID);
1189 WRITEMEM(setclientid->sc_verifier->data, sizeof(setclientid->sc_verifier->data));
1190
1191 encode_string(xdr, setclientid->sc_name_len, setclientid->sc_name);
1192 RESERVE_SPACE(4);
1193 WRITE32(setclientid->sc_prog);
1194 encode_string(xdr, setclientid->sc_netid_len, setclientid->sc_netid);
1195 encode_string(xdr, setclientid->sc_uaddr_len, setclientid->sc_uaddr);
1196 RESERVE_SPACE(4);
1197 WRITE32(setclientid->sc_cb_ident);
1198
1199 return 0;
1200}
1201
1202static int encode_setclientid_confirm(struct xdr_stream *xdr, const struct nfs4_client *client_state)
1203{
1204 uint32_t *p;
1205
1206 RESERVE_SPACE(12 + sizeof(client_state->cl_confirm.data));
1207 WRITE32(OP_SETCLIENTID_CONFIRM);
1208 WRITE64(client_state->cl_clientid);
1209 WRITEMEM(client_state->cl_confirm.data, sizeof(client_state->cl_confirm.data));
1210
1211 return 0;
1212}
1213
1214static int encode_write(struct xdr_stream *xdr, const struct nfs_writeargs *args)
1215{
1216 uint32_t *p;
1217
1218 RESERVE_SPACE(4);
1219 WRITE32(OP_WRITE);
1220
1221 encode_stateid(xdr, args->context);
1222
1223 RESERVE_SPACE(16);
1224 WRITE64(args->offset);
1225 WRITE32(args->stable);
1226 WRITE32(args->count);
1227
1228 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1229
1230 return 0;
1231}
1232
1233static int encode_delegreturn(struct xdr_stream *xdr, const nfs4_stateid *stateid)
1234{
1235 uint32_t *p;
1236
1237 RESERVE_SPACE(20);
1238
1239 WRITE32(OP_DELEGRETURN);
1240 WRITEMEM(stateid->data, sizeof(stateid->data));
1241 return 0;
1242
1243}
1244/*
1245 * END OF "GENERIC" ENCODE ROUTINES.
1246 */
1247
1248/*
1249 * Encode an ACCESS request
1250 */
1251static int nfs4_xdr_enc_access(struct rpc_rqst *req, uint32_t *p, const struct nfs4_accessargs *args)
1252{
1253 struct xdr_stream xdr;
1254 struct compound_hdr hdr = {
1255 .nops = 2,
1256 };
1257 int status;
1258
1259 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1260 encode_compound_hdr(&xdr, &hdr);
1261 if ((status = encode_putfh(&xdr, args->fh)) == 0)
1262 status = encode_access(&xdr, args->access);
1263 return status;
1264}
1265
1266/*
1267 * Encode LOOKUP request
1268 */
1269static int nfs4_xdr_enc_lookup(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_arg *args)
1270{
1271 struct xdr_stream xdr;
1272 struct compound_hdr hdr = {
1273 .nops = 4,
1274 };
1275 int status;
1276
1277 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1278 encode_compound_hdr(&xdr, &hdr);
1279 if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
1280 goto out;
1281 if ((status = encode_lookup(&xdr, args->name)) != 0)
1282 goto out;
1283 if ((status = encode_getfh(&xdr)) != 0)
1284 goto out;
1285 status = encode_getfattr(&xdr, args->bitmask);
1286out:
1287 return status;
1288}
1289
1290/*
1291 * Encode LOOKUP_ROOT request
1292 */
1293static int nfs4_xdr_enc_lookup_root(struct rpc_rqst *req, uint32_t *p, const struct nfs4_lookup_root_arg *args)
1294{
1295 struct xdr_stream xdr;
1296 struct compound_hdr hdr = {
1297 .nops = 3,
1298 };
1299 int status;
1300
1301 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1302 encode_compound_hdr(&xdr, &hdr);
1303 if ((status = encode_putrootfh(&xdr)) != 0)
1304 goto out;
1305 if ((status = encode_getfh(&xdr)) == 0)
1306 status = encode_getfattr(&xdr, args->bitmask);
1307out:
1308 return status;
1309}
1310
1311/*
1312 * Encode REMOVE request
1313 */
1314static int nfs4_xdr_enc_remove(struct rpc_rqst *req, uint32_t *p, const struct nfs4_remove_arg *args)
1315{
1316 struct xdr_stream xdr;
1317 struct compound_hdr hdr = {
1318 .nops = 2,
1319 };
1320 int status;
1321
1322 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1323 encode_compound_hdr(&xdr, &hdr);
1324 if ((status = encode_putfh(&xdr, args->fh)) == 0)
1325 status = encode_remove(&xdr, args->name);
1326 return status;
1327}
1328
1329/*
1330 * Encode RENAME request
1331 */
1332static int nfs4_xdr_enc_rename(struct rpc_rqst *req, uint32_t *p, const struct nfs4_rename_arg *args)
1333{
1334 struct xdr_stream xdr;
1335 struct compound_hdr hdr = {
1336 .nops = 4,
1337 };
1338 int status;
1339
1340 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1341 encode_compound_hdr(&xdr, &hdr);
1342 if ((status = encode_putfh(&xdr, args->old_dir)) != 0)
1343 goto out;
1344 if ((status = encode_savefh(&xdr)) != 0)
1345 goto out;
1346 if ((status = encode_putfh(&xdr, args->new_dir)) != 0)
1347 goto out;
1348 status = encode_rename(&xdr, args->old_name, args->new_name);
1349out:
1350 return status;
1351}
1352
1353/*
1354 * Encode LINK request
1355 */
1356static int nfs4_xdr_enc_link(struct rpc_rqst *req, uint32_t *p, const struct nfs4_link_arg *args)
1357{
1358 struct xdr_stream xdr;
1359 struct compound_hdr hdr = {
1360 .nops = 4,
1361 };
1362 int status;
1363
1364 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1365 encode_compound_hdr(&xdr, &hdr);
1366 if ((status = encode_putfh(&xdr, args->fh)) != 0)
1367 goto out;
1368 if ((status = encode_savefh(&xdr)) != 0)
1369 goto out;
1370 if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
1371 goto out;
1372 status = encode_link(&xdr, args->name);
1373out:
1374 return status;
1375}
1376
1377/*
1378 * Encode CREATE request
1379 */
1380static int nfs4_xdr_enc_create(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
1381{
1382 struct xdr_stream xdr;
1383 struct compound_hdr hdr = {
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001384 .nops = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001385 };
1386 int status;
1387
1388 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1389 encode_compound_hdr(&xdr, &hdr);
1390 if ((status = encode_putfh(&xdr, args->dir_fh)) != 0)
1391 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001392 if ((status = encode_savefh(&xdr)) != 0)
1393 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001394 if ((status = encode_create(&xdr, args)) != 0)
1395 goto out;
1396 if ((status = encode_getfh(&xdr)) != 0)
1397 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001398 if ((status = encode_getfattr(&xdr, args->bitmask)) != 0)
1399 goto out;
1400 if ((status = encode_restorefh(&xdr)) != 0)
1401 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001402 status = encode_getfattr(&xdr, args->bitmask);
1403out:
1404 return status;
1405}
1406
1407/*
1408 * Encode SYMLINK request
1409 */
1410static int nfs4_xdr_enc_symlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_create_arg *args)
1411{
1412 return nfs4_xdr_enc_create(req, p, args);
1413}
1414
1415/*
1416 * Encode GETATTR request
1417 */
1418static int nfs4_xdr_enc_getattr(struct rpc_rqst *req, uint32_t *p, const struct nfs4_getattr_arg *args)
1419{
1420 struct xdr_stream xdr;
1421 struct compound_hdr hdr = {
1422 .nops = 2,
1423 };
1424 int status;
1425
1426 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1427 encode_compound_hdr(&xdr, &hdr);
1428 if ((status = encode_putfh(&xdr, args->fh)) == 0)
1429 status = encode_getfattr(&xdr, args->bitmask);
1430 return status;
1431}
1432
1433/*
1434 * Encode a CLOSE request
1435 */
1436static int nfs4_xdr_enc_close(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args)
1437{
1438 struct xdr_stream xdr;
1439 struct compound_hdr hdr = {
Trond Myklebust516a6af2005-10-27 22:12:41 -04001440 .nops = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001441 };
1442 int status;
1443
1444 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1445 encode_compound_hdr(&xdr, &hdr);
1446 status = encode_putfh(&xdr, args->fh);
1447 if(status)
1448 goto out;
1449 status = encode_close(&xdr, args);
Trond Myklebust516a6af2005-10-27 22:12:41 -04001450 if (status != 0)
1451 goto out;
1452 status = encode_getfattr(&xdr, args->bitmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001453out:
1454 return status;
1455}
1456
1457/*
1458 * Encode an OPEN request
1459 */
1460static int nfs4_xdr_enc_open(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
1461{
1462 struct xdr_stream xdr;
1463 struct compound_hdr hdr = {
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001464 .nops = 7,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001465 };
1466 int status;
1467
Trond Myklebustcee54fc2005-10-18 14:20:12 -07001468 status = nfs_wait_on_sequence(args->seqid, req->rq_task);
1469 if (status != 0)
1470 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001471 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1472 encode_compound_hdr(&xdr, &hdr);
1473 status = encode_putfh(&xdr, args->fh);
1474 if (status)
1475 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001476 status = encode_savefh(&xdr);
1477 if (status)
1478 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001479 status = encode_open(&xdr, args);
1480 if (status)
1481 goto out;
1482 status = encode_getfh(&xdr);
1483 if (status)
1484 goto out;
1485 status = encode_getfattr(&xdr, args->bitmask);
Trond Myklebust56ae19f2005-10-27 22:12:40 -04001486 if (status)
1487 goto out;
1488 status = encode_restorefh(&xdr);
1489 if (status)
1490 goto out;
1491 status = encode_getfattr(&xdr, args->bitmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001492out:
1493 return status;
1494}
1495
1496/*
1497 * Encode an OPEN_CONFIRM request
1498 */
1499static int nfs4_xdr_enc_open_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_open_confirmargs *args)
1500{
1501 struct xdr_stream xdr;
1502 struct compound_hdr hdr = {
1503 .nops = 2,
1504 };
1505 int status;
1506
Trond Myklebustcee54fc2005-10-18 14:20:12 -07001507 status = nfs_wait_on_sequence(args->seqid, req->rq_task);
1508 if (status != 0)
1509 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001510 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1511 encode_compound_hdr(&xdr, &hdr);
1512 status = encode_putfh(&xdr, args->fh);
1513 if(status)
1514 goto out;
1515 status = encode_open_confirm(&xdr, args);
1516out:
1517 return status;
1518}
1519
1520/*
1521 * Encode an OPEN request with no attributes.
1522 */
1523static int nfs4_xdr_enc_open_noattr(struct rpc_rqst *req, uint32_t *p, struct nfs_openargs *args)
1524{
1525 struct xdr_stream xdr;
1526 struct compound_hdr hdr = {
1527 .nops = 2,
1528 };
1529 int status;
1530
Trond Myklebustcee54fc2005-10-18 14:20:12 -07001531 status = nfs_wait_on_sequence(args->seqid, req->rq_task);
1532 if (status != 0)
1533 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001534 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1535 encode_compound_hdr(&xdr, &hdr);
1536 status = encode_putfh(&xdr, args->fh);
1537 if (status)
1538 goto out;
1539 status = encode_open(&xdr, args);
1540out:
1541 return status;
1542}
1543
1544/*
1545 * Encode an OPEN_DOWNGRADE request
1546 */
1547static int nfs4_xdr_enc_open_downgrade(struct rpc_rqst *req, uint32_t *p, struct nfs_closeargs *args)
1548{
1549 struct xdr_stream xdr;
1550 struct compound_hdr hdr = {
Trond Myklebust516a6af2005-10-27 22:12:41 -04001551 .nops = 3,
Linus Torvalds1da177e2005-04-16 15:20:36 -07001552 };
1553 int status;
1554
1555 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1556 encode_compound_hdr(&xdr, &hdr);
1557 status = encode_putfh(&xdr, args->fh);
1558 if (status)
1559 goto out;
1560 status = encode_open_downgrade(&xdr, args);
Trond Myklebust516a6af2005-10-27 22:12:41 -04001561 if (status != 0)
1562 goto out;
1563 status = encode_getfattr(&xdr, args->bitmask);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001564out:
1565 return status;
1566}
1567
1568/*
1569 * Encode a LOCK request
1570 */
1571static int nfs4_xdr_enc_lock(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
1572{
1573 struct xdr_stream xdr;
1574 struct compound_hdr hdr = {
1575 .nops = 2,
1576 };
Trond Myklebustcee54fc2005-10-18 14:20:12 -07001577 struct nfs_lock_opargs *opargs = args->u.lock;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001578 int status;
1579
Trond Myklebust06735b32005-10-18 14:20:15 -07001580 status = nfs_wait_on_sequence(opargs->lock_seqid, req->rq_task);
Trond Myklebustcee54fc2005-10-18 14:20:12 -07001581 if (status != 0)
1582 goto out;
Trond Myklebust06735b32005-10-18 14:20:15 -07001583 /* Do we need to do an open_to_lock_owner? */
1584 if (opargs->lock_seqid->sequence->flags & NFS_SEQID_CONFIRMED)
1585 opargs->new_lock_owner = 0;
Linus Torvalds1da177e2005-04-16 15:20:36 -07001586 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1587 encode_compound_hdr(&xdr, &hdr);
1588 status = encode_putfh(&xdr, args->fh);
1589 if(status)
1590 goto out;
1591 status = encode_lock(&xdr, args);
1592out:
1593 return status;
1594}
1595
1596/*
1597 * Encode a LOCKT request
1598 */
1599static int nfs4_xdr_enc_lockt(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
1600{
1601 struct xdr_stream xdr;
1602 struct compound_hdr hdr = {
1603 .nops = 2,
1604 };
1605 int status;
1606
1607 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1608 encode_compound_hdr(&xdr, &hdr);
1609 status = encode_putfh(&xdr, args->fh);
1610 if(status)
1611 goto out;
1612 status = encode_lockt(&xdr, args);
1613out:
1614 return status;
1615}
1616
1617/*
1618 * Encode a LOCKU request
1619 */
1620static int nfs4_xdr_enc_locku(struct rpc_rqst *req, uint32_t *p, struct nfs_lockargs *args)
1621{
1622 struct xdr_stream xdr;
1623 struct compound_hdr hdr = {
1624 .nops = 2,
1625 };
1626 int status;
1627
1628 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1629 encode_compound_hdr(&xdr, &hdr);
1630 status = encode_putfh(&xdr, args->fh);
1631 if(status)
1632 goto out;
1633 status = encode_locku(&xdr, args);
1634out:
1635 return status;
1636}
1637
1638/*
1639 * Encode a READLINK request
1640 */
1641static int nfs4_xdr_enc_readlink(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readlink *args)
1642{
1643 struct xdr_stream xdr;
1644 struct compound_hdr hdr = {
1645 .nops = 2,
1646 };
1647 int status;
1648
1649 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1650 encode_compound_hdr(&xdr, &hdr);
1651 status = encode_putfh(&xdr, args->fh);
1652 if(status)
1653 goto out;
1654 status = encode_readlink(&xdr, args, req);
1655out:
1656 return status;
1657}
1658
1659/*
1660 * Encode a READDIR request
1661 */
1662static int nfs4_xdr_enc_readdir(struct rpc_rqst *req, uint32_t *p, const struct nfs4_readdir_arg *args)
1663{
1664 struct xdr_stream xdr;
1665 struct compound_hdr hdr = {
1666 .nops = 2,
1667 };
1668 int status;
1669
1670 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1671 encode_compound_hdr(&xdr, &hdr);
1672 status = encode_putfh(&xdr, args->fh);
1673 if(status)
1674 goto out;
1675 status = encode_readdir(&xdr, args, req);
1676out:
1677 return status;
1678}
1679
1680/*
1681 * Encode a READ request
1682 */
1683static int nfs4_xdr_enc_read(struct rpc_rqst *req, uint32_t *p, struct nfs_readargs *args)
1684{
1685 struct rpc_auth *auth = req->rq_task->tk_auth;
1686 struct xdr_stream xdr;
1687 struct compound_hdr hdr = {
1688 .nops = 2,
1689 };
1690 int replen, status;
1691
1692 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1693 encode_compound_hdr(&xdr, &hdr);
1694 status = encode_putfh(&xdr, args->fh);
1695 if (status)
1696 goto out;
1697 status = encode_read(&xdr, args);
1698 if (status)
1699 goto out;
1700
1701 /* set up reply kvec
1702 * toplevel status + taglen=0 + rescount + OP_PUTFH + status
1703 * + OP_READ + status + eof + datalen = 9
1704 */
1705 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_read_sz) << 2;
1706 xdr_inline_pages(&req->rq_rcv_buf, replen,
1707 args->pages, args->pgbase, args->count);
1708out:
1709 return status;
1710}
1711
1712/*
1713 * Encode an SETATTR request
1714 */
1715static int nfs4_xdr_enc_setattr(struct rpc_rqst *req, uint32_t *p, struct nfs_setattrargs *args)
1716
1717{
1718 struct xdr_stream xdr;
1719 struct compound_hdr hdr = {
1720 .nops = 3,
1721 };
1722 int status;
1723
1724 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1725 encode_compound_hdr(&xdr, &hdr);
1726 status = encode_putfh(&xdr, args->fh);
1727 if(status)
1728 goto out;
1729 status = encode_setattr(&xdr, args, args->server);
1730 if(status)
1731 goto out;
1732 status = encode_getfattr(&xdr, args->bitmask);
1733out:
1734 return status;
1735}
1736
1737/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00001738 * Encode a GETACL request
1739 */
1740static int
1741nfs4_xdr_enc_getacl(struct rpc_rqst *req, uint32_t *p,
1742 struct nfs_getaclargs *args)
1743{
1744 struct xdr_stream xdr;
1745 struct rpc_auth *auth = req->rq_task->tk_auth;
1746 struct compound_hdr hdr = {
1747 .nops = 2,
1748 };
1749 int replen, status;
1750
1751 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1752 encode_compound_hdr(&xdr, &hdr);
1753 status = encode_putfh(&xdr, args->fh);
1754 if (status)
1755 goto out;
1756 status = encode_getattr_two(&xdr, FATTR4_WORD0_ACL, 0);
1757 /* set up reply buffer: */
1758 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS4_dec_getacl_sz) << 2;
1759 xdr_inline_pages(&req->rq_rcv_buf, replen,
1760 args->acl_pages, args->acl_pgbase, args->acl_len);
1761out:
1762 return status;
1763}
1764
1765/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001766 * Encode a WRITE request
1767 */
1768static int nfs4_xdr_enc_write(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
1769{
1770 struct xdr_stream xdr;
1771 struct compound_hdr hdr = {
1772 .nops = 2,
1773 };
1774 int status;
1775
1776 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1777 encode_compound_hdr(&xdr, &hdr);
1778 status = encode_putfh(&xdr, args->fh);
1779 if (status)
1780 goto out;
1781 status = encode_write(&xdr, args);
1782out:
1783 return status;
1784}
1785
1786/*
1787 * a COMMIT request
1788 */
1789static int nfs4_xdr_enc_commit(struct rpc_rqst *req, uint32_t *p, struct nfs_writeargs *args)
1790{
1791 struct xdr_stream xdr;
1792 struct compound_hdr hdr = {
1793 .nops = 2,
1794 };
1795 int status;
1796
1797 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1798 encode_compound_hdr(&xdr, &hdr);
1799 status = encode_putfh(&xdr, args->fh);
1800 if (status)
1801 goto out;
1802 status = encode_commit(&xdr, args);
1803out:
1804 return status;
1805}
1806
1807/*
1808 * FSINFO request
1809 */
1810static int nfs4_xdr_enc_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs4_fsinfo_arg *args)
1811{
1812 struct xdr_stream xdr;
1813 struct compound_hdr hdr = {
1814 .nops = 2,
1815 };
1816 int status;
1817
1818 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1819 encode_compound_hdr(&xdr, &hdr);
1820 status = encode_putfh(&xdr, args->fh);
1821 if (!status)
1822 status = encode_fsinfo(&xdr, args->bitmask);
1823 return status;
1824}
1825
1826/*
1827 * a PATHCONF request
1828 */
1829static int nfs4_xdr_enc_pathconf(struct rpc_rqst *req, uint32_t *p, const struct nfs4_pathconf_arg *args)
1830{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001831 struct xdr_stream xdr;
1832 struct compound_hdr hdr = {
1833 .nops = 2,
1834 };
1835 int status;
1836
1837 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1838 encode_compound_hdr(&xdr, &hdr);
1839 status = encode_putfh(&xdr, args->fh);
1840 if (!status)
1841 status = encode_getattr_one(&xdr,
1842 args->bitmask[0] & nfs4_pathconf_bitmap[0]);
1843 return status;
1844}
1845
1846/*
1847 * a STATFS request
1848 */
1849static int nfs4_xdr_enc_statfs(struct rpc_rqst *req, uint32_t *p, const struct nfs4_statfs_arg *args)
1850{
Linus Torvalds1da177e2005-04-16 15:20:36 -07001851 struct xdr_stream xdr;
1852 struct compound_hdr hdr = {
1853 .nops = 2,
1854 };
1855 int status;
1856
1857 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1858 encode_compound_hdr(&xdr, &hdr);
1859 status = encode_putfh(&xdr, args->fh);
1860 if (status == 0)
1861 status = encode_getattr_two(&xdr,
1862 args->bitmask[0] & nfs4_statfs_bitmap[0],
1863 args->bitmask[1] & nfs4_statfs_bitmap[1]);
1864 return status;
1865}
1866
1867/*
1868 * GETATTR_BITMAP request
1869 */
1870static int nfs4_xdr_enc_server_caps(struct rpc_rqst *req, uint32_t *p, const struct nfs_fh *fhandle)
1871{
1872 struct xdr_stream xdr;
1873 struct compound_hdr hdr = {
1874 .nops = 2,
1875 };
1876 int status;
1877
1878 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1879 encode_compound_hdr(&xdr, &hdr);
1880 status = encode_putfh(&xdr, fhandle);
1881 if (status == 0)
1882 status = encode_getattr_one(&xdr, FATTR4_WORD0_SUPPORTED_ATTRS|
1883 FATTR4_WORD0_LINK_SUPPORT|
1884 FATTR4_WORD0_SYMLINK_SUPPORT|
1885 FATTR4_WORD0_ACLSUPPORT);
1886 return status;
1887}
1888
1889/*
1890 * a RENEW request
1891 */
1892static int nfs4_xdr_enc_renew(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp)
1893{
1894 struct xdr_stream xdr;
1895 struct compound_hdr hdr = {
1896 .nops = 1,
1897 };
1898
1899 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1900 encode_compound_hdr(&xdr, &hdr);
1901 return encode_renew(&xdr, clp);
1902}
1903
1904/*
1905 * a SETCLIENTID request
1906 */
1907static int nfs4_xdr_enc_setclientid(struct rpc_rqst *req, uint32_t *p, struct nfs4_setclientid *sc)
1908{
1909 struct xdr_stream xdr;
1910 struct compound_hdr hdr = {
1911 .nops = 1,
1912 };
1913
1914 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1915 encode_compound_hdr(&xdr, &hdr);
1916 return encode_setclientid(&xdr, sc);
1917}
1918
1919/*
1920 * a SETCLIENTID_CONFIRM request
1921 */
1922static int nfs4_xdr_enc_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs4_client *clp)
1923{
1924 struct xdr_stream xdr;
1925 struct compound_hdr hdr = {
1926 .nops = 3,
1927 };
1928 const u32 lease_bitmap[2] = { FATTR4_WORD0_LEASE_TIME, 0 };
1929 int status;
1930
1931 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1932 encode_compound_hdr(&xdr, &hdr);
1933 status = encode_setclientid_confirm(&xdr, clp);
1934 if (!status)
1935 status = encode_putrootfh(&xdr);
1936 if (!status)
1937 status = encode_fsinfo(&xdr, lease_bitmap);
1938 return status;
1939}
1940
1941/*
1942 * DELEGRETURN request
1943 */
1944static int nfs4_xdr_enc_delegreturn(struct rpc_rqst *req, uint32_t *p, const struct nfs4_delegreturnargs *args)
1945{
1946 struct xdr_stream xdr;
1947 struct compound_hdr hdr = {
1948 .nops = 2,
1949 };
1950 int status;
1951
1952 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1953 encode_compound_hdr(&xdr, &hdr);
1954 if ((status = encode_putfh(&xdr, args->fhandle)) == 0)
1955 status = encode_delegreturn(&xdr, args->stateid);
1956 return status;
1957}
1958
1959/*
1960 * START OF "GENERIC" DECODE ROUTINES.
1961 * These may look a little ugly since they are imported from a "generic"
1962 * set of XDR encode/decode routines which are intended to be shared by
1963 * all of our NFSv4 implementations (OpenBSD, MacOS X...).
1964 *
1965 * If the pain of reading these is too great, it should be a straightforward
1966 * task to translate them into Linux-specific versions which are more
1967 * consistent with the style used in NFSv2/v3...
1968 */
1969#define READ32(x) (x) = ntohl(*p++)
1970#define READ64(x) do { \
1971 (x) = (u64)ntohl(*p++) << 32; \
1972 (x) |= ntohl(*p++); \
1973} while (0)
1974#define READTIME(x) do { \
1975 p++; \
1976 (x.tv_sec) = ntohl(*p++); \
1977 (x.tv_nsec) = ntohl(*p++); \
1978} while (0)
1979#define COPYMEM(x,nbytes) do { \
1980 memcpy((x), p, nbytes); \
1981 p += XDR_QUADLEN(nbytes); \
1982} while (0)
1983
1984#define READ_BUF(nbytes) do { \
1985 p = xdr_inline_decode(xdr, nbytes); \
1986 if (!p) { \
1987 printk(KERN_WARNING "%s: reply buffer overflowed in line %d.", \
1988 __FUNCTION__, __LINE__); \
1989 return -EIO; \
1990 } \
1991} while (0)
1992
1993static int decode_opaque_inline(struct xdr_stream *xdr, uint32_t *len, char **string)
1994{
1995 uint32_t *p;
1996
1997 READ_BUF(4);
1998 READ32(*len);
1999 READ_BUF(*len);
2000 *string = (char *)p;
2001 return 0;
2002}
2003
2004static int decode_compound_hdr(struct xdr_stream *xdr, struct compound_hdr *hdr)
2005{
2006 uint32_t *p;
2007
2008 READ_BUF(8);
2009 READ32(hdr->status);
2010 READ32(hdr->taglen);
2011
2012 READ_BUF(hdr->taglen + 4);
2013 hdr->tag = (char *)p;
2014 p += XDR_QUADLEN(hdr->taglen);
2015 READ32(hdr->nops);
2016 return 0;
2017}
2018
2019static int decode_op_hdr(struct xdr_stream *xdr, enum nfs_opnum4 expected)
2020{
2021 uint32_t *p;
2022 uint32_t opnum;
2023 int32_t nfserr;
2024
2025 READ_BUF(8);
2026 READ32(opnum);
2027 if (opnum != expected) {
2028 printk(KERN_NOTICE
2029 "nfs4_decode_op_hdr: Server returned operation"
2030 " %d but we issued a request for %d\n",
2031 opnum, expected);
2032 return -EIO;
2033 }
2034 READ32(nfserr);
2035 if (nfserr != NFS_OK)
2036 return -nfs_stat_to_errno(nfserr);
2037 return 0;
2038}
2039
2040/* Dummy routine */
2041static int decode_ace(struct xdr_stream *xdr, void *ace, struct nfs4_client *clp)
2042{
2043 uint32_t *p;
2044 uint32_t strlen;
2045 char *str;
2046
2047 READ_BUF(12);
2048 return decode_opaque_inline(xdr, &strlen, &str);
2049}
2050
2051static int decode_attr_bitmap(struct xdr_stream *xdr, uint32_t *bitmap)
2052{
2053 uint32_t bmlen, *p;
2054
2055 READ_BUF(4);
2056 READ32(bmlen);
2057
2058 bitmap[0] = bitmap[1] = 0;
2059 READ_BUF((bmlen << 2));
2060 if (bmlen > 0) {
2061 READ32(bitmap[0]);
2062 if (bmlen > 1)
2063 READ32(bitmap[1]);
2064 }
2065 return 0;
2066}
2067
2068static inline int decode_attr_length(struct xdr_stream *xdr, uint32_t *attrlen, uint32_t **savep)
2069{
2070 uint32_t *p;
2071
2072 READ_BUF(4);
2073 READ32(*attrlen);
2074 *savep = xdr->p;
2075 return 0;
2076}
2077
2078static int decode_attr_supported(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *bitmask)
2079{
2080 if (likely(bitmap[0] & FATTR4_WORD0_SUPPORTED_ATTRS)) {
2081 decode_attr_bitmap(xdr, bitmask);
2082 bitmap[0] &= ~FATTR4_WORD0_SUPPORTED_ATTRS;
2083 } else
2084 bitmask[0] = bitmask[1] = 0;
2085 dprintk("%s: bitmask=0x%x%x\n", __FUNCTION__, bitmask[0], bitmask[1]);
2086 return 0;
2087}
2088
2089static int decode_attr_type(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *type)
2090{
2091 uint32_t *p;
2092
2093 *type = 0;
2094 if (unlikely(bitmap[0] & (FATTR4_WORD0_TYPE - 1U)))
2095 return -EIO;
2096 if (likely(bitmap[0] & FATTR4_WORD0_TYPE)) {
2097 READ_BUF(4);
2098 READ32(*type);
2099 if (*type < NF4REG || *type > NF4NAMEDATTR) {
2100 dprintk("%s: bad type %d\n", __FUNCTION__, *type);
2101 return -EIO;
2102 }
2103 bitmap[0] &= ~FATTR4_WORD0_TYPE;
2104 }
2105 dprintk("%s: type=0%o\n", __FUNCTION__, nfs_type2fmt[*type].nfs2type);
2106 return 0;
2107}
2108
2109static int decode_attr_change(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *change)
2110{
2111 uint32_t *p;
2112
2113 *change = 0;
2114 if (unlikely(bitmap[0] & (FATTR4_WORD0_CHANGE - 1U)))
2115 return -EIO;
2116 if (likely(bitmap[0] & FATTR4_WORD0_CHANGE)) {
2117 READ_BUF(8);
2118 READ64(*change);
2119 bitmap[0] &= ~FATTR4_WORD0_CHANGE;
2120 }
2121 dprintk("%s: change attribute=%Lu\n", __FUNCTION__,
2122 (unsigned long long)*change);
2123 return 0;
2124}
2125
2126static int decode_attr_size(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *size)
2127{
2128 uint32_t *p;
2129
2130 *size = 0;
2131 if (unlikely(bitmap[0] & (FATTR4_WORD0_SIZE - 1U)))
2132 return -EIO;
2133 if (likely(bitmap[0] & FATTR4_WORD0_SIZE)) {
2134 READ_BUF(8);
2135 READ64(*size);
2136 bitmap[0] &= ~FATTR4_WORD0_SIZE;
2137 }
2138 dprintk("%s: file size=%Lu\n", __FUNCTION__, (unsigned long long)*size);
2139 return 0;
2140}
2141
2142static int decode_attr_link_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2143{
2144 uint32_t *p;
2145
2146 *res = 0;
2147 if (unlikely(bitmap[0] & (FATTR4_WORD0_LINK_SUPPORT - 1U)))
2148 return -EIO;
2149 if (likely(bitmap[0] & FATTR4_WORD0_LINK_SUPPORT)) {
2150 READ_BUF(4);
2151 READ32(*res);
2152 bitmap[0] &= ~FATTR4_WORD0_LINK_SUPPORT;
2153 }
2154 dprintk("%s: link support=%s\n", __FUNCTION__, *res == 0 ? "false" : "true");
2155 return 0;
2156}
2157
2158static int decode_attr_symlink_support(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2159{
2160 uint32_t *p;
2161
2162 *res = 0;
2163 if (unlikely(bitmap[0] & (FATTR4_WORD0_SYMLINK_SUPPORT - 1U)))
2164 return -EIO;
2165 if (likely(bitmap[0] & FATTR4_WORD0_SYMLINK_SUPPORT)) {
2166 READ_BUF(4);
2167 READ32(*res);
2168 bitmap[0] &= ~FATTR4_WORD0_SYMLINK_SUPPORT;
2169 }
2170 dprintk("%s: symlink support=%s\n", __FUNCTION__, *res == 0 ? "false" : "true");
2171 return 0;
2172}
2173
2174static int decode_attr_fsid(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_fsid *fsid)
2175{
2176 uint32_t *p;
2177
2178 fsid->major = 0;
2179 fsid->minor = 0;
2180 if (unlikely(bitmap[0] & (FATTR4_WORD0_FSID - 1U)))
2181 return -EIO;
2182 if (likely(bitmap[0] & FATTR4_WORD0_FSID)) {
2183 READ_BUF(16);
2184 READ64(fsid->major);
2185 READ64(fsid->minor);
2186 bitmap[0] &= ~FATTR4_WORD0_FSID;
2187 }
2188 dprintk("%s: fsid=(0x%Lx/0x%Lx)\n", __FUNCTION__,
2189 (unsigned long long)fsid->major,
2190 (unsigned long long)fsid->minor);
2191 return 0;
2192}
2193
2194static int decode_attr_lease_time(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2195{
2196 uint32_t *p;
2197
2198 *res = 60;
2199 if (unlikely(bitmap[0] & (FATTR4_WORD0_LEASE_TIME - 1U)))
2200 return -EIO;
2201 if (likely(bitmap[0] & FATTR4_WORD0_LEASE_TIME)) {
2202 READ_BUF(4);
2203 READ32(*res);
2204 bitmap[0] &= ~FATTR4_WORD0_LEASE_TIME;
2205 }
2206 dprintk("%s: file size=%u\n", __FUNCTION__, (unsigned int)*res);
2207 return 0;
2208}
2209
2210static int decode_attr_aclsupport(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2211{
2212 uint32_t *p;
2213
2214 *res = ACL4_SUPPORT_ALLOW_ACL|ACL4_SUPPORT_DENY_ACL;
2215 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACLSUPPORT - 1U)))
2216 return -EIO;
2217 if (likely(bitmap[0] & FATTR4_WORD0_ACLSUPPORT)) {
2218 READ_BUF(4);
2219 READ32(*res);
2220 bitmap[0] &= ~FATTR4_WORD0_ACLSUPPORT;
2221 }
2222 dprintk("%s: ACLs supported=%u\n", __FUNCTION__, (unsigned int)*res);
2223 return 0;
2224}
2225
2226static int decode_attr_fileid(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *fileid)
2227{
2228 uint32_t *p;
2229
2230 *fileid = 0;
2231 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILEID - 1U)))
2232 return -EIO;
2233 if (likely(bitmap[0] & FATTR4_WORD0_FILEID)) {
2234 READ_BUF(8);
2235 READ64(*fileid);
2236 bitmap[0] &= ~FATTR4_WORD0_FILEID;
2237 }
2238 dprintk("%s: fileid=%Lu\n", __FUNCTION__, (unsigned long long)*fileid);
2239 return 0;
2240}
2241
2242static int decode_attr_files_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2243{
2244 uint32_t *p;
2245 int status = 0;
2246
2247 *res = 0;
2248 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_AVAIL - 1U)))
2249 return -EIO;
2250 if (likely(bitmap[0] & FATTR4_WORD0_FILES_AVAIL)) {
2251 READ_BUF(8);
2252 READ64(*res);
2253 bitmap[0] &= ~FATTR4_WORD0_FILES_AVAIL;
2254 }
2255 dprintk("%s: files avail=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2256 return status;
2257}
2258
2259static int decode_attr_files_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2260{
2261 uint32_t *p;
2262 int status = 0;
2263
2264 *res = 0;
2265 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_FREE - 1U)))
2266 return -EIO;
2267 if (likely(bitmap[0] & FATTR4_WORD0_FILES_FREE)) {
2268 READ_BUF(8);
2269 READ64(*res);
2270 bitmap[0] &= ~FATTR4_WORD0_FILES_FREE;
2271 }
2272 dprintk("%s: files free=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2273 return status;
2274}
2275
2276static int decode_attr_files_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2277{
2278 uint32_t *p;
2279 int status = 0;
2280
2281 *res = 0;
2282 if (unlikely(bitmap[0] & (FATTR4_WORD0_FILES_TOTAL - 1U)))
2283 return -EIO;
2284 if (likely(bitmap[0] & FATTR4_WORD0_FILES_TOTAL)) {
2285 READ_BUF(8);
2286 READ64(*res);
2287 bitmap[0] &= ~FATTR4_WORD0_FILES_TOTAL;
2288 }
2289 dprintk("%s: files total=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2290 return status;
2291}
2292
2293static int decode_attr_maxfilesize(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2294{
2295 uint32_t *p;
2296 int status = 0;
2297
2298 *res = 0;
2299 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXFILESIZE - 1U)))
2300 return -EIO;
2301 if (likely(bitmap[0] & FATTR4_WORD0_MAXFILESIZE)) {
2302 READ_BUF(8);
2303 READ64(*res);
2304 bitmap[0] &= ~FATTR4_WORD0_MAXFILESIZE;
2305 }
2306 dprintk("%s: maxfilesize=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2307 return status;
2308}
2309
2310static int decode_attr_maxlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxlink)
2311{
2312 uint32_t *p;
2313 int status = 0;
2314
2315 *maxlink = 1;
2316 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXLINK - 1U)))
2317 return -EIO;
2318 if (likely(bitmap[0] & FATTR4_WORD0_MAXLINK)) {
2319 READ_BUF(4);
2320 READ32(*maxlink);
2321 bitmap[0] &= ~FATTR4_WORD0_MAXLINK;
2322 }
2323 dprintk("%s: maxlink=%u\n", __FUNCTION__, *maxlink);
2324 return status;
2325}
2326
2327static int decode_attr_maxname(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *maxname)
2328{
2329 uint32_t *p;
2330 int status = 0;
2331
2332 *maxname = 1024;
2333 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXNAME - 1U)))
2334 return -EIO;
2335 if (likely(bitmap[0] & FATTR4_WORD0_MAXNAME)) {
2336 READ_BUF(4);
2337 READ32(*maxname);
2338 bitmap[0] &= ~FATTR4_WORD0_MAXNAME;
2339 }
2340 dprintk("%s: maxname=%u\n", __FUNCTION__, *maxname);
2341 return status;
2342}
2343
2344static int decode_attr_maxread(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2345{
2346 uint32_t *p;
2347 int status = 0;
2348
2349 *res = 1024;
2350 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXREAD - 1U)))
2351 return -EIO;
2352 if (likely(bitmap[0] & FATTR4_WORD0_MAXREAD)) {
2353 uint64_t maxread;
2354 READ_BUF(8);
2355 READ64(maxread);
2356 if (maxread > 0x7FFFFFFF)
2357 maxread = 0x7FFFFFFF;
2358 *res = (uint32_t)maxread;
2359 bitmap[0] &= ~FATTR4_WORD0_MAXREAD;
2360 }
2361 dprintk("%s: maxread=%lu\n", __FUNCTION__, (unsigned long)*res);
2362 return status;
2363}
2364
2365static int decode_attr_maxwrite(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *res)
2366{
2367 uint32_t *p;
2368 int status = 0;
2369
2370 *res = 1024;
2371 if (unlikely(bitmap[0] & (FATTR4_WORD0_MAXWRITE - 1U)))
2372 return -EIO;
2373 if (likely(bitmap[0] & FATTR4_WORD0_MAXWRITE)) {
2374 uint64_t maxwrite;
2375 READ_BUF(8);
2376 READ64(maxwrite);
2377 if (maxwrite > 0x7FFFFFFF)
2378 maxwrite = 0x7FFFFFFF;
2379 *res = (uint32_t)maxwrite;
2380 bitmap[0] &= ~FATTR4_WORD0_MAXWRITE;
2381 }
2382 dprintk("%s: maxwrite=%lu\n", __FUNCTION__, (unsigned long)*res);
2383 return status;
2384}
2385
2386static int decode_attr_mode(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *mode)
2387{
2388 uint32_t *p;
2389
2390 *mode = 0;
2391 if (unlikely(bitmap[1] & (FATTR4_WORD1_MODE - 1U)))
2392 return -EIO;
2393 if (likely(bitmap[1] & FATTR4_WORD1_MODE)) {
2394 READ_BUF(4);
2395 READ32(*mode);
2396 *mode &= ~S_IFMT;
2397 bitmap[1] &= ~FATTR4_WORD1_MODE;
2398 }
2399 dprintk("%s: file mode=0%o\n", __FUNCTION__, (unsigned int)*mode);
2400 return 0;
2401}
2402
2403static int decode_attr_nlink(struct xdr_stream *xdr, uint32_t *bitmap, uint32_t *nlink)
2404{
2405 uint32_t *p;
2406
2407 *nlink = 1;
2408 if (unlikely(bitmap[1] & (FATTR4_WORD1_NUMLINKS - 1U)))
2409 return -EIO;
2410 if (likely(bitmap[1] & FATTR4_WORD1_NUMLINKS)) {
2411 READ_BUF(4);
2412 READ32(*nlink);
2413 bitmap[1] &= ~FATTR4_WORD1_NUMLINKS;
2414 }
2415 dprintk("%s: nlink=%u\n", __FUNCTION__, (unsigned int)*nlink);
2416 return 0;
2417}
2418
2419static int decode_attr_owner(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *uid)
2420{
2421 uint32_t len, *p;
2422
2423 *uid = -2;
2424 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER - 1U)))
2425 return -EIO;
2426 if (likely(bitmap[1] & FATTR4_WORD1_OWNER)) {
2427 READ_BUF(4);
2428 READ32(len);
2429 READ_BUF(len);
2430 if (len < XDR_MAX_NETOBJ) {
2431 if (nfs_map_name_to_uid(clp, (char *)p, len, uid) != 0)
2432 dprintk("%s: nfs_map_name_to_uid failed!\n",
2433 __FUNCTION__);
2434 } else
2435 printk(KERN_WARNING "%s: name too long (%u)!\n",
2436 __FUNCTION__, len);
2437 bitmap[1] &= ~FATTR4_WORD1_OWNER;
2438 }
2439 dprintk("%s: uid=%d\n", __FUNCTION__, (int)*uid);
2440 return 0;
2441}
2442
2443static int decode_attr_group(struct xdr_stream *xdr, uint32_t *bitmap, struct nfs4_client *clp, int32_t *gid)
2444{
2445 uint32_t len, *p;
2446
2447 *gid = -2;
2448 if (unlikely(bitmap[1] & (FATTR4_WORD1_OWNER_GROUP - 1U)))
2449 return -EIO;
2450 if (likely(bitmap[1] & FATTR4_WORD1_OWNER_GROUP)) {
2451 READ_BUF(4);
2452 READ32(len);
2453 READ_BUF(len);
2454 if (len < XDR_MAX_NETOBJ) {
2455 if (nfs_map_group_to_gid(clp, (char *)p, len, gid) != 0)
2456 dprintk("%s: nfs_map_group_to_gid failed!\n",
2457 __FUNCTION__);
2458 } else
2459 printk(KERN_WARNING "%s: name too long (%u)!\n",
2460 __FUNCTION__, len);
2461 bitmap[1] &= ~FATTR4_WORD1_OWNER_GROUP;
2462 }
2463 dprintk("%s: gid=%d\n", __FUNCTION__, (int)*gid);
2464 return 0;
2465}
2466
2467static int decode_attr_rdev(struct xdr_stream *xdr, uint32_t *bitmap, dev_t *rdev)
2468{
2469 uint32_t major = 0, minor = 0, *p;
2470
2471 *rdev = MKDEV(0,0);
2472 if (unlikely(bitmap[1] & (FATTR4_WORD1_RAWDEV - 1U)))
2473 return -EIO;
2474 if (likely(bitmap[1] & FATTR4_WORD1_RAWDEV)) {
2475 dev_t tmp;
2476
2477 READ_BUF(8);
2478 READ32(major);
2479 READ32(minor);
2480 tmp = MKDEV(major, minor);
2481 if (MAJOR(tmp) == major && MINOR(tmp) == minor)
2482 *rdev = tmp;
2483 bitmap[1] &= ~ FATTR4_WORD1_RAWDEV;
2484 }
2485 dprintk("%s: rdev=(0x%x:0x%x)\n", __FUNCTION__, major, minor);
2486 return 0;
2487}
2488
2489static int decode_attr_space_avail(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2490{
2491 uint32_t *p;
2492 int status = 0;
2493
2494 *res = 0;
2495 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_AVAIL - 1U)))
2496 return -EIO;
2497 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_AVAIL)) {
2498 READ_BUF(8);
2499 READ64(*res);
2500 bitmap[1] &= ~FATTR4_WORD1_SPACE_AVAIL;
2501 }
2502 dprintk("%s: space avail=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2503 return status;
2504}
2505
2506static int decode_attr_space_free(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2507{
2508 uint32_t *p;
2509 int status = 0;
2510
2511 *res = 0;
2512 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_FREE - 1U)))
2513 return -EIO;
2514 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_FREE)) {
2515 READ_BUF(8);
2516 READ64(*res);
2517 bitmap[1] &= ~FATTR4_WORD1_SPACE_FREE;
2518 }
2519 dprintk("%s: space free=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2520 return status;
2521}
2522
2523static int decode_attr_space_total(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *res)
2524{
2525 uint32_t *p;
2526 int status = 0;
2527
2528 *res = 0;
2529 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_TOTAL - 1U)))
2530 return -EIO;
2531 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_TOTAL)) {
2532 READ_BUF(8);
2533 READ64(*res);
2534 bitmap[1] &= ~FATTR4_WORD1_SPACE_TOTAL;
2535 }
2536 dprintk("%s: space total=%Lu\n", __FUNCTION__, (unsigned long long)*res);
2537 return status;
2538}
2539
2540static int decode_attr_space_used(struct xdr_stream *xdr, uint32_t *bitmap, uint64_t *used)
2541{
2542 uint32_t *p;
2543
2544 *used = 0;
2545 if (unlikely(bitmap[1] & (FATTR4_WORD1_SPACE_USED - 1U)))
2546 return -EIO;
2547 if (likely(bitmap[1] & FATTR4_WORD1_SPACE_USED)) {
2548 READ_BUF(8);
2549 READ64(*used);
2550 bitmap[1] &= ~FATTR4_WORD1_SPACE_USED;
2551 }
2552 dprintk("%s: space used=%Lu\n", __FUNCTION__,
2553 (unsigned long long)*used);
2554 return 0;
2555}
2556
2557static int decode_attr_time(struct xdr_stream *xdr, struct timespec *time)
2558{
2559 uint32_t *p;
2560 uint64_t sec;
2561 uint32_t nsec;
2562
2563 READ_BUF(12);
2564 READ64(sec);
2565 READ32(nsec);
2566 time->tv_sec = (time_t)sec;
2567 time->tv_nsec = (long)nsec;
2568 return 0;
2569}
2570
2571static int decode_attr_time_access(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
2572{
2573 int status = 0;
2574
2575 time->tv_sec = 0;
2576 time->tv_nsec = 0;
2577 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_ACCESS - 1U)))
2578 return -EIO;
2579 if (likely(bitmap[1] & FATTR4_WORD1_TIME_ACCESS)) {
2580 status = decode_attr_time(xdr, time);
2581 bitmap[1] &= ~FATTR4_WORD1_TIME_ACCESS;
2582 }
2583 dprintk("%s: atime=%ld\n", __FUNCTION__, (long)time->tv_sec);
2584 return status;
2585}
2586
2587static int decode_attr_time_metadata(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
2588{
2589 int status = 0;
2590
2591 time->tv_sec = 0;
2592 time->tv_nsec = 0;
2593 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_METADATA - 1U)))
2594 return -EIO;
2595 if (likely(bitmap[1] & FATTR4_WORD1_TIME_METADATA)) {
2596 status = decode_attr_time(xdr, time);
2597 bitmap[1] &= ~FATTR4_WORD1_TIME_METADATA;
2598 }
2599 dprintk("%s: ctime=%ld\n", __FUNCTION__, (long)time->tv_sec);
2600 return status;
2601}
2602
2603static int decode_attr_time_modify(struct xdr_stream *xdr, uint32_t *bitmap, struct timespec *time)
2604{
2605 int status = 0;
2606
2607 time->tv_sec = 0;
2608 time->tv_nsec = 0;
2609 if (unlikely(bitmap[1] & (FATTR4_WORD1_TIME_MODIFY - 1U)))
2610 return -EIO;
2611 if (likely(bitmap[1] & FATTR4_WORD1_TIME_MODIFY)) {
2612 status = decode_attr_time(xdr, time);
2613 bitmap[1] &= ~FATTR4_WORD1_TIME_MODIFY;
2614 }
2615 dprintk("%s: mtime=%ld\n", __FUNCTION__, (long)time->tv_sec);
2616 return status;
2617}
2618
2619static int verify_attr_len(struct xdr_stream *xdr, uint32_t *savep, uint32_t attrlen)
2620{
2621 unsigned int attrwords = XDR_QUADLEN(attrlen);
2622 unsigned int nwords = xdr->p - savep;
2623
2624 if (unlikely(attrwords != nwords)) {
2625 printk(KERN_WARNING "%s: server returned incorrect attribute length: %u %c %u\n",
2626 __FUNCTION__,
2627 attrwords << 2,
2628 (attrwords < nwords) ? '<' : '>',
2629 nwords << 2);
2630 return -EIO;
2631 }
2632 return 0;
2633}
2634
2635static int decode_change_info(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
2636{
2637 uint32_t *p;
2638
2639 READ_BUF(20);
2640 READ32(cinfo->atomic);
2641 READ64(cinfo->before);
2642 READ64(cinfo->after);
2643 return 0;
2644}
2645
2646static int decode_access(struct xdr_stream *xdr, struct nfs4_accessres *access)
2647{
2648 uint32_t *p;
2649 uint32_t supp, acc;
2650 int status;
2651
2652 status = decode_op_hdr(xdr, OP_ACCESS);
2653 if (status)
2654 return status;
2655 READ_BUF(8);
2656 READ32(supp);
2657 READ32(acc);
2658 access->supported = supp;
2659 access->access = acc;
2660 return 0;
2661}
2662
2663static int decode_close(struct xdr_stream *xdr, struct nfs_closeres *res)
2664{
2665 uint32_t *p;
2666 int status;
2667
2668 status = decode_op_hdr(xdr, OP_CLOSE);
2669 if (status)
2670 return status;
2671 READ_BUF(sizeof(res->stateid.data));
2672 COPYMEM(res->stateid.data, sizeof(res->stateid.data));
2673 return 0;
2674}
2675
2676static int decode_commit(struct xdr_stream *xdr, struct nfs_writeres *res)
2677{
2678 uint32_t *p;
2679 int status;
2680
2681 status = decode_op_hdr(xdr, OP_COMMIT);
2682 if (status)
2683 return status;
2684 READ_BUF(8);
2685 COPYMEM(res->verf->verifier, 8);
2686 return 0;
2687}
2688
2689static int decode_create(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
2690{
2691 uint32_t *p;
2692 uint32_t bmlen;
2693 int status;
2694
2695 status = decode_op_hdr(xdr, OP_CREATE);
2696 if (status)
2697 return status;
2698 if ((status = decode_change_info(xdr, cinfo)))
2699 return status;
2700 READ_BUF(4);
2701 READ32(bmlen);
2702 READ_BUF(bmlen << 2);
2703 return 0;
2704}
2705
2706static int decode_server_caps(struct xdr_stream *xdr, struct nfs4_server_caps_res *res)
2707{
2708 uint32_t *savep;
2709 uint32_t attrlen,
2710 bitmap[2] = {0};
2711 int status;
2712
2713 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
2714 goto xdr_error;
2715 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
2716 goto xdr_error;
2717 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
2718 goto xdr_error;
2719 if ((status = decode_attr_supported(xdr, bitmap, res->attr_bitmask)) != 0)
2720 goto xdr_error;
2721 if ((status = decode_attr_link_support(xdr, bitmap, &res->has_links)) != 0)
2722 goto xdr_error;
2723 if ((status = decode_attr_symlink_support(xdr, bitmap, &res->has_symlinks)) != 0)
2724 goto xdr_error;
2725 if ((status = decode_attr_aclsupport(xdr, bitmap, &res->acl_bitmask)) != 0)
2726 goto xdr_error;
2727 status = verify_attr_len(xdr, savep, attrlen);
2728xdr_error:
2729 if (status != 0)
2730 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
2731 return status;
2732}
2733
2734static int decode_statfs(struct xdr_stream *xdr, struct nfs_fsstat *fsstat)
2735{
2736 uint32_t *savep;
2737 uint32_t attrlen,
2738 bitmap[2] = {0};
2739 int status;
2740
2741 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
2742 goto xdr_error;
2743 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
2744 goto xdr_error;
2745 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
2746 goto xdr_error;
2747
2748 if ((status = decode_attr_files_avail(xdr, bitmap, &fsstat->afiles)) != 0)
2749 goto xdr_error;
2750 if ((status = decode_attr_files_free(xdr, bitmap, &fsstat->ffiles)) != 0)
2751 goto xdr_error;
2752 if ((status = decode_attr_files_total(xdr, bitmap, &fsstat->tfiles)) != 0)
2753 goto xdr_error;
2754 if ((status = decode_attr_space_avail(xdr, bitmap, &fsstat->abytes)) != 0)
2755 goto xdr_error;
2756 if ((status = decode_attr_space_free(xdr, bitmap, &fsstat->fbytes)) != 0)
2757 goto xdr_error;
2758 if ((status = decode_attr_space_total(xdr, bitmap, &fsstat->tbytes)) != 0)
2759 goto xdr_error;
2760
2761 status = verify_attr_len(xdr, savep, attrlen);
2762xdr_error:
2763 if (status != 0)
2764 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
2765 return status;
2766}
2767
2768static int decode_pathconf(struct xdr_stream *xdr, struct nfs_pathconf *pathconf)
2769{
2770 uint32_t *savep;
2771 uint32_t attrlen,
2772 bitmap[2] = {0};
2773 int status;
2774
2775 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
2776 goto xdr_error;
2777 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
2778 goto xdr_error;
2779 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
2780 goto xdr_error;
2781
2782 if ((status = decode_attr_maxlink(xdr, bitmap, &pathconf->max_link)) != 0)
2783 goto xdr_error;
2784 if ((status = decode_attr_maxname(xdr, bitmap, &pathconf->max_namelen)) != 0)
2785 goto xdr_error;
2786
2787 status = verify_attr_len(xdr, savep, attrlen);
2788xdr_error:
2789 if (status != 0)
2790 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
2791 return status;
2792}
2793
2794static int decode_getfattr(struct xdr_stream *xdr, struct nfs_fattr *fattr, const struct nfs_server *server)
2795{
2796 uint32_t *savep;
2797 uint32_t attrlen,
2798 bitmap[2] = {0},
2799 type;
2800 int status, fmode = 0;
2801
2802 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
2803 goto xdr_error;
2804 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
2805 goto xdr_error;
2806
2807 fattr->bitmap[0] = bitmap[0];
2808 fattr->bitmap[1] = bitmap[1];
2809
2810 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
2811 goto xdr_error;
2812
2813
2814 if ((status = decode_attr_type(xdr, bitmap, &type)) != 0)
2815 goto xdr_error;
2816 fattr->type = nfs_type2fmt[type].nfs2type;
2817 fmode = nfs_type2fmt[type].mode;
2818
2819 if ((status = decode_attr_change(xdr, bitmap, &fattr->change_attr)) != 0)
2820 goto xdr_error;
2821 if ((status = decode_attr_size(xdr, bitmap, &fattr->size)) != 0)
2822 goto xdr_error;
2823 if ((status = decode_attr_fsid(xdr, bitmap, &fattr->fsid_u.nfs4)) != 0)
2824 goto xdr_error;
2825 if ((status = decode_attr_fileid(xdr, bitmap, &fattr->fileid)) != 0)
2826 goto xdr_error;
2827 if ((status = decode_attr_mode(xdr, bitmap, &fattr->mode)) != 0)
2828 goto xdr_error;
2829 fattr->mode |= fmode;
2830 if ((status = decode_attr_nlink(xdr, bitmap, &fattr->nlink)) != 0)
2831 goto xdr_error;
2832 if ((status = decode_attr_owner(xdr, bitmap, server->nfs4_state, &fattr->uid)) != 0)
2833 goto xdr_error;
2834 if ((status = decode_attr_group(xdr, bitmap, server->nfs4_state, &fattr->gid)) != 0)
2835 goto xdr_error;
2836 if ((status = decode_attr_rdev(xdr, bitmap, &fattr->rdev)) != 0)
2837 goto xdr_error;
2838 if ((status = decode_attr_space_used(xdr, bitmap, &fattr->du.nfs3.used)) != 0)
2839 goto xdr_error;
2840 if ((status = decode_attr_time_access(xdr, bitmap, &fattr->atime)) != 0)
2841 goto xdr_error;
2842 if ((status = decode_attr_time_metadata(xdr, bitmap, &fattr->ctime)) != 0)
2843 goto xdr_error;
2844 if ((status = decode_attr_time_modify(xdr, bitmap, &fattr->mtime)) != 0)
2845 goto xdr_error;
Trond Myklebust33801142005-10-27 22:12:39 -04002846 if ((status = verify_attr_len(xdr, savep, attrlen)) == 0)
Linus Torvalds1da177e2005-04-16 15:20:36 -07002847 fattr->valid = NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3 | NFS_ATTR_FATTR_V4;
Linus Torvalds1da177e2005-04-16 15:20:36 -07002848xdr_error:
2849 if (status != 0)
2850 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
2851 return status;
2852}
2853
2854
2855static int decode_fsinfo(struct xdr_stream *xdr, struct nfs_fsinfo *fsinfo)
2856{
2857 uint32_t *savep;
2858 uint32_t attrlen, bitmap[2];
2859 int status;
2860
2861 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
2862 goto xdr_error;
2863 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
2864 goto xdr_error;
2865 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
2866 goto xdr_error;
2867
2868 fsinfo->rtmult = fsinfo->wtmult = 512; /* ??? */
2869
2870 if ((status = decode_attr_lease_time(xdr, bitmap, &fsinfo->lease_time)) != 0)
2871 goto xdr_error;
2872 if ((status = decode_attr_maxfilesize(xdr, bitmap, &fsinfo->maxfilesize)) != 0)
2873 goto xdr_error;
2874 if ((status = decode_attr_maxread(xdr, bitmap, &fsinfo->rtmax)) != 0)
2875 goto xdr_error;
2876 fsinfo->rtpref = fsinfo->dtpref = fsinfo->rtmax;
2877 if ((status = decode_attr_maxwrite(xdr, bitmap, &fsinfo->wtmax)) != 0)
2878 goto xdr_error;
2879 fsinfo->wtpref = fsinfo->wtmax;
2880
2881 status = verify_attr_len(xdr, savep, attrlen);
2882xdr_error:
2883 if (status != 0)
2884 printk(KERN_NOTICE "%s: xdr error %d!\n", __FUNCTION__, -status);
2885 return status;
2886}
2887
2888static int decode_getfh(struct xdr_stream *xdr, struct nfs_fh *fh)
2889{
2890 uint32_t *p;
2891 uint32_t len;
2892 int status;
2893
2894 status = decode_op_hdr(xdr, OP_GETFH);
2895 if (status)
2896 return status;
2897 /* Zero handle first to allow comparisons */
2898 memset(fh, 0, sizeof(*fh));
2899
2900 READ_BUF(4);
2901 READ32(len);
2902 if (len > NFS4_FHSIZE)
2903 return -EIO;
2904 fh->size = len;
2905 READ_BUF(len);
2906 COPYMEM(fh->data, len);
2907 return 0;
2908}
2909
2910static int decode_link(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
2911{
2912 int status;
2913
2914 status = decode_op_hdr(xdr, OP_LINK);
2915 if (status)
2916 return status;
2917 return decode_change_info(xdr, cinfo);
2918}
2919
2920/*
2921 * We create the owner, so we know a proper owner.id length is 4.
2922 */
2923static int decode_lock_denied (struct xdr_stream *xdr, struct nfs_lock_denied *denied)
2924{
2925 uint32_t *p;
2926 uint32_t namelen;
2927
2928 READ_BUF(32);
2929 READ64(denied->offset);
2930 READ64(denied->length);
2931 READ32(denied->type);
2932 READ64(denied->owner.clientid);
2933 READ32(namelen);
2934 READ_BUF(namelen);
2935 if (namelen == 4)
2936 READ32(denied->owner.id);
2937 return -NFS4ERR_DENIED;
2938}
2939
2940static int decode_lock(struct xdr_stream *xdr, struct nfs_lockres *res)
2941{
2942 uint32_t *p;
2943 int status;
2944
2945 status = decode_op_hdr(xdr, OP_LOCK);
2946 if (status == 0) {
Trond Myklebust06735b32005-10-18 14:20:15 -07002947 READ_BUF(sizeof(res->u.stateid.data));
2948 COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002949 } else if (status == -NFS4ERR_DENIED)
2950 return decode_lock_denied(xdr, &res->u.denied);
2951 return status;
2952}
2953
2954static int decode_lockt(struct xdr_stream *xdr, struct nfs_lockres *res)
2955{
2956 int status;
2957 status = decode_op_hdr(xdr, OP_LOCKT);
2958 if (status == -NFS4ERR_DENIED)
2959 return decode_lock_denied(xdr, &res->u.denied);
2960 return status;
2961}
2962
2963static int decode_locku(struct xdr_stream *xdr, struct nfs_lockres *res)
2964{
2965 uint32_t *p;
2966 int status;
2967
2968 status = decode_op_hdr(xdr, OP_LOCKU);
2969 if (status == 0) {
Trond Myklebustfaf5f492005-10-18 14:20:15 -07002970 READ_BUF(sizeof(res->u.stateid.data));
2971 COPYMEM(res->u.stateid.data, sizeof(res->u.stateid.data));
Linus Torvalds1da177e2005-04-16 15:20:36 -07002972 }
2973 return status;
2974}
2975
2976static int decode_lookup(struct xdr_stream *xdr)
2977{
2978 return decode_op_hdr(xdr, OP_LOOKUP);
2979}
2980
2981/* This is too sick! */
2982static int decode_space_limit(struct xdr_stream *xdr, u64 *maxsize)
2983{
2984 uint32_t *p;
2985 uint32_t limit_type, nblocks, blocksize;
2986
2987 READ_BUF(12);
2988 READ32(limit_type);
2989 switch (limit_type) {
2990 case 1:
2991 READ64(*maxsize);
2992 break;
2993 case 2:
2994 READ32(nblocks);
2995 READ32(blocksize);
2996 *maxsize = (uint64_t)nblocks * (uint64_t)blocksize;
2997 }
2998 return 0;
2999}
3000
3001static int decode_delegation(struct xdr_stream *xdr, struct nfs_openres *res)
3002{
3003 uint32_t *p;
3004 uint32_t delegation_type;
3005
3006 READ_BUF(4);
3007 READ32(delegation_type);
3008 if (delegation_type == NFS4_OPEN_DELEGATE_NONE) {
3009 res->delegation_type = 0;
3010 return 0;
3011 }
3012 READ_BUF(20);
3013 COPYMEM(res->delegation.data, sizeof(res->delegation.data));
3014 READ32(res->do_recall);
3015 switch (delegation_type) {
3016 case NFS4_OPEN_DELEGATE_READ:
3017 res->delegation_type = FMODE_READ;
3018 break;
3019 case NFS4_OPEN_DELEGATE_WRITE:
3020 res->delegation_type = FMODE_WRITE|FMODE_READ;
3021 if (decode_space_limit(xdr, &res->maxsize) < 0)
3022 return -EIO;
3023 }
3024 return decode_ace(xdr, NULL, res->server->nfs4_state);
3025}
3026
3027static int decode_open(struct xdr_stream *xdr, struct nfs_openres *res)
3028{
3029 uint32_t *p;
3030 uint32_t bmlen;
3031 int status;
3032
3033 status = decode_op_hdr(xdr, OP_OPEN);
3034 if (status)
3035 return status;
3036 READ_BUF(sizeof(res->stateid.data));
3037 COPYMEM(res->stateid.data, sizeof(res->stateid.data));
3038
3039 decode_change_info(xdr, &res->cinfo);
3040
3041 READ_BUF(8);
3042 READ32(res->rflags);
3043 READ32(bmlen);
3044 if (bmlen > 10)
3045 goto xdr_error;
3046
3047 READ_BUF(bmlen << 2);
3048 p += bmlen;
3049 return decode_delegation(xdr, res);
3050xdr_error:
3051 printk(KERN_NOTICE "%s: xdr error!\n", __FUNCTION__);
3052 return -EIO;
3053}
3054
3055static int decode_open_confirm(struct xdr_stream *xdr, struct nfs_open_confirmres *res)
3056{
3057 uint32_t *p;
3058 int status;
3059
3060 status = decode_op_hdr(xdr, OP_OPEN_CONFIRM);
3061 if (status)
3062 return status;
3063 READ_BUF(sizeof(res->stateid.data));
3064 COPYMEM(res->stateid.data, sizeof(res->stateid.data));
3065 return 0;
3066}
3067
3068static int decode_open_downgrade(struct xdr_stream *xdr, struct nfs_closeres *res)
3069{
3070 uint32_t *p;
3071 int status;
3072
3073 status = decode_op_hdr(xdr, OP_OPEN_DOWNGRADE);
3074 if (status)
3075 return status;
3076 READ_BUF(sizeof(res->stateid.data));
3077 COPYMEM(res->stateid.data, sizeof(res->stateid.data));
3078 return 0;
3079}
3080
3081static int decode_putfh(struct xdr_stream *xdr)
3082{
3083 return decode_op_hdr(xdr, OP_PUTFH);
3084}
3085
3086static int decode_putrootfh(struct xdr_stream *xdr)
3087{
3088 return decode_op_hdr(xdr, OP_PUTROOTFH);
3089}
3090
3091static int decode_read(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs_readres *res)
3092{
3093 struct kvec *iov = req->rq_rcv_buf.head;
3094 uint32_t *p;
3095 uint32_t count, eof, recvd, hdrlen;
3096 int status;
3097
3098 status = decode_op_hdr(xdr, OP_READ);
3099 if (status)
3100 return status;
3101 READ_BUF(8);
3102 READ32(eof);
3103 READ32(count);
3104 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
3105 recvd = req->rq_rcv_buf.len - hdrlen;
3106 if (count > recvd) {
3107 printk(KERN_WARNING "NFS: server cheating in read reply: "
3108 "count %u > recvd %u\n", count, recvd);
3109 count = recvd;
3110 eof = 0;
3111 }
3112 xdr_read_pages(xdr, count);
3113 res->eof = eof;
3114 res->count = count;
3115 return 0;
3116}
3117
3118static int decode_readdir(struct xdr_stream *xdr, struct rpc_rqst *req, struct nfs4_readdir_res *readdir)
3119{
3120 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
3121 struct page *page = *rcvbuf->pages;
3122 struct kvec *iov = rcvbuf->head;
3123 unsigned int nr, pglen = rcvbuf->page_len;
3124 uint32_t *end, *entry, *p, *kaddr;
3125 uint32_t len, attrlen;
3126 int hdrlen, recvd, status;
3127
3128 status = decode_op_hdr(xdr, OP_READDIR);
3129 if (status)
3130 return status;
3131 READ_BUF(8);
3132 COPYMEM(readdir->verifier.data, 8);
Trond Myklebusteadf4592005-06-22 17:16:39 +00003133 dprintk("%s: verifier = 0x%x%x\n",
3134 __FUNCTION__,
3135 ((u32 *)readdir->verifier.data)[0],
3136 ((u32 *)readdir->verifier.data)[1]);
3137
Linus Torvalds1da177e2005-04-16 15:20:36 -07003138
3139 hdrlen = (char *) p - (char *) iov->iov_base;
3140 recvd = rcvbuf->len - hdrlen;
3141 if (pglen > recvd)
3142 pglen = recvd;
3143 xdr_read_pages(xdr, pglen);
3144
3145 BUG_ON(pglen + readdir->pgbase > PAGE_CACHE_SIZE);
3146 kaddr = p = (uint32_t *) kmap_atomic(page, KM_USER0);
3147 end = (uint32_t *) ((char *)p + pglen + readdir->pgbase);
3148 entry = p;
3149 for (nr = 0; *p++; nr++) {
3150 if (p + 3 > end)
3151 goto short_pkt;
Trond Myklebusteadf4592005-06-22 17:16:39 +00003152 dprintk("cookie = %Lu, ", *((unsigned long long *)p));
Linus Torvalds1da177e2005-04-16 15:20:36 -07003153 p += 2; /* cookie */
3154 len = ntohl(*p++); /* filename length */
3155 if (len > NFS4_MAXNAMLEN) {
3156 printk(KERN_WARNING "NFS: giant filename in readdir (len 0x%x)\n", len);
3157 goto err_unmap;
3158 }
Trond Myklebusteadf4592005-06-22 17:16:39 +00003159 dprintk("filename = %*s\n", len, (char *)p);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003160 p += XDR_QUADLEN(len);
3161 if (p + 1 > end)
3162 goto short_pkt;
3163 len = ntohl(*p++); /* bitmap length */
3164 p += len;
3165 if (p + 1 > end)
3166 goto short_pkt;
3167 attrlen = XDR_QUADLEN(ntohl(*p++));
3168 p += attrlen; /* attributes */
3169 if (p + 2 > end)
3170 goto short_pkt;
3171 entry = p;
3172 }
3173 if (!nr && (entry[0] != 0 || entry[1] == 0))
3174 goto short_pkt;
3175out:
3176 kunmap_atomic(kaddr, KM_USER0);
3177 return 0;
3178short_pkt:
Trond Myklebusteadf4592005-06-22 17:16:39 +00003179 dprintk("%s: short packet at entry %d\n", __FUNCTION__, nr);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003180 entry[0] = entry[1] = 0;
3181 /* truncate listing ? */
3182 if (!nr) {
3183 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
3184 entry[1] = 1;
3185 }
3186 goto out;
3187err_unmap:
3188 kunmap_atomic(kaddr, KM_USER0);
3189 return -errno_NFSERR_IO;
3190}
3191
3192static int decode_readlink(struct xdr_stream *xdr, struct rpc_rqst *req)
3193{
3194 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
3195 struct kvec *iov = rcvbuf->head;
3196 int hdrlen, len, recvd;
3197 uint32_t *p;
3198 char *kaddr;
3199 int status;
3200
3201 status = decode_op_hdr(xdr, OP_READLINK);
3202 if (status)
3203 return status;
3204
3205 /* Convert length of symlink */
3206 READ_BUF(4);
3207 READ32(len);
3208 if (len >= rcvbuf->page_len || len <= 0) {
3209 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
3210 return -ENAMETOOLONG;
3211 }
3212 hdrlen = (char *) xdr->p - (char *) iov->iov_base;
3213 recvd = req->rq_rcv_buf.len - hdrlen;
3214 if (recvd < len) {
3215 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
3216 "count %u > recvd %u\n", len, recvd);
3217 return -EIO;
3218 }
3219 xdr_read_pages(xdr, len);
3220 /*
3221 * The XDR encode routine has set things up so that
3222 * the link text will be copied directly into the
3223 * buffer. We just have to do overflow-checking,
3224 * and and null-terminate the text (the VFS expects
3225 * null-termination).
3226 */
3227 kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
3228 kaddr[len+rcvbuf->page_base] = '\0';
3229 kunmap_atomic(kaddr, KM_USER0);
3230 return 0;
3231}
3232
3233static int decode_remove(struct xdr_stream *xdr, struct nfs4_change_info *cinfo)
3234{
3235 int status;
3236
3237 status = decode_op_hdr(xdr, OP_REMOVE);
3238 if (status)
3239 goto out;
3240 status = decode_change_info(xdr, cinfo);
3241out:
3242 return status;
3243}
3244
3245static int decode_rename(struct xdr_stream *xdr, struct nfs4_change_info *old_cinfo,
3246 struct nfs4_change_info *new_cinfo)
3247{
3248 int status;
3249
3250 status = decode_op_hdr(xdr, OP_RENAME);
3251 if (status)
3252 goto out;
3253 if ((status = decode_change_info(xdr, old_cinfo)))
3254 goto out;
3255 status = decode_change_info(xdr, new_cinfo);
3256out:
3257 return status;
3258}
3259
3260static int decode_renew(struct xdr_stream *xdr)
3261{
3262 return decode_op_hdr(xdr, OP_RENEW);
3263}
3264
Trond Myklebust56ae19f2005-10-27 22:12:40 -04003265static int
3266decode_restorefh(struct xdr_stream *xdr)
3267{
3268 return decode_op_hdr(xdr, OP_RESTOREFH);
3269}
3270
J. Bruce Fields029d1052005-06-22 17:16:22 +00003271static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
3272 size_t *acl_len)
3273{
3274 uint32_t *savep;
3275 uint32_t attrlen,
3276 bitmap[2] = {0};
3277 struct kvec *iov = req->rq_rcv_buf.head;
3278 int status;
3279
3280 *acl_len = 0;
3281 if ((status = decode_op_hdr(xdr, OP_GETATTR)) != 0)
3282 goto out;
3283 if ((status = decode_attr_bitmap(xdr, bitmap)) != 0)
3284 goto out;
3285 if ((status = decode_attr_length(xdr, &attrlen, &savep)) != 0)
3286 goto out;
3287
3288 if (unlikely(bitmap[0] & (FATTR4_WORD0_ACL - 1U)))
3289 return -EIO;
3290 if (likely(bitmap[0] & FATTR4_WORD0_ACL)) {
3291 int hdrlen, recvd;
3292
3293 /* We ignore &savep and don't do consistency checks on
3294 * the attr length. Let userspace figure it out.... */
3295 hdrlen = (u8 *)xdr->p - (u8 *)iov->iov_base;
3296 recvd = req->rq_rcv_buf.len - hdrlen;
3297 if (attrlen > recvd) {
3298 printk(KERN_WARNING "NFS: server cheating in getattr"
3299 " acl reply: attrlen %u > recvd %u\n",
3300 attrlen, recvd);
3301 return -EINVAL;
3302 }
3303 if (attrlen <= *acl_len)
3304 xdr_read_pages(xdr, attrlen);
3305 *acl_len = attrlen;
J. Bruce Fields8c233cf2005-10-13 16:54:27 -04003306 } else
3307 status = -EOPNOTSUPP;
J. Bruce Fields029d1052005-06-22 17:16:22 +00003308
3309out:
3310 return status;
3311}
3312
Linus Torvalds1da177e2005-04-16 15:20:36 -07003313static int
3314decode_savefh(struct xdr_stream *xdr)
3315{
3316 return decode_op_hdr(xdr, OP_SAVEFH);
3317}
3318
3319static int decode_setattr(struct xdr_stream *xdr, struct nfs_setattrres *res)
3320{
3321 uint32_t *p;
3322 uint32_t bmlen;
3323 int status;
3324
3325
3326 status = decode_op_hdr(xdr, OP_SETATTR);
3327 if (status)
3328 return status;
3329 READ_BUF(4);
3330 READ32(bmlen);
3331 READ_BUF(bmlen << 2);
3332 return 0;
3333}
3334
3335static int decode_setclientid(struct xdr_stream *xdr, struct nfs4_client *clp)
3336{
3337 uint32_t *p;
3338 uint32_t opnum;
3339 int32_t nfserr;
3340
3341 READ_BUF(8);
3342 READ32(opnum);
3343 if (opnum != OP_SETCLIENTID) {
3344 printk(KERN_NOTICE
3345 "nfs4_decode_setclientid: Server returned operation"
3346 " %d\n", opnum);
3347 return -EIO;
3348 }
3349 READ32(nfserr);
3350 if (nfserr == NFS_OK) {
3351 READ_BUF(8 + sizeof(clp->cl_confirm.data));
3352 READ64(clp->cl_clientid);
3353 COPYMEM(clp->cl_confirm.data, sizeof(clp->cl_confirm.data));
3354 } else if (nfserr == NFSERR_CLID_INUSE) {
3355 uint32_t len;
3356
3357 /* skip netid string */
3358 READ_BUF(4);
3359 READ32(len);
3360 READ_BUF(len);
3361
3362 /* skip uaddr string */
3363 READ_BUF(4);
3364 READ32(len);
3365 READ_BUF(len);
3366 return -NFSERR_CLID_INUSE;
3367 } else
3368 return -nfs_stat_to_errno(nfserr);
3369
3370 return 0;
3371}
3372
3373static int decode_setclientid_confirm(struct xdr_stream *xdr)
3374{
3375 return decode_op_hdr(xdr, OP_SETCLIENTID_CONFIRM);
3376}
3377
3378static int decode_write(struct xdr_stream *xdr, struct nfs_writeres *res)
3379{
3380 uint32_t *p;
3381 int status;
3382
3383 status = decode_op_hdr(xdr, OP_WRITE);
3384 if (status)
3385 return status;
3386
3387 READ_BUF(16);
3388 READ32(res->count);
3389 READ32(res->verf->committed);
3390 COPYMEM(res->verf->verifier, 8);
3391 return 0;
3392}
3393
3394static int decode_delegreturn(struct xdr_stream *xdr)
3395{
3396 return decode_op_hdr(xdr, OP_DELEGRETURN);
3397}
3398
3399/*
3400 * Decode OPEN_DOWNGRADE response
3401 */
3402static int nfs4_xdr_dec_open_downgrade(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res)
3403{
3404 struct xdr_stream xdr;
3405 struct compound_hdr hdr;
3406 int status;
3407
3408 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3409 status = decode_compound_hdr(&xdr, &hdr);
3410 if (status)
3411 goto out;
3412 status = decode_putfh(&xdr);
3413 if (status)
3414 goto out;
3415 status = decode_open_downgrade(&xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04003416 if (status != 0)
3417 goto out;
3418 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003419out:
3420 return status;
3421}
3422
3423/*
3424 * END OF "GENERIC" DECODE ROUTINES.
3425 */
3426
3427/*
3428 * Decode ACCESS response
3429 */
3430static int nfs4_xdr_dec_access(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_accessres *res)
3431{
3432 struct xdr_stream xdr;
3433 struct compound_hdr hdr;
3434 int status;
3435
3436 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3437 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3438 goto out;
3439 if ((status = decode_putfh(&xdr)) == 0)
3440 status = decode_access(&xdr, res);
3441out:
3442 return status;
3443}
3444
3445/*
3446 * Decode LOOKUP response
3447 */
3448static int nfs4_xdr_dec_lookup(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res)
3449{
3450 struct xdr_stream xdr;
3451 struct compound_hdr hdr;
3452 int status;
3453
3454 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3455 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3456 goto out;
3457 if ((status = decode_putfh(&xdr)) != 0)
3458 goto out;
3459 if ((status = decode_lookup(&xdr)) != 0)
3460 goto out;
3461 if ((status = decode_getfh(&xdr, res->fh)) != 0)
3462 goto out;
3463 status = decode_getfattr(&xdr, res->fattr, res->server);
3464out:
3465 return status;
3466}
3467
3468/*
3469 * Decode LOOKUP_ROOT response
3470 */
3471static int nfs4_xdr_dec_lookup_root(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_lookup_res *res)
3472{
3473 struct xdr_stream xdr;
3474 struct compound_hdr hdr;
3475 int status;
3476
3477 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3478 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3479 goto out;
3480 if ((status = decode_putrootfh(&xdr)) != 0)
3481 goto out;
3482 if ((status = decode_getfh(&xdr, res->fh)) == 0)
3483 status = decode_getfattr(&xdr, res->fattr, res->server);
3484out:
3485 return status;
3486}
3487
3488/*
3489 * Decode REMOVE response
3490 */
3491static int nfs4_xdr_dec_remove(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
3492{
3493 struct xdr_stream xdr;
3494 struct compound_hdr hdr;
3495 int status;
3496
3497 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3498 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3499 goto out;
3500 if ((status = decode_putfh(&xdr)) == 0)
3501 status = decode_remove(&xdr, cinfo);
3502out:
3503 return status;
3504}
3505
3506/*
3507 * Decode RENAME response
3508 */
3509static int nfs4_xdr_dec_rename(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_rename_res *res)
3510{
3511 struct xdr_stream xdr;
3512 struct compound_hdr hdr;
3513 int status;
3514
3515 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3516 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3517 goto out;
3518 if ((status = decode_putfh(&xdr)) != 0)
3519 goto out;
3520 if ((status = decode_savefh(&xdr)) != 0)
3521 goto out;
3522 if ((status = decode_putfh(&xdr)) != 0)
3523 goto out;
3524 status = decode_rename(&xdr, &res->old_cinfo, &res->new_cinfo);
3525out:
3526 return status;
3527}
3528
3529/*
3530 * Decode LINK response
3531 */
3532static int nfs4_xdr_dec_link(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_change_info *cinfo)
3533{
3534 struct xdr_stream xdr;
3535 struct compound_hdr hdr;
3536 int status;
3537
3538 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3539 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3540 goto out;
3541 if ((status = decode_putfh(&xdr)) != 0)
3542 goto out;
3543 if ((status = decode_savefh(&xdr)) != 0)
3544 goto out;
3545 if ((status = decode_putfh(&xdr)) != 0)
3546 goto out;
3547 status = decode_link(&xdr, cinfo);
3548out:
3549 return status;
3550}
3551
3552/*
3553 * Decode CREATE response
3554 */
3555static int nfs4_xdr_dec_create(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
3556{
3557 struct xdr_stream xdr;
3558 struct compound_hdr hdr;
3559 int status;
3560
3561 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3562 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
3563 goto out;
3564 if ((status = decode_putfh(&xdr)) != 0)
3565 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04003566 if ((status = decode_savefh(&xdr)) != 0)
3567 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003568 if ((status = decode_create(&xdr,&res->dir_cinfo)) != 0)
3569 goto out;
3570 if ((status = decode_getfh(&xdr, res->fh)) != 0)
3571 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04003572 if (decode_getfattr(&xdr, res->fattr, res->server) != 0)
3573 goto out;
3574 if ((status = decode_restorefh(&xdr)) != 0)
3575 goto out;
3576 decode_getfattr(&xdr, res->dir_fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003577out:
3578 return status;
3579}
3580
3581/*
3582 * Decode SYMLINK response
3583 */
3584static int nfs4_xdr_dec_symlink(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_create_res *res)
3585{
3586 return nfs4_xdr_dec_create(rqstp, p, res);
3587}
3588
3589/*
3590 * Decode GETATTR response
3591 */
3592static int nfs4_xdr_dec_getattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_getattr_res *res)
3593{
3594 struct xdr_stream xdr;
3595 struct compound_hdr hdr;
3596 int status;
3597
3598 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3599 status = decode_compound_hdr(&xdr, &hdr);
3600 if (status)
3601 goto out;
3602 status = decode_putfh(&xdr);
3603 if (status)
3604 goto out;
3605 status = decode_getfattr(&xdr, res->fattr, res->server);
3606out:
3607 return status;
3608
3609}
3610
J. Bruce Fields23ec6962005-06-22 17:16:22 +00003611/*
3612 * Encode an SETACL request
3613 */
3614static int
3615nfs4_xdr_enc_setacl(struct rpc_rqst *req, uint32_t *p, struct nfs_setaclargs *args)
3616{
3617 struct xdr_stream xdr;
3618 struct compound_hdr hdr = {
3619 .nops = 2,
3620 };
3621 int status;
3622
3623 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
3624 encode_compound_hdr(&xdr, &hdr);
3625 status = encode_putfh(&xdr, args->fh);
3626 if (status)
3627 goto out;
3628 status = encode_setacl(&xdr, args);
3629out:
3630 return status;
3631}
3632/*
3633 * Decode SETACL response
3634 */
3635static int
3636nfs4_xdr_dec_setacl(struct rpc_rqst *rqstp, uint32_t *p, void *res)
3637{
3638 struct xdr_stream xdr;
3639 struct compound_hdr hdr;
3640 int status;
3641
3642 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3643 status = decode_compound_hdr(&xdr, &hdr);
3644 if (status)
3645 goto out;
3646 status = decode_putfh(&xdr);
3647 if (status)
3648 goto out;
3649 status = decode_setattr(&xdr, res);
3650out:
3651 return status;
3652}
Linus Torvalds1da177e2005-04-16 15:20:36 -07003653
3654/*
J. Bruce Fields029d1052005-06-22 17:16:22 +00003655 * Decode GETACL response
3656 */
3657static int
3658nfs4_xdr_dec_getacl(struct rpc_rqst *rqstp, uint32_t *p, size_t *acl_len)
3659{
3660 struct xdr_stream xdr;
3661 struct compound_hdr hdr;
3662 int status;
3663
3664 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3665 status = decode_compound_hdr(&xdr, &hdr);
3666 if (status)
3667 goto out;
3668 status = decode_putfh(&xdr);
3669 if (status)
3670 goto out;
3671 status = decode_getacl(&xdr, rqstp, acl_len);
3672
3673out:
3674 return status;
3675}
3676
3677/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07003678 * Decode CLOSE response
3679 */
3680static int nfs4_xdr_dec_close(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_closeres *res)
3681{
3682 struct xdr_stream xdr;
3683 struct compound_hdr hdr;
3684 int status;
3685
3686 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3687 status = decode_compound_hdr(&xdr, &hdr);
3688 if (status)
3689 goto out;
3690 status = decode_putfh(&xdr);
3691 if (status)
3692 goto out;
3693 status = decode_close(&xdr, res);
Trond Myklebust516a6af2005-10-27 22:12:41 -04003694 if (status != 0)
3695 goto out;
3696 /*
3697 * Note: Server may do delete on close for this file
3698 * in which case the getattr call will fail with
3699 * an ESTALE error. Shouldn't be a problem,
3700 * though, since fattr->valid will remain unset.
3701 */
3702 decode_getfattr(&xdr, res->fattr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003703out:
3704 return status;
3705}
3706
3707/*
3708 * Decode OPEN response
3709 */
3710static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
3711{
3712 struct xdr_stream xdr;
3713 struct compound_hdr hdr;
3714 int status;
3715
3716 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3717 status = decode_compound_hdr(&xdr, &hdr);
3718 if (status)
3719 goto out;
3720 status = decode_putfh(&xdr);
3721 if (status)
3722 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04003723 status = decode_savefh(&xdr);
3724 if (status)
3725 goto out;
Linus Torvalds1da177e2005-04-16 15:20:36 -07003726 status = decode_open(&xdr, res);
3727 if (status)
3728 goto out;
3729 status = decode_getfh(&xdr, &res->fh);
3730 if (status)
3731 goto out;
Trond Myklebust56ae19f2005-10-27 22:12:40 -04003732 if (decode_getfattr(&xdr, res->f_attr, res->server) != 0)
3733 goto out;
3734 if ((status = decode_restorefh(&xdr)) != 0)
3735 goto out;
3736 decode_getfattr(&xdr, res->dir_attr, res->server);
Linus Torvalds1da177e2005-04-16 15:20:36 -07003737out:
3738 return status;
3739}
3740
3741/*
3742 * Decode OPEN_CONFIRM response
3743 */
3744static int nfs4_xdr_dec_open_confirm(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_open_confirmres *res)
3745{
3746 struct xdr_stream xdr;
3747 struct compound_hdr hdr;
3748 int status;
3749
3750 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3751 status = decode_compound_hdr(&xdr, &hdr);
3752 if (status)
3753 goto out;
3754 status = decode_putfh(&xdr);
3755 if (status)
3756 goto out;
3757 status = decode_open_confirm(&xdr, res);
3758out:
3759 return status;
3760}
3761
3762/*
3763 * Decode OPEN response
3764 */
3765static int nfs4_xdr_dec_open_noattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_openres *res)
3766{
3767 struct xdr_stream xdr;
3768 struct compound_hdr hdr;
3769 int status;
3770
3771 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3772 status = decode_compound_hdr(&xdr, &hdr);
3773 if (status)
3774 goto out;
3775 status = decode_putfh(&xdr);
3776 if (status)
3777 goto out;
3778 status = decode_open(&xdr, res);
3779out:
3780 return status;
3781}
3782
3783/*
3784 * Decode SETATTR response
3785 */
3786static int nfs4_xdr_dec_setattr(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_setattrres *res)
3787{
3788 struct xdr_stream xdr;
3789 struct compound_hdr hdr;
3790 int status;
3791
3792 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3793 status = decode_compound_hdr(&xdr, &hdr);
3794 if (status)
3795 goto out;
3796 status = decode_putfh(&xdr);
3797 if (status)
3798 goto out;
3799 status = decode_setattr(&xdr, res);
3800 if (status)
3801 goto out;
3802 status = decode_getfattr(&xdr, res->fattr, res->server);
3803 if (status == NFS4ERR_DELAY)
3804 status = 0;
3805out:
3806 return status;
3807}
3808
3809/*
3810 * Decode LOCK response
3811 */
3812static int nfs4_xdr_dec_lock(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
3813{
3814 struct xdr_stream xdr;
3815 struct compound_hdr hdr;
3816 int status;
3817
3818 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3819 status = decode_compound_hdr(&xdr, &hdr);
3820 if (status)
3821 goto out;
3822 status = decode_putfh(&xdr);
3823 if (status)
3824 goto out;
3825 status = decode_lock(&xdr, res);
3826out:
3827 return status;
3828}
3829
3830/*
3831 * Decode LOCKT response
3832 */
3833static int nfs4_xdr_dec_lockt(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
3834{
3835 struct xdr_stream xdr;
3836 struct compound_hdr hdr;
3837 int status;
3838
3839 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3840 status = decode_compound_hdr(&xdr, &hdr);
3841 if (status)
3842 goto out;
3843 status = decode_putfh(&xdr);
3844 if (status)
3845 goto out;
3846 status = decode_lockt(&xdr, res);
3847out:
3848 return status;
3849}
3850
3851/*
3852 * Decode LOCKU response
3853 */
3854static int nfs4_xdr_dec_locku(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_lockres *res)
3855{
3856 struct xdr_stream xdr;
3857 struct compound_hdr hdr;
3858 int status;
3859
3860 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3861 status = decode_compound_hdr(&xdr, &hdr);
3862 if (status)
3863 goto out;
3864 status = decode_putfh(&xdr);
3865 if (status)
3866 goto out;
3867 status = decode_locku(&xdr, res);
3868out:
3869 return status;
3870}
3871
3872/*
3873 * Decode READLINK response
3874 */
3875static int nfs4_xdr_dec_readlink(struct rpc_rqst *rqstp, uint32_t *p, void *res)
3876{
3877 struct xdr_stream xdr;
3878 struct compound_hdr hdr;
3879 int status;
3880
3881 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3882 status = decode_compound_hdr(&xdr, &hdr);
3883 if (status)
3884 goto out;
3885 status = decode_putfh(&xdr);
3886 if (status)
3887 goto out;
3888 status = decode_readlink(&xdr, rqstp);
3889out:
3890 return status;
3891}
3892
3893/*
3894 * Decode READDIR response
3895 */
3896static int nfs4_xdr_dec_readdir(struct rpc_rqst *rqstp, uint32_t *p, struct nfs4_readdir_res *res)
3897{
3898 struct xdr_stream xdr;
3899 struct compound_hdr hdr;
3900 int status;
3901
3902 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3903 status = decode_compound_hdr(&xdr, &hdr);
3904 if (status)
3905 goto out;
3906 status = decode_putfh(&xdr);
3907 if (status)
3908 goto out;
3909 status = decode_readdir(&xdr, rqstp, res);
3910out:
3911 return status;
3912}
3913
3914/*
3915 * Decode Read response
3916 */
3917static int nfs4_xdr_dec_read(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_readres *res)
3918{
3919 struct xdr_stream xdr;
3920 struct compound_hdr hdr;
3921 int status;
3922
3923 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3924 status = decode_compound_hdr(&xdr, &hdr);
3925 if (status)
3926 goto out;
3927 status = decode_putfh(&xdr);
3928 if (status)
3929 goto out;
3930 status = decode_read(&xdr, rqstp, res);
3931 if (!status)
3932 status = res->count;
3933out:
3934 return status;
3935}
3936
3937/*
3938 * Decode WRITE response
3939 */
3940static int nfs4_xdr_dec_write(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res)
3941{
3942 struct xdr_stream xdr;
3943 struct compound_hdr hdr;
3944 int status;
3945
3946 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3947 status = decode_compound_hdr(&xdr, &hdr);
3948 if (status)
3949 goto out;
3950 status = decode_putfh(&xdr);
3951 if (status)
3952 goto out;
3953 status = decode_write(&xdr, res);
3954 if (!status)
3955 status = res->count;
3956out:
3957 return status;
3958}
3959
3960/*
3961 * Decode COMMIT response
3962 */
3963static int nfs4_xdr_dec_commit(struct rpc_rqst *rqstp, uint32_t *p, struct nfs_writeres *res)
3964{
3965 struct xdr_stream xdr;
3966 struct compound_hdr hdr;
3967 int status;
3968
3969 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
3970 status = decode_compound_hdr(&xdr, &hdr);
3971 if (status)
3972 goto out;
3973 status = decode_putfh(&xdr);
3974 if (status)
3975 goto out;
3976 status = decode_commit(&xdr, res);
3977out:
3978 return status;
3979}
3980
3981/*
3982 * FSINFO request
3983 */
3984static int nfs4_xdr_dec_fsinfo(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo)
3985{
3986 struct xdr_stream xdr;
3987 struct compound_hdr hdr;
3988 int status;
3989
3990 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
3991 status = decode_compound_hdr(&xdr, &hdr);
3992 if (!status)
3993 status = decode_putfh(&xdr);
3994 if (!status)
3995 status = decode_fsinfo(&xdr, fsinfo);
3996 if (!status)
3997 status = -nfs_stat_to_errno(hdr.status);
3998 return status;
3999}
4000
4001/*
4002 * PATHCONF request
4003 */
4004static int nfs4_xdr_dec_pathconf(struct rpc_rqst *req, uint32_t *p, struct nfs_pathconf *pathconf)
4005{
4006 struct xdr_stream xdr;
4007 struct compound_hdr hdr;
4008 int status;
4009
4010 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4011 status = decode_compound_hdr(&xdr, &hdr);
4012 if (!status)
4013 status = decode_putfh(&xdr);
4014 if (!status)
4015 status = decode_pathconf(&xdr, pathconf);
4016 return status;
4017}
4018
4019/*
4020 * STATFS request
4021 */
4022static int nfs4_xdr_dec_statfs(struct rpc_rqst *req, uint32_t *p, struct nfs_fsstat *fsstat)
4023{
4024 struct xdr_stream xdr;
4025 struct compound_hdr hdr;
4026 int status;
4027
4028 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4029 status = decode_compound_hdr(&xdr, &hdr);
4030 if (!status)
4031 status = decode_putfh(&xdr);
4032 if (!status)
4033 status = decode_statfs(&xdr, fsstat);
4034 return status;
4035}
4036
4037/*
4038 * GETATTR_BITMAP request
4039 */
4040static int nfs4_xdr_dec_server_caps(struct rpc_rqst *req, uint32_t *p, struct nfs4_server_caps_res *res)
4041{
4042 struct xdr_stream xdr;
4043 struct compound_hdr hdr;
4044 int status;
4045
4046 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4047 if ((status = decode_compound_hdr(&xdr, &hdr)) != 0)
4048 goto out;
4049 if ((status = decode_putfh(&xdr)) != 0)
4050 goto out;
4051 status = decode_server_caps(&xdr, res);
4052out:
4053 return status;
4054}
4055
4056/*
4057 * Decode RENEW response
4058 */
4059static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
4060{
4061 struct xdr_stream xdr;
4062 struct compound_hdr hdr;
4063 int status;
4064
4065 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4066 status = decode_compound_hdr(&xdr, &hdr);
4067 if (!status)
4068 status = decode_renew(&xdr);
4069 return status;
4070}
4071
4072/*
4073 * a SETCLIENTID request
4074 */
4075static int nfs4_xdr_dec_setclientid(struct rpc_rqst *req, uint32_t *p,
4076 struct nfs4_client *clp)
4077{
4078 struct xdr_stream xdr;
4079 struct compound_hdr hdr;
4080 int status;
4081
4082 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4083 status = decode_compound_hdr(&xdr, &hdr);
4084 if (!status)
4085 status = decode_setclientid(&xdr, clp);
4086 if (!status)
4087 status = -nfs_stat_to_errno(hdr.status);
4088 return status;
4089}
4090
4091/*
4092 * a SETCLIENTID_CONFIRM request
4093 */
4094static int nfs4_xdr_dec_setclientid_confirm(struct rpc_rqst *req, uint32_t *p, struct nfs_fsinfo *fsinfo)
4095{
4096 struct xdr_stream xdr;
4097 struct compound_hdr hdr;
4098 int status;
4099
4100 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
4101 status = decode_compound_hdr(&xdr, &hdr);
4102 if (!status)
4103 status = decode_setclientid_confirm(&xdr);
4104 if (!status)
4105 status = decode_putrootfh(&xdr);
4106 if (!status)
4107 status = decode_fsinfo(&xdr, fsinfo);
4108 if (!status)
4109 status = -nfs_stat_to_errno(hdr.status);
4110 return status;
4111}
4112
4113/*
4114 * DELEGRETURN request
4115 */
4116static int nfs4_xdr_dec_delegreturn(struct rpc_rqst *rqstp, uint32_t *p, void *dummy)
4117{
4118 struct xdr_stream xdr;
4119 struct compound_hdr hdr;
4120 int status;
4121
4122 xdr_init_decode(&xdr, &rqstp->rq_rcv_buf, p);
4123 status = decode_compound_hdr(&xdr, &hdr);
4124 if (status == 0) {
4125 status = decode_putfh(&xdr);
4126 if (status == 0)
4127 status = decode_delegreturn(&xdr);
4128 }
4129 return status;
4130}
4131
4132uint32_t *nfs4_decode_dirent(uint32_t *p, struct nfs_entry *entry, int plus)
4133{
4134 uint32_t bitmap[2] = {0};
4135 uint32_t len;
4136
4137 if (!*p++) {
4138 if (!*p)
4139 return ERR_PTR(-EAGAIN);
4140 entry->eof = 1;
4141 return ERR_PTR(-EBADCOOKIE);
4142 }
4143
4144 entry->prev_cookie = entry->cookie;
4145 p = xdr_decode_hyper(p, &entry->cookie);
4146 entry->len = ntohl(*p++);
4147 entry->name = (const char *) p;
4148 p += XDR_QUADLEN(entry->len);
4149
4150 /*
4151 * In case the server doesn't return an inode number,
4152 * we fake one here. (We don't use inode number 0,
4153 * since glibc seems to choke on it...)
4154 */
4155 entry->ino = 1;
4156
4157 len = ntohl(*p++); /* bitmap length */
4158 if (len-- > 0) {
4159 bitmap[0] = ntohl(*p++);
4160 if (len-- > 0) {
4161 bitmap[1] = ntohl(*p++);
4162 p += len;
4163 }
4164 }
4165 len = XDR_QUADLEN(ntohl(*p++)); /* attribute buffer length */
4166 if (len > 0) {
Manoj Naik97d312d2005-06-22 17:16:39 +00004167 if (bitmap[0] & FATTR4_WORD0_RDATTR_ERROR) {
4168 bitmap[0] &= ~FATTR4_WORD0_RDATTR_ERROR;
4169 /* Ignore the return value of rdattr_error for now */
4170 p++;
4171 len--;
4172 }
Linus Torvalds1da177e2005-04-16 15:20:36 -07004173 if (bitmap[0] == 0 && bitmap[1] == FATTR4_WORD1_MOUNTED_ON_FILEID)
4174 xdr_decode_hyper(p, &entry->ino);
4175 else if (bitmap[0] == FATTR4_WORD0_FILEID)
4176 xdr_decode_hyper(p, &entry->ino);
4177 p += len;
4178 }
4179
4180 entry->eof = !p[0] && p[1];
4181 return p;
4182}
4183
4184/*
4185 * We need to translate between nfs status return values and
4186 * the local errno values which may not be the same.
4187 */
4188static struct {
4189 int stat;
4190 int errno;
4191} nfs_errtbl[] = {
4192 { NFS4_OK, 0 },
4193 { NFS4ERR_PERM, EPERM },
4194 { NFS4ERR_NOENT, ENOENT },
4195 { NFS4ERR_IO, errno_NFSERR_IO },
4196 { NFS4ERR_NXIO, ENXIO },
4197 { NFS4ERR_ACCESS, EACCES },
4198 { NFS4ERR_EXIST, EEXIST },
4199 { NFS4ERR_XDEV, EXDEV },
4200 { NFS4ERR_NOTDIR, ENOTDIR },
4201 { NFS4ERR_ISDIR, EISDIR },
4202 { NFS4ERR_INVAL, EINVAL },
4203 { NFS4ERR_FBIG, EFBIG },
4204 { NFS4ERR_NOSPC, ENOSPC },
4205 { NFS4ERR_ROFS, EROFS },
4206 { NFS4ERR_MLINK, EMLINK },
4207 { NFS4ERR_NAMETOOLONG, ENAMETOOLONG },
4208 { NFS4ERR_NOTEMPTY, ENOTEMPTY },
4209 { NFS4ERR_DQUOT, EDQUOT },
4210 { NFS4ERR_STALE, ESTALE },
4211 { NFS4ERR_BADHANDLE, EBADHANDLE },
Manoj Naik6ebf3652005-06-22 17:16:39 +00004212 { NFS4ERR_BADOWNER, EINVAL },
4213 { NFS4ERR_BADNAME, EINVAL },
Linus Torvalds1da177e2005-04-16 15:20:36 -07004214 { NFS4ERR_BAD_COOKIE, EBADCOOKIE },
4215 { NFS4ERR_NOTSUPP, ENOTSUPP },
4216 { NFS4ERR_TOOSMALL, ETOOSMALL },
4217 { NFS4ERR_SERVERFAULT, ESERVERFAULT },
4218 { NFS4ERR_BADTYPE, EBADTYPE },
4219 { NFS4ERR_LOCKED, EAGAIN },
4220 { NFS4ERR_RESOURCE, EREMOTEIO },
4221 { NFS4ERR_SYMLINK, ELOOP },
4222 { NFS4ERR_OP_ILLEGAL, EOPNOTSUPP },
4223 { NFS4ERR_DEADLOCK, EDEADLK },
4224 { NFS4ERR_WRONGSEC, EPERM }, /* FIXME: this needs
4225 * to be handled by a
4226 * middle-layer.
4227 */
4228 { -1, EIO }
4229};
4230
4231/*
4232 * Convert an NFS error code to a local one.
4233 * This one is used jointly by NFSv2 and NFSv3.
4234 */
4235static int
4236nfs_stat_to_errno(int stat)
4237{
4238 int i;
4239 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
4240 if (nfs_errtbl[i].stat == stat)
4241 return nfs_errtbl[i].errno;
4242 }
4243 if (stat <= 10000 || stat > 10100) {
4244 /* The server is looney tunes. */
4245 return ESERVERFAULT;
4246 }
4247 /* If we cannot translate the error, the recovery routines should
4248 * handle it.
4249 * Note: remaining NFSv4 error codes have values > 10000, so should
4250 * not conflict with native Linux error codes.
4251 */
4252 return stat;
4253}
4254
4255#ifndef MAX
4256# define MAX(a, b) (((a) > (b))? (a) : (b))
4257#endif
4258
4259#define PROC(proc, argtype, restype) \
4260[NFSPROC4_CLNT_##proc] = { \
4261 .p_proc = NFSPROC4_COMPOUND, \
4262 .p_encode = (kxdrproc_t) nfs4_xdr_##argtype, \
4263 .p_decode = (kxdrproc_t) nfs4_xdr_##restype, \
4264 .p_bufsiz = MAX(NFS4_##argtype##_sz,NFS4_##restype##_sz) << 2, \
4265 }
4266
4267struct rpc_procinfo nfs4_procedures[] = {
4268 PROC(READ, enc_read, dec_read),
4269 PROC(WRITE, enc_write, dec_write),
4270 PROC(COMMIT, enc_commit, dec_commit),
4271 PROC(OPEN, enc_open, dec_open),
4272 PROC(OPEN_CONFIRM, enc_open_confirm, dec_open_confirm),
4273 PROC(OPEN_NOATTR, enc_open_noattr, dec_open_noattr),
4274 PROC(OPEN_DOWNGRADE, enc_open_downgrade, dec_open_downgrade),
4275 PROC(CLOSE, enc_close, dec_close),
4276 PROC(SETATTR, enc_setattr, dec_setattr),
4277 PROC(FSINFO, enc_fsinfo, dec_fsinfo),
4278 PROC(RENEW, enc_renew, dec_renew),
4279 PROC(SETCLIENTID, enc_setclientid, dec_setclientid),
4280 PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm),
4281 PROC(LOCK, enc_lock, dec_lock),
4282 PROC(LOCKT, enc_lockt, dec_lockt),
4283 PROC(LOCKU, enc_locku, dec_locku),
4284 PROC(ACCESS, enc_access, dec_access),
4285 PROC(GETATTR, enc_getattr, dec_getattr),
4286 PROC(LOOKUP, enc_lookup, dec_lookup),
4287 PROC(LOOKUP_ROOT, enc_lookup_root, dec_lookup_root),
4288 PROC(REMOVE, enc_remove, dec_remove),
4289 PROC(RENAME, enc_rename, dec_rename),
4290 PROC(LINK, enc_link, dec_link),
4291 PROC(SYMLINK, enc_symlink, dec_symlink),
4292 PROC(CREATE, enc_create, dec_create),
4293 PROC(PATHCONF, enc_pathconf, dec_pathconf),
4294 PROC(STATFS, enc_statfs, dec_statfs),
4295 PROC(READLINK, enc_readlink, dec_readlink),
4296 PROC(READDIR, enc_readdir, dec_readdir),
4297 PROC(SERVER_CAPS, enc_server_caps, dec_server_caps),
4298 PROC(DELEGRETURN, enc_delegreturn, dec_delegreturn),
J. Bruce Fields029d1052005-06-22 17:16:22 +00004299 PROC(GETACL, enc_getacl, dec_getacl),
J. Bruce Fields23ec6962005-06-22 17:16:22 +00004300 PROC(SETACL, enc_setacl, dec_setacl),
Linus Torvalds1da177e2005-04-16 15:20:36 -07004301};
4302
4303struct rpc_version nfs_version4 = {
4304 .number = 4,
4305 .nrprocs = sizeof(nfs4_procedures)/sizeof(nfs4_procedures[0]),
4306 .procs = nfs4_procedures
4307};
4308
4309/*
4310 * Local variables:
4311 * c-basic-offset: 8
4312 * End:
4313 */