blob: c97d00fe849a826b93b226122580d7d086046298 [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * linux/fs/nfs/nfs3xdr.c
3 *
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
5 *
6 * Copyright (C) 1996, 1997 Olaf Kirch
7 */
8
9#include <linux/param.h>
10#include <linux/time.h>
11#include <linux/mm.h>
Linus Torvalds1da177e2005-04-16 15:20:36 -070012#include <linux/errno.h>
13#include <linux/string.h>
14#include <linux/in.h>
15#include <linux/pagemap.h>
16#include <linux/proc_fs.h>
17#include <linux/kdev_t.h>
18#include <linux/sunrpc/clnt.h>
19#include <linux/nfs.h>
20#include <linux/nfs3.h>
21#include <linux/nfs_fs.h>
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +000022#include <linux/nfsacl.h>
David Howellsf7b422b2006-06-09 09:34:33 -040023#include "internal.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070024
25#define NFSDBG_FACILITY NFSDBG_XDR
26
27/* Mapping from NFS error code to "errno" error code. */
28#define errno_NFSERR_IO EIO
29
Linus Torvalds1da177e2005-04-16 15:20:36 -070030/*
31 * Declare the space requirements for NFS arguments and replies as
32 * number of 32bit-words
33 */
34#define NFS3_fhandle_sz (1+16)
35#define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
36#define NFS3_sattr_sz (15)
37#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
38#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
39#define NFS3_fattr_sz (21)
Chuck Leverd9c407b2010-12-14 14:55:50 +000040#define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
Chuck Leverf5fc3c502010-12-14 14:56:42 +000041#define NFS3_wcc_attr_sz (6)
Linus Torvalds1da177e2005-04-16 15:20:36 -070042#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
Chuck Leverf5fc3c502010-12-14 14:56:42 +000044#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
Chuck Leverad96b5b2010-12-14 14:56:01 +000046
47#define NFS3_getattrargs_sz (NFS3_fh_sz)
48#define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
49#define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070050#define NFS3_accessargs_sz (NFS3_fh_sz+1)
51#define NFS3_readlinkargs_sz (NFS3_fh_sz)
52#define NFS3_readargs_sz (NFS3_fh_sz+3)
53#define NFS3_writeargs_sz (NFS3_fh_sz+5)
54#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
55#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
Chuck Lever94a6d752006-08-22 20:06:23 -040056#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070057#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
Chuck Leverad96b5b2010-12-14 14:56:01 +000058#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070059#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
60#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
Chuck Leverd9c407b2010-12-14 14:55:50 +000061#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
Linus Torvalds1da177e2005-04-16 15:20:36 -070063#define NFS3_commitargs_sz (NFS3_fh_sz+3)
64
Chuck Leverf5fc3c502010-12-14 14:56:42 +000065#define NFS3_getattrres_sz (1+NFS3_fattr_sz)
66#define NFS3_setattrres_sz (1+NFS3_wcc_data_sz)
67#define NFS3_removeres_sz (NFS3_setattrres_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070068#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
70#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
71#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
72#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
73#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
74#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
75#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
77#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
78#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
79#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
80#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
81
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +000082#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
Trond Myklebustae46141f2009-03-10 20:33:18 -040083#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
84 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
85#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +000087#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
88
Linus Torvalds1da177e2005-04-16 15:20:36 -070089/*
90 * Map file type to S_IFMT bits
91 */
Trond Myklebustbca79472009-03-11 14:10:26 -040092static const umode_t nfs_type2fmt[] = {
93 [NF3BAD] = 0,
94 [NF3REG] = S_IFREG,
95 [NF3DIR] = S_IFDIR,
96 [NF3BLK] = S_IFBLK,
97 [NF3CHR] = S_IFCHR,
98 [NF3LNK] = S_IFLNK,
99 [NF3SOCK] = S_IFSOCK,
100 [NF3FIFO] = S_IFIFO,
Linus Torvalds1da177e2005-04-16 15:20:36 -0700101};
102
103/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000104 * While encoding arguments, set up the reply buffer in advance to
105 * receive reply data directly into the page cache.
106 */
107static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
108 unsigned int base, unsigned int len,
109 unsigned int bufsize)
110{
111 struct rpc_auth *auth = req->rq_cred->cr_auth;
112 unsigned int replen;
113
114 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
115 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
116}
117
Chuck Levere4f93232010-12-14 14:56:30 +0000118/*
119 * Handle decode buffer overflows out-of-line.
120 */
121static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
122{
123 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
124 "Remaining buffer length is %tu words.\n",
125 func, xdr->end - xdr->p);
126}
127
Chuck Leverd9c407b2010-12-14 14:55:50 +0000128
129/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000130 * Encode/decode NFSv3 basic data types
131 *
132 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
133 * "NFS Version 3 Protocol Specification".
134 *
135 * Not all basic data types have their own encoding and decoding
136 * functions. For run-time efficiency, some data types are encoded
137 * or decoded inline.
138 */
139
140static void encode_uint32(struct xdr_stream *xdr, u32 value)
141{
142 __be32 *p = xdr_reserve_space(xdr, 4);
143 *p = cpu_to_be32(value);
144}
145
Chuck Levere4f93232010-12-14 14:56:30 +0000146static int decode_uint32(struct xdr_stream *xdr, u32 *value)
147{
148 __be32 *p;
149
150 p = xdr_inline_decode(xdr, 4);
151 if (unlikely(p == NULL))
152 goto out_overflow;
153 *value = be32_to_cpup(p);
154 return 0;
155out_overflow:
156 print_overflow_msg(__func__, xdr);
157 return -EIO;
158}
159
160static int decode_uint64(struct xdr_stream *xdr, u64 *value)
161{
162 __be32 *p;
163
164 p = xdr_inline_decode(xdr, 8);
165 if (unlikely(p == NULL))
166 goto out_overflow;
167 xdr_decode_hyper(p, value);
168 return 0;
169out_overflow:
170 print_overflow_msg(__func__, xdr);
171 return -EIO;
172}
173
174/*
175 * fileid3
176 *
177 * typedef uint64 fileid3;
178 */
Chuck Leverf6048702010-12-14 14:57:02 +0000179static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
180{
181 return xdr_decode_hyper(p, fileid);
182}
183
Chuck Levere4f93232010-12-14 14:56:30 +0000184static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
185{
186 return decode_uint64(xdr, fileid);
187}
188
Chuck Leverd9c407b2010-12-14 14:55:50 +0000189/*
190 * filename3
191 *
192 * typedef string filename3<>;
193 */
194static void encode_filename3(struct xdr_stream *xdr,
195 const char *name, u32 length)
196{
197 __be32 *p;
198
199 BUG_ON(length > NFS3_MAXNAMLEN);
200 p = xdr_reserve_space(xdr, 4 + length);
201 xdr_encode_opaque(p, name, length);
202}
203
Chuck Levere4f93232010-12-14 14:56:30 +0000204static int decode_inline_filename3(struct xdr_stream *xdr,
205 const char **name, u32 *length)
206{
207 __be32 *p;
208 u32 count;
209
210 p = xdr_inline_decode(xdr, 4);
211 if (unlikely(p == NULL))
212 goto out_overflow;
213 count = be32_to_cpup(p);
214 if (count > NFS3_MAXNAMLEN)
215 goto out_nametoolong;
216 p = xdr_inline_decode(xdr, count);
217 if (unlikely(p == NULL))
218 goto out_overflow;
219 *name = (const char *)p;
220 *length = count;
221 return 0;
222
223out_nametoolong:
224 dprintk("NFS: returned filename too long: %u\n", count);
225 return -ENAMETOOLONG;
226out_overflow:
227 print_overflow_msg(__func__, xdr);
228 return -EIO;
229}
230
Chuck Leverd9c407b2010-12-14 14:55:50 +0000231/*
232 * nfspath3
233 *
234 * typedef string nfspath3<>;
235 */
236static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
237 const u32 length)
238{
239 BUG_ON(length > NFS3_MAXPATHLEN);
240 encode_uint32(xdr, length);
241 xdr_write_pages(xdr, pages, 0, length);
242}
243
Chuck Levere4f93232010-12-14 14:56:30 +0000244static int decode_nfspath3(struct xdr_stream *xdr)
245{
246 u32 recvd, count;
247 size_t hdrlen;
248 __be32 *p;
249
250 p = xdr_inline_decode(xdr, 4);
251 if (unlikely(p == NULL))
252 goto out_overflow;
253 count = be32_to_cpup(p);
254 if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
255 goto out_nametoolong;
256 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
257 recvd = xdr->buf->len - hdrlen;
258 if (unlikely(count > recvd))
259 goto out_cheating;
260
261 xdr_read_pages(xdr, count);
262 xdr_terminate_string(xdr->buf, count);
263 return 0;
264
265out_nametoolong:
266 dprintk("NFS: returned pathname too long: %u\n", count);
267 return -ENAMETOOLONG;
268out_cheating:
269 dprintk("NFS: server cheating in pathname result: "
270 "count %u > recvd %u\n", count, recvd);
271 return -EIO;
272out_overflow:
273 print_overflow_msg(__func__, xdr);
274 return -EIO;
275}
276
Chuck Leverd9c407b2010-12-14 14:55:50 +0000277/*
278 * cookie3
279 *
280 * typedef uint64 cookie3
281 */
282static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
283{
284 return xdr_encode_hyper(p, cookie);
285}
286
Chuck Levere4f93232010-12-14 14:56:30 +0000287static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
288{
289 return decode_uint64(xdr, cookie);
290}
291
Chuck Leverd9c407b2010-12-14 14:55:50 +0000292/*
293 * cookieverf3
294 *
295 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
296 */
297static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
298{
299 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
300 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
301}
302
Chuck Levere4f93232010-12-14 14:56:30 +0000303static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
304{
305 __be32 *p;
306
307 p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
308 if (unlikely(p == NULL))
309 goto out_overflow;
310 memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
311 return 0;
312out_overflow:
313 print_overflow_msg(__func__, xdr);
314 return -EIO;
315}
316
Chuck Leverd9c407b2010-12-14 14:55:50 +0000317/*
318 * createverf3
319 *
320 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
321 */
322static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
323{
324 __be32 *p;
325
326 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
327 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
328}
329
Chuck Levere4f93232010-12-14 14:56:30 +0000330static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
331{
332 __be32 *p;
333
334 p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
335 if (unlikely(p == NULL))
336 goto out_overflow;
337 memcpy(verifier, p, NFS3_WRITEVERFSIZE);
338 return 0;
339out_overflow:
340 print_overflow_msg(__func__, xdr);
341 return -EIO;
342}
343
344/*
345 * size3
346 *
347 * typedef uint64 size3;
348 */
349static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
350{
351 return xdr_decode_hyper(p, size);
352}
353
354/*
355 * nfsstat3
356 *
357 * enum nfsstat3 {
358 * NFS3_OK = 0,
359 * ...
360 * }
361 */
362#define NFS3_OK NFS_OK
363
364static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
365{
366 __be32 *p;
367
368 p = xdr_inline_decode(xdr, 4);
369 if (unlikely(p == NULL))
370 goto out_overflow;
371 *status = be32_to_cpup(p);
372 return 0;
373out_overflow:
374 print_overflow_msg(__func__, xdr);
375 return -EIO;
376}
377
Chuck Leverd9c407b2010-12-14 14:55:50 +0000378/*
379 * ftype3
380 *
381 * enum ftype3 {
382 * NF3REG = 1,
383 * NF3DIR = 2,
384 * NF3BLK = 3,
385 * NF3CHR = 4,
386 * NF3LNK = 5,
387 * NF3SOCK = 6,
388 * NF3FIFO = 7
389 * };
390 */
391static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
392{
393 BUG_ON(type > NF3FIFO);
394 encode_uint32(xdr, type);
395}
396
Chuck Leverf6048702010-12-14 14:57:02 +0000397static __be32 *xdr_decode_ftype3(__be32 *p, umode_t *mode)
398{
399 u32 type;
400
401 type = be32_to_cpup(p++);
402 if (type > NF3FIFO)
403 type = NF3NON;
404 *mode = nfs_type2fmt[type];
405 return p;
406}
407
Chuck Leverd9c407b2010-12-14 14:55:50 +0000408/*
409 * specdata3
410 *
411 * struct specdata3 {
412 * uint32 specdata1;
413 * uint32 specdata2;
414 * };
415 */
416static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
417{
418 __be32 *p;
419
420 p = xdr_reserve_space(xdr, 8);
421 *p++ = cpu_to_be32(MAJOR(rdev));
422 *p = cpu_to_be32(MINOR(rdev));
423}
424
Chuck Leverf6048702010-12-14 14:57:02 +0000425static __be32 *xdr_decode_specdata3(__be32 *p, dev_t *rdev)
426{
427 unsigned int major, minor;
428
429 major = be32_to_cpup(p++);
430 minor = be32_to_cpup(p++);
431 *rdev = MKDEV(major, minor);
432 if (MAJOR(*rdev) != major || MINOR(*rdev) != minor)
433 *rdev = 0;
434 return p;
435}
436
Chuck Leverd9c407b2010-12-14 14:55:50 +0000437/*
438 * nfs_fh3
439 *
440 * struct nfs_fh3 {
441 * opaque data<NFS3_FHSIZE>;
442 * };
443 */
444static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
445{
446 __be32 *p;
447
448 BUG_ON(fh->size > NFS3_FHSIZE);
449 p = xdr_reserve_space(xdr, 4 + fh->size);
450 xdr_encode_opaque(p, fh->data, fh->size);
451}
452
Chuck Levere4f93232010-12-14 14:56:30 +0000453static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
454{
455 u32 length;
456 __be32 *p;
457
458 p = xdr_inline_decode(xdr, 4);
459 if (unlikely(p == NULL))
460 goto out_overflow;
461 length = be32_to_cpup(p++);
462 if (unlikely(length > NFS3_FHSIZE))
463 goto out_toobig;
464 p = xdr_inline_decode(xdr, length);
465 if (unlikely(p == NULL))
466 goto out_overflow;
467 fh->size = length;
468 memcpy(fh->data, p, length);
469 return 0;
470out_toobig:
471 dprintk("NFS: file handle size (%u) too big\n", length);
472 return -E2BIG;
473out_overflow:
474 print_overflow_msg(__func__, xdr);
475 return -EIO;
476}
477
478static void zero_nfs_fh3(struct nfs_fh *fh)
479{
480 memset(fh, 0, sizeof(*fh));
481}
482
Chuck Leverd9c407b2010-12-14 14:55:50 +0000483/*
Chuck Lever9d5a6432010-12-14 14:56:20 +0000484 * nfstime3
485 *
486 * struct nfstime3 {
487 * uint32 seconds;
488 * uint32 nseconds;
489 * };
490 */
491static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
492{
493 *p++ = cpu_to_be32(timep->tv_sec);
494 *p++ = cpu_to_be32(timep->tv_nsec);
495 return p;
496}
497
Chuck Leverf6048702010-12-14 14:57:02 +0000498static __be32 *xdr_decode_nfstime3(__be32 *p, struct timespec *timep)
499{
500 timep->tv_sec = be32_to_cpup(p++);
501 timep->tv_nsec = be32_to_cpup(p++);
502 return p;
503}
504
Chuck Lever9d5a6432010-12-14 14:56:20 +0000505/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000506 * sattr3
507 *
508 * enum time_how {
509 * DONT_CHANGE = 0,
510 * SET_TO_SERVER_TIME = 1,
511 * SET_TO_CLIENT_TIME = 2
512 * };
513 *
514 * union set_mode3 switch (bool set_it) {
515 * case TRUE:
516 * mode3 mode;
517 * default:
518 * void;
519 * };
520 *
521 * union set_uid3 switch (bool set_it) {
522 * case TRUE:
523 * uid3 uid;
524 * default:
525 * void;
526 * };
527 *
528 * union set_gid3 switch (bool set_it) {
529 * case TRUE:
530 * gid3 gid;
531 * default:
532 * void;
533 * };
534 *
535 * union set_size3 switch (bool set_it) {
536 * case TRUE:
537 * size3 size;
538 * default:
539 * void;
540 * };
541 *
542 * union set_atime switch (time_how set_it) {
543 * case SET_TO_CLIENT_TIME:
544 * nfstime3 atime;
545 * default:
546 * void;
547 * };
548 *
549 * union set_mtime switch (time_how set_it) {
550 * case SET_TO_CLIENT_TIME:
551 * nfstime3 mtime;
552 * default:
553 * void;
554 * };
555 *
556 * struct sattr3 {
557 * set_mode3 mode;
558 * set_uid3 uid;
559 * set_gid3 gid;
560 * set_size3 size;
561 * set_atime atime;
562 * set_mtime mtime;
563 * };
564 */
565static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
566{
567 u32 nbytes;
568 __be32 *p;
569
570 /*
571 * In order to make only a single xdr_reserve_space() call,
572 * pre-compute the total number of bytes to be reserved.
573 * Six boolean values, one for each set_foo field, are always
574 * present in the encoded result, so start there.
575 */
576 nbytes = 6 * 4;
577 if (attr->ia_valid & ATTR_MODE)
578 nbytes += 4;
579 if (attr->ia_valid & ATTR_UID)
580 nbytes += 4;
581 if (attr->ia_valid & ATTR_GID)
582 nbytes += 4;
583 if (attr->ia_valid & ATTR_SIZE)
584 nbytes += 8;
585 if (attr->ia_valid & ATTR_ATIME_SET)
586 nbytes += 8;
587 if (attr->ia_valid & ATTR_MTIME_SET)
588 nbytes += 8;
589 p = xdr_reserve_space(xdr, nbytes);
590
Chuck Lever9d5a6432010-12-14 14:56:20 +0000591 if (attr->ia_valid & ATTR_MODE) {
592 *p++ = xdr_one;
593 *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
594 } else
595 *p++ = xdr_zero;
596
597 if (attr->ia_valid & ATTR_UID) {
598 *p++ = xdr_one;
599 *p++ = cpu_to_be32(attr->ia_uid);
600 } else
601 *p++ = xdr_zero;
602
603 if (attr->ia_valid & ATTR_GID) {
604 *p++ = xdr_one;
605 *p++ = cpu_to_be32(attr->ia_gid);
606 } else
607 *p++ = xdr_zero;
608
609 if (attr->ia_valid & ATTR_SIZE) {
610 *p++ = xdr_one;
611 p = xdr_encode_hyper(p, (u64)attr->ia_size);
612 } else
613 *p++ = xdr_zero;
614
615 if (attr->ia_valid & ATTR_ATIME_SET) {
616 *p++ = xdr_two;
617 p = xdr_encode_nfstime3(p, &attr->ia_atime);
618 } else if (attr->ia_valid & ATTR_ATIME) {
619 *p++ = xdr_one;
620 } else
621 *p++ = xdr_zero;
622
623 if (attr->ia_valid & ATTR_MTIME_SET) {
624 *p++ = xdr_two;
625 xdr_encode_nfstime3(p, &attr->ia_mtime);
626 } else if (attr->ia_valid & ATTR_MTIME) {
627 *p = xdr_one;
628 } else
629 *p = xdr_zero;
Chuck Leverd9c407b2010-12-14 14:55:50 +0000630}
631
632/*
Chuck Levere4f93232010-12-14 14:56:30 +0000633 * fattr3
634 *
635 * struct fattr3 {
636 * ftype3 type;
637 * mode3 mode;
638 * uint32 nlink;
639 * uid3 uid;
640 * gid3 gid;
641 * size3 size;
642 * size3 used;
643 * specdata3 rdev;
644 * uint64 fsid;
645 * fileid3 fileid;
646 * nfstime3 atime;
647 * nfstime3 mtime;
648 * nfstime3 ctime;
649 * };
650 */
651static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
652{
Chuck Leverf6048702010-12-14 14:57:02 +0000653 umode_t fmode;
Chuck Levere4f93232010-12-14 14:56:30 +0000654 __be32 *p;
655
656 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
657 if (unlikely(p == NULL))
658 goto out_overflow;
Chuck Leverf6048702010-12-14 14:57:02 +0000659
660 p = xdr_decode_ftype3(p, &fmode);
661
662 fattr->mode = (be32_to_cpup(p++) & ~S_IFMT) | fmode;
663 fattr->nlink = be32_to_cpup(p++);
664 fattr->uid = be32_to_cpup(p++);
665 fattr->gid = be32_to_cpup(p++);
666
667 p = xdr_decode_size3(p, &fattr->size);
668 p = xdr_decode_size3(p, &fattr->du.nfs3.used);
669 p = xdr_decode_specdata3(p, &fattr->rdev);
670
671 p = xdr_decode_hyper(p, &fattr->fsid.major);
672 fattr->fsid.minor = 0;
673
674 p = xdr_decode_fileid3(p, &fattr->fileid);
675 p = xdr_decode_nfstime3(p, &fattr->atime);
676 p = xdr_decode_nfstime3(p, &fattr->mtime);
677 xdr_decode_nfstime3(p, &fattr->ctime);
678
679 fattr->valid |= NFS_ATTR_FATTR_V3;
Chuck Levere4f93232010-12-14 14:56:30 +0000680 return 0;
681out_overflow:
682 print_overflow_msg(__func__, xdr);
683 return -EIO;
684}
685
686/*
687 * post_op_attr
688 *
689 * union post_op_attr switch (bool attributes_follow) {
690 * case TRUE:
691 * fattr3 attributes;
692 * case FALSE:
693 * void;
694 * };
695 */
696static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
697{
698 __be32 *p;
699
700 p = xdr_inline_decode(xdr, 4);
701 if (unlikely(p == NULL))
702 goto out_overflow;
703 if (*p != xdr_zero)
704 return decode_fattr3(xdr, fattr);
705 return 0;
706out_overflow:
707 print_overflow_msg(__func__, xdr);
708 return -EIO;
709}
710
711/*
712 * wcc_attr
713 * struct wcc_attr {
714 * size3 size;
715 * nfstime3 mtime;
716 * nfstime3 ctime;
717 * };
718 */
719static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
720{
721 __be32 *p;
722
723 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
724 if (unlikely(p == NULL))
725 goto out_overflow;
Chuck Leverf6048702010-12-14 14:57:02 +0000726
727 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
728 | NFS_ATTR_FATTR_PREMTIME
729 | NFS_ATTR_FATTR_PRECTIME;
730
731 p = xdr_decode_size3(p, &fattr->pre_size);
732 p = xdr_decode_nfstime3(p, &fattr->pre_mtime);
733 xdr_decode_nfstime3(p, &fattr->pre_ctime);
734
Chuck Levere4f93232010-12-14 14:56:30 +0000735 return 0;
736out_overflow:
737 print_overflow_msg(__func__, xdr);
738 return -EIO;
739}
740
741/*
742 * pre_op_attr
743 * union pre_op_attr switch (bool attributes_follow) {
744 * case TRUE:
745 * wcc_attr attributes;
746 * case FALSE:
747 * void;
748 * };
749 *
750 * wcc_data
751 *
752 * struct wcc_data {
753 * pre_op_attr before;
754 * post_op_attr after;
755 * };
756 */
757static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
758{
759 __be32 *p;
760
761 p = xdr_inline_decode(xdr, 4);
762 if (unlikely(p == NULL))
763 goto out_overflow;
764 if (*p != xdr_zero)
765 return decode_wcc_attr(xdr, fattr);
766 return 0;
767out_overflow:
768 print_overflow_msg(__func__, xdr);
769 return -EIO;
770}
771
772static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
773{
774 int error;
775
776 error = decode_pre_op_attr(xdr, fattr);
777 if (unlikely(error))
778 goto out;
779 error = decode_post_op_attr(xdr, fattr);
780out:
781 return error;
782}
783
784/*
785 * post_op_fh3
786 *
787 * union post_op_fh3 switch (bool handle_follows) {
788 * case TRUE:
789 * nfs_fh3 handle;
790 * case FALSE:
791 * void;
792 * };
793 */
794static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
795{
796 __be32 *p = xdr_inline_decode(xdr, 4);
797 if (unlikely(p == NULL))
798 goto out_overflow;
799 if (*p != xdr_zero)
800 return decode_nfs_fh3(xdr, fh);
801 zero_nfs_fh3(fh);
802 return 0;
803out_overflow:
804 print_overflow_msg(__func__, xdr);
805 return -EIO;
806}
807
808/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000809 * diropargs3
810 *
811 * struct diropargs3 {
812 * nfs_fh3 dir;
813 * filename3 name;
814 * };
815 */
816static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
817 const char *name, u32 length)
818{
819 encode_nfs_fh3(xdr, fh);
820 encode_filename3(xdr, name, length);
821}
822
823
Linus Torvalds1da177e2005-04-16 15:20:36 -0700824/*
Chuck Lever499ff712010-12-14 14:56:10 +0000825 * NFSv3 XDR encode functions
826 *
827 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
828 * "NFS Version 3 Protocol Specification".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700829 */
830
831/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000832 * 3.3.1 GETATTR3args
833 *
834 * struct GETATTR3args {
835 * nfs_fh3 object;
836 * };
837 */
838static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
839 const struct nfs_fh *fh)
840{
841 struct xdr_stream xdr;
842
843 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
844 encode_nfs_fh3(&xdr, fh);
845 return 0;
846}
847
848/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000849 * 3.3.2 SETATTR3args
850 *
851 * union sattrguard3 switch (bool check) {
852 * case TRUE:
853 * nfstime3 obj_ctime;
854 * case FALSE:
855 * void;
856 * };
857 *
858 * struct SETATTR3args {
859 * nfs_fh3 object;
860 * sattr3 new_attributes;
861 * sattrguard3 guard;
862 * };
863 */
864static void encode_sattrguard3(struct xdr_stream *xdr,
865 const struct nfs3_sattrargs *args)
866{
867 __be32 *p;
868
869 if (args->guard) {
870 p = xdr_reserve_space(xdr, 4 + 8);
871 *p++ = xdr_one;
Chuck Lever9d5a6432010-12-14 14:56:20 +0000872 xdr_encode_nfstime3(p, &args->guardtime);
Chuck Leverd9c407b2010-12-14 14:55:50 +0000873 } else {
874 p = xdr_reserve_space(xdr, 4);
875 *p = xdr_zero;
876 }
877}
878
879static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
880 const struct nfs3_sattrargs *args)
881{
882 struct xdr_stream xdr;
883
884 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
885 encode_nfs_fh3(&xdr, args->fh);
886 encode_sattr3(&xdr, args->sattr);
887 encode_sattrguard3(&xdr, args);
888 return 0;
889}
890
891/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000892 * 3.3.3 LOOKUP3args
893 *
894 * struct LOOKUP3args {
895 * diropargs3 what;
896 * };
897 */
898static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
899 const struct nfs3_diropargs *args)
900{
901 struct xdr_stream xdr;
902
903 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
904 encode_diropargs3(&xdr, args->fh, args->name, args->len);
905 return 0;
906}
907
908/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000909 * 3.3.4 ACCESS3args
910 *
911 * struct ACCESS3args {
912 * nfs_fh3 object;
913 * uint32 access;
914 * };
915 */
916static void encode_access3args(struct xdr_stream *xdr,
917 const struct nfs3_accessargs *args)
918{
919 encode_nfs_fh3(xdr, args->fh);
920 encode_uint32(xdr, args->access);
921}
922
923static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
924 const struct nfs3_accessargs *args)
925{
926 struct xdr_stream xdr;
927
928 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
929 encode_access3args(&xdr, args);
930 return 0;
931}
932
933/*
934 * 3.3.5 READLINK3args
935 *
936 * struct READLINK3args {
937 * nfs_fh3 symlink;
938 * };
939 */
940static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
941 const struct nfs3_readlinkargs *args)
942{
943 struct xdr_stream xdr;
944
945 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
946 encode_nfs_fh3(&xdr, args->fh);
947 prepare_reply_buffer(req, args->pages, args->pgbase,
948 args->pglen, NFS3_readlinkres_sz);
949 return 0;
950}
951
952/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000953 * 3.3.6 READ3args
954 *
955 * struct READ3args {
956 * nfs_fh3 file;
957 * offset3 offset;
958 * count3 count;
959 * };
960 */
961static void encode_read3args(struct xdr_stream *xdr,
962 const struct nfs_readargs *args)
963{
964 __be32 *p;
965
966 encode_nfs_fh3(xdr, args->fh);
967
968 p = xdr_reserve_space(xdr, 8 + 4);
969 p = xdr_encode_hyper(p, args->offset);
970 *p = cpu_to_be32(args->count);
971}
972
973static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
974 const struct nfs_readargs *args)
975{
976 struct xdr_stream xdr;
977
978 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
979 encode_read3args(&xdr, args);
980 prepare_reply_buffer(req, args->pages, args->pgbase,
981 args->count, NFS3_readres_sz);
982 req->rq_rcv_buf.flags |= XDRBUF_READ;
983 return 0;
984}
985
986/*
Chuck Leverd9c407b2010-12-14 14:55:50 +0000987 * 3.3.7 WRITE3args
988 *
989 * enum stable_how {
990 * UNSTABLE = 0,
991 * DATA_SYNC = 1,
992 * FILE_SYNC = 2
993 * };
994 *
995 * struct WRITE3args {
996 * nfs_fh3 file;
997 * offset3 offset;
998 * count3 count;
999 * stable_how stable;
1000 * opaque data<>;
1001 * };
1002 */
1003static void encode_write3args(struct xdr_stream *xdr,
1004 const struct nfs_writeargs *args)
1005{
1006 __be32 *p;
1007
1008 encode_nfs_fh3(xdr, args->fh);
1009
1010 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
1011 p = xdr_encode_hyper(p, args->offset);
1012 *p++ = cpu_to_be32(args->count);
Chuck Leverd9c407b2010-12-14 14:55:50 +00001013 *p++ = cpu_to_be32(args->stable);
Chuck Leverd9c407b2010-12-14 14:55:50 +00001014 *p = cpu_to_be32(args->count);
1015 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1016}
1017
1018static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
1019 const struct nfs_writeargs *args)
1020{
1021 struct xdr_stream xdr;
1022
1023 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1024 encode_write3args(&xdr, args);
1025 xdr.buf->flags |= XDRBUF_WRITE;
1026 return 0;
1027}
1028
1029/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001030 * 3.3.8 CREATE3args
1031 *
1032 * enum createmode3 {
1033 * UNCHECKED = 0,
1034 * GUARDED = 1,
1035 * EXCLUSIVE = 2
1036 * };
1037 *
1038 * union createhow3 switch (createmode3 mode) {
1039 * case UNCHECKED:
1040 * case GUARDED:
1041 * sattr3 obj_attributes;
1042 * case EXCLUSIVE:
1043 * createverf3 verf;
1044 * };
1045 *
1046 * struct CREATE3args {
1047 * diropargs3 where;
1048 * createhow3 how;
1049 * };
1050 */
1051static void encode_createhow3(struct xdr_stream *xdr,
1052 const struct nfs3_createargs *args)
1053{
1054 encode_uint32(xdr, args->createmode);
1055 switch (args->createmode) {
1056 case NFS3_CREATE_UNCHECKED:
1057 case NFS3_CREATE_GUARDED:
1058 encode_sattr3(xdr, args->sattr);
1059 break;
1060 case NFS3_CREATE_EXCLUSIVE:
1061 encode_createverf3(xdr, args->verifier);
1062 break;
1063 default:
1064 BUG();
1065 }
1066}
1067
1068static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
1069 const struct nfs3_createargs *args)
1070{
1071 struct xdr_stream xdr;
1072
1073 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1074 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1075 encode_createhow3(&xdr, args);
1076 return 0;
1077}
1078
1079/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001080 * 3.3.9 MKDIR3args
1081 *
1082 * struct MKDIR3args {
1083 * diropargs3 where;
1084 * sattr3 attributes;
1085 * };
1086 */
1087static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
1088 const struct nfs3_mkdirargs *args)
1089{
1090 struct xdr_stream xdr;
1091
1092 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1093 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1094 encode_sattr3(&xdr, args->sattr);
1095 return 0;
1096}
1097
1098/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001099 * 3.3.10 SYMLINK3args
1100 *
1101 * struct symlinkdata3 {
1102 * sattr3 symlink_attributes;
1103 * nfspath3 symlink_data;
1104 * };
1105 *
1106 * struct SYMLINK3args {
1107 * diropargs3 where;
1108 * symlinkdata3 symlink;
1109 * };
1110 */
1111static void encode_symlinkdata3(struct xdr_stream *xdr,
1112 const struct nfs3_symlinkargs *args)
1113{
1114 encode_sattr3(xdr, args->sattr);
1115 encode_nfspath3(xdr, args->pages, args->pathlen);
1116}
1117
1118static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
1119 const struct nfs3_symlinkargs *args)
1120{
1121 struct xdr_stream xdr;
1122
1123 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1124 encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
1125 encode_symlinkdata3(&xdr, args);
1126 return 0;
1127}
1128
1129/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001130 * 3.3.11 MKNOD3args
1131 *
1132 * struct devicedata3 {
1133 * sattr3 dev_attributes;
1134 * specdata3 spec;
1135 * };
1136 *
1137 * union mknoddata3 switch (ftype3 type) {
1138 * case NF3CHR:
1139 * case NF3BLK:
1140 * devicedata3 device;
1141 * case NF3SOCK:
1142 * case NF3FIFO:
1143 * sattr3 pipe_attributes;
1144 * default:
1145 * void;
1146 * };
1147 *
1148 * struct MKNOD3args {
1149 * diropargs3 where;
1150 * mknoddata3 what;
1151 * };
1152 */
1153static void encode_devicedata3(struct xdr_stream *xdr,
1154 const struct nfs3_mknodargs *args)
1155{
1156 encode_sattr3(xdr, args->sattr);
1157 encode_specdata3(xdr, args->rdev);
1158}
1159
1160static void encode_mknoddata3(struct xdr_stream *xdr,
1161 const struct nfs3_mknodargs *args)
1162{
1163 encode_ftype3(xdr, args->type);
1164 switch (args->type) {
1165 case NF3CHR:
1166 case NF3BLK:
1167 encode_devicedata3(xdr, args);
1168 break;
1169 case NF3SOCK:
1170 case NF3FIFO:
1171 encode_sattr3(xdr, args->sattr);
1172 break;
1173 case NF3REG:
1174 case NF3DIR:
1175 break;
1176 default:
1177 BUG();
1178 }
1179}
1180
1181static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
1182 const struct nfs3_mknodargs *args)
1183{
1184 struct xdr_stream xdr;
1185
1186 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1187 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1188 encode_mknoddata3(&xdr, args);
1189 return 0;
1190}
1191
1192/*
1193 * 3.3.12 REMOVE3args
1194 *
1195 * struct REMOVE3args {
1196 * diropargs3 object;
1197 * };
1198 */
1199static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
1200 const struct nfs_removeargs *args)
1201{
1202 struct xdr_stream xdr;
1203
1204 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1205 encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
1206 return 0;
1207}
1208
1209/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001210 * 3.3.14 RENAME3args
1211 *
1212 * struct RENAME3args {
1213 * diropargs3 from;
1214 * diropargs3 to;
1215 * };
1216 */
1217static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
1218 const struct nfs_renameargs *args)
1219{
1220 const struct qstr *old = args->old_name;
1221 const struct qstr *new = args->new_name;
1222 struct xdr_stream xdr;
1223
1224 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1225 encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
1226 encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
1227 return 0;
1228}
1229
1230/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001231 * 3.3.15 LINK3args
1232 *
1233 * struct LINK3args {
1234 * nfs_fh3 file;
1235 * diropargs3 link;
1236 * };
1237 */
1238static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
1239 const struct nfs3_linkargs *args)
1240{
1241 struct xdr_stream xdr;
1242
1243 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1244 encode_nfs_fh3(&xdr, args->fromfh);
1245 encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
1246 return 0;
1247}
1248
1249/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001250 * 3.3.16 READDIR3args
1251 *
1252 * struct READDIR3args {
1253 * nfs_fh3 dir;
1254 * cookie3 cookie;
1255 * cookieverf3 cookieverf;
1256 * count3 count;
1257 * };
1258 */
1259static void encode_readdir3args(struct xdr_stream *xdr,
1260 const struct nfs3_readdirargs *args)
1261{
1262 __be32 *p;
1263
1264 encode_nfs_fh3(xdr, args->fh);
1265
1266 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1267 p = xdr_encode_cookie3(p, args->cookie);
1268 p = xdr_encode_cookieverf3(p, args->verf);
1269 *p = cpu_to_be32(args->count);
1270}
1271
1272static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1273 const struct nfs3_readdirargs *args)
1274{
1275 struct xdr_stream xdr;
1276
1277 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1278 encode_readdir3args(&xdr, args);
1279 prepare_reply_buffer(req, args->pages, 0,
1280 args->count, NFS3_readdirres_sz);
1281 return 0;
1282}
1283
1284/*
1285 * 3.3.17 READDIRPLUS3args
1286 *
1287 * struct READDIRPLUS3args {
1288 * nfs_fh3 dir;
1289 * cookie3 cookie;
1290 * cookieverf3 cookieverf;
1291 * count3 dircount;
1292 * count3 maxcount;
1293 * };
1294 */
1295static void encode_readdirplus3args(struct xdr_stream *xdr,
1296 const struct nfs3_readdirargs *args)
1297{
1298 __be32 *p;
1299
1300 encode_nfs_fh3(xdr, args->fh);
1301
1302 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1303 p = xdr_encode_cookie3(p, args->cookie);
1304 p = xdr_encode_cookieverf3(p, args->verf);
1305
1306 /*
1307 * readdirplus: need dircount + buffer size.
1308 * We just make sure we make dircount big enough
1309 */
1310 *p++ = cpu_to_be32(args->count >> 3);
1311
1312 *p = cpu_to_be32(args->count);
1313}
1314
1315static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1316 const struct nfs3_readdirargs *args)
1317{
1318 struct xdr_stream xdr;
1319
1320 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1321 encode_readdirplus3args(&xdr, args);
1322 prepare_reply_buffer(req, args->pages, 0,
1323 args->count, NFS3_readdirres_sz);
1324 return 0;
1325}
1326
1327/*
Chuck Leverd9c407b2010-12-14 14:55:50 +00001328 * 3.3.21 COMMIT3args
1329 *
1330 * struct COMMIT3args {
1331 * nfs_fh3 file;
1332 * offset3 offset;
1333 * count3 count;
1334 * };
1335 */
1336static void encode_commit3args(struct xdr_stream *xdr,
1337 const struct nfs_writeargs *args)
1338{
1339 __be32 *p;
1340
1341 encode_nfs_fh3(xdr, args->fh);
1342
1343 p = xdr_reserve_space(xdr, 8 + 4);
1344 p = xdr_encode_hyper(p, args->offset);
1345 *p = cpu_to_be32(args->count);
1346}
1347
1348static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1349 const struct nfs_writeargs *args)
1350{
1351 struct xdr_stream xdr;
1352
1353 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1354 encode_commit3args(&xdr, args);
1355 return 0;
1356}
1357
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00001358#ifdef CONFIG_NFS_V3_ACL
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00001359
Chuck Leverd9c407b2010-12-14 14:55:50 +00001360static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1361 const struct nfs3_getaclargs *args)
1362{
1363 struct xdr_stream xdr;
1364
1365 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1366 encode_nfs_fh3(&xdr, args->fh);
1367 encode_uint32(&xdr, args->mask);
1368 if (args->mask & (NFS_ACL | NFS_DFACL))
1369 prepare_reply_buffer(req, args->pages, 0,
1370 NFSACL_MAXPAGES << PAGE_SHIFT,
1371 ACL3_getaclres_sz);
1372 return 0;
1373}
1374
Chuck Leverd9c407b2010-12-14 14:55:50 +00001375static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1376 const struct nfs3_setaclargs *args)
1377{
1378 struct xdr_stream xdr;
1379 unsigned int base;
1380 int error;
1381
1382 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1383 encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1384 encode_uint32(&xdr, args->mask);
1385 if (args->npages != 0)
1386 xdr_write_pages(&xdr, args->pages, 0, args->len);
1387
1388 base = req->rq_slen;
1389 error = nfsacl_encode(xdr.buf, base, args->inode,
1390 (args->mask & NFS_ACL) ?
1391 args->acl_access : NULL, 1, 0);
1392 BUG_ON(error < 0);
1393 error = nfsacl_encode(xdr.buf, base + error, args->inode,
1394 (args->mask & NFS_DFACL) ?
1395 args->acl_default : NULL, 1,
1396 NFS_ACL_DEFAULT);
1397 BUG_ON(error < 0);
1398 return 0;
1399}
1400
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00001401#endif /* CONFIG_NFS_V3_ACL */
1402
Linus Torvalds1da177e2005-04-16 15:20:36 -07001403/*
Chuck Leverb2cdd9c2010-12-14 14:56:52 +00001404 * NFSv3 XDR decode functions
1405 *
1406 * NFSv3 result types are defined in section 3.3 of RFC 1813:
1407 * "NFS Version 3 Protocol Specification".
Linus Torvalds1da177e2005-04-16 15:20:36 -07001408 */
1409
1410/*
Chuck Levere4f93232010-12-14 14:56:30 +00001411 * 3.3.1 GETATTR3res
1412 *
1413 * struct GETATTR3resok {
1414 * fattr3 obj_attributes;
1415 * };
1416 *
1417 * union GETATTR3res switch (nfsstat3 status) {
1418 * case NFS3_OK:
1419 * GETATTR3resok resok;
1420 * default:
1421 * void;
1422 * };
1423 */
1424static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, __be32 *p,
1425 struct nfs_fattr *result)
1426{
1427 struct xdr_stream xdr;
1428 enum nfs_stat status;
1429 int error;
1430
1431 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1432 error = decode_nfsstat3(&xdr, &status);
1433 if (unlikely(error))
1434 goto out;
1435 if (status != NFS3_OK)
1436 goto out_default;
1437 error = decode_fattr3(&xdr, result);
1438out:
1439 return error;
1440out_default:
1441 return nfs_stat_to_errno(status);
1442}
1443
1444/*
Chuck Levere4f93232010-12-14 14:56:30 +00001445 * 3.3.2 SETATTR3res
1446 *
1447 * struct SETATTR3resok {
1448 * wcc_data obj_wcc;
1449 * };
1450 *
1451 * struct SETATTR3resfail {
1452 * wcc_data obj_wcc;
1453 * };
1454 *
1455 * union SETATTR3res switch (nfsstat3 status) {
1456 * case NFS3_OK:
1457 * SETATTR3resok resok;
1458 * default:
1459 * SETATTR3resfail resfail;
1460 * };
1461 */
1462static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, __be32 *p,
1463 struct nfs_fattr *result)
1464{
1465 struct xdr_stream xdr;
1466 enum nfs_stat status;
1467 int error;
1468
1469 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1470 error = decode_nfsstat3(&xdr, &status);
1471 if (unlikely(error))
1472 goto out;
1473 error = decode_wcc_data(&xdr, result);
1474 if (unlikely(error))
1475 goto out;
1476 if (status != NFS3_OK)
1477 goto out_status;
1478out:
1479 return error;
1480out_status:
1481 return nfs_stat_to_errno(status);
1482}
1483
Linus Torvalds1da177e2005-04-16 15:20:36 -07001484/*
Chuck Levere4f93232010-12-14 14:56:30 +00001485 * 3.3.3 LOOKUP3res
1486 *
1487 * struct LOOKUP3resok {
1488 * nfs_fh3 object;
1489 * post_op_attr obj_attributes;
1490 * post_op_attr dir_attributes;
1491 * };
1492 *
1493 * struct LOOKUP3resfail {
1494 * post_op_attr dir_attributes;
1495 * };
1496 *
1497 * union LOOKUP3res switch (nfsstat3 status) {
1498 * case NFS3_OK:
1499 * LOOKUP3resok resok;
1500 * default:
1501 * LOOKUP3resfail resfail;
1502 * };
1503 */
1504static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, __be32 *p,
1505 struct nfs3_diropres *result)
1506{
1507 struct xdr_stream xdr;
1508 enum nfs_stat status;
1509 int error;
1510
1511 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1512 error = decode_nfsstat3(&xdr, &status);
1513 if (unlikely(error))
1514 goto out;
1515 if (status != NFS3_OK)
1516 goto out_default;
1517 error = decode_nfs_fh3(&xdr, result->fh);
1518 if (unlikely(error))
1519 goto out;
1520 error = decode_post_op_attr(&xdr, result->fattr);
1521 if (unlikely(error))
1522 goto out;
1523 error = decode_post_op_attr(&xdr, result->dir_attr);
1524out:
1525 return error;
1526out_default:
1527 error = decode_post_op_attr(&xdr, result->dir_attr);
1528 if (unlikely(error))
1529 goto out;
1530 return nfs_stat_to_errno(status);
1531}
1532
1533/*
Chuck Levere4f93232010-12-14 14:56:30 +00001534 * 3.3.4 ACCESS3res
1535 *
1536 * struct ACCESS3resok {
1537 * post_op_attr obj_attributes;
1538 * uint32 access;
1539 * };
1540 *
1541 * struct ACCESS3resfail {
1542 * post_op_attr obj_attributes;
1543 * };
1544 *
1545 * union ACCESS3res switch (nfsstat3 status) {
1546 * case NFS3_OK:
1547 * ACCESS3resok resok;
1548 * default:
1549 * ACCESS3resfail resfail;
1550 * };
1551 */
1552static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, __be32 *p,
1553 struct nfs3_accessres *result)
1554{
1555 struct xdr_stream xdr;
1556 enum nfs_stat status;
1557 int error;
1558
1559 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1560 error = decode_nfsstat3(&xdr, &status);
1561 if (unlikely(error))
1562 goto out;
1563 error = decode_post_op_attr(&xdr, result->fattr);
1564 if (unlikely(error))
1565 goto out;
1566 if (status != NFS3_OK)
1567 goto out_default;
1568 error = decode_uint32(&xdr, &result->access);
1569out:
1570 return error;
1571out_default:
1572 return nfs_stat_to_errno(status);
1573}
1574
1575/*
Chuck Levere4f93232010-12-14 14:56:30 +00001576 * 3.3.5 READLINK3res
1577 *
1578 * struct READLINK3resok {
1579 * post_op_attr symlink_attributes;
1580 * nfspath3 data;
1581 * };
1582 *
1583 * struct READLINK3resfail {
1584 * post_op_attr symlink_attributes;
1585 * };
1586 *
1587 * union READLINK3res switch (nfsstat3 status) {
1588 * case NFS3_OK:
1589 * READLINK3resok resok;
1590 * default:
1591 * READLINK3resfail resfail;
1592 * };
1593 */
1594static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, __be32 *p,
1595 struct nfs_fattr *result)
1596{
1597 struct xdr_stream xdr;
1598 enum nfs_stat status;
1599 int error;
1600
1601 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1602 error = decode_nfsstat3(&xdr, &status);
1603 if (unlikely(error))
1604 goto out;
1605 error = decode_post_op_attr(&xdr, result);
1606 if (unlikely(error))
1607 goto out;
1608 if (status != NFS3_OK)
1609 goto out_default;
1610 error = decode_nfspath3(&xdr);
1611out:
1612 return error;
1613out_default:
1614 return nfs_stat_to_errno(status);
1615}
1616
1617/*
Chuck Levere4f93232010-12-14 14:56:30 +00001618 * 3.3.6 READ3res
1619 *
1620 * struct READ3resok {
1621 * post_op_attr file_attributes;
1622 * count3 count;
1623 * bool eof;
1624 * opaque data<>;
1625 * };
1626 *
1627 * struct READ3resfail {
1628 * post_op_attr file_attributes;
1629 * };
1630 *
1631 * union READ3res switch (nfsstat3 status) {
1632 * case NFS3_OK:
1633 * READ3resok resok;
1634 * default:
1635 * READ3resfail resfail;
1636 * };
1637 */
1638static int decode_read3resok(struct xdr_stream *xdr,
1639 struct nfs_readres *result)
1640{
1641 u32 eof, count, ocount, recvd;
1642 size_t hdrlen;
1643 __be32 *p;
1644
1645 p = xdr_inline_decode(xdr, 4 + 4 + 4);
1646 if (unlikely(p == NULL))
1647 goto out_overflow;
1648 count = be32_to_cpup(p++);
1649 eof = be32_to_cpup(p++);
1650 ocount = be32_to_cpup(p++);
1651 if (unlikely(ocount != count))
1652 goto out_mismatch;
1653 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1654 recvd = xdr->buf->len - hdrlen;
1655 if (unlikely(count > recvd))
1656 goto out_cheating;
1657
1658out:
1659 xdr_read_pages(xdr, count);
1660 result->eof = eof;
1661 result->count = count;
1662 return count;
1663out_mismatch:
1664 dprintk("NFS: READ count doesn't match length of opaque: "
1665 "count %u != ocount %u\n", count, ocount);
1666 return -EIO;
1667out_cheating:
1668 dprintk("NFS: server cheating in read result: "
1669 "count %u > recvd %u\n", count, recvd);
1670 count = recvd;
1671 eof = 0;
1672 goto out;
1673out_overflow:
1674 print_overflow_msg(__func__, xdr);
1675 return -EIO;
1676}
1677
1678static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, __be32 *p,
1679 struct nfs_readres *result)
1680{
1681 struct xdr_stream xdr;
1682 enum nfs_stat status;
1683 int error;
1684
1685 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1686 error = decode_nfsstat3(&xdr, &status);
1687 if (unlikely(error))
1688 goto out;
1689 error = decode_post_op_attr(&xdr, result->fattr);
1690 if (unlikely(error))
1691 goto out;
1692 if (status != NFS3_OK)
1693 goto out_status;
1694 error = decode_read3resok(&xdr, result);
1695out:
1696 return error;
1697out_status:
1698 return nfs_stat_to_errno(status);
1699}
1700
1701/*
Chuck Levere4f93232010-12-14 14:56:30 +00001702 * 3.3.7 WRITE3res
1703 *
1704 * enum stable_how {
1705 * UNSTABLE = 0,
1706 * DATA_SYNC = 1,
1707 * FILE_SYNC = 2
1708 * };
1709 *
1710 * struct WRITE3resok {
1711 * wcc_data file_wcc;
1712 * count3 count;
1713 * stable_how committed;
1714 * writeverf3 verf;
1715 * };
1716 *
1717 * struct WRITE3resfail {
1718 * wcc_data file_wcc;
1719 * };
1720 *
1721 * union WRITE3res switch (nfsstat3 status) {
1722 * case NFS3_OK:
1723 * WRITE3resok resok;
1724 * default:
1725 * WRITE3resfail resfail;
1726 * };
1727 */
1728static int decode_write3resok(struct xdr_stream *xdr,
1729 struct nfs_writeres *result)
1730{
1731 __be32 *p;
1732
1733 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
1734 if (unlikely(p == NULL))
1735 goto out_overflow;
1736 result->count = be32_to_cpup(p++);
1737 result->verf->committed = be32_to_cpup(p++);
1738 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
1739 goto out_badvalue;
1740 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
1741 return result->count;
1742out_badvalue:
1743 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
1744 return -EIO;
1745out_overflow:
1746 print_overflow_msg(__func__, xdr);
1747 return -EIO;
1748}
1749
1750static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, __be32 *p,
1751 struct nfs_writeres *result)
1752{
1753 struct xdr_stream xdr;
1754 enum nfs_stat status;
1755 int error;
1756
1757 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1758 error = decode_nfsstat3(&xdr, &status);
1759 if (unlikely(error))
1760 goto out;
1761 error = decode_wcc_data(&xdr, result->fattr);
1762 if (unlikely(error))
1763 goto out;
1764 if (status != NFS3_OK)
1765 goto out_status;
1766 error = decode_write3resok(&xdr, result);
1767out:
1768 return error;
1769out_status:
1770 return nfs_stat_to_errno(status);
1771}
1772
1773/*
Chuck Levere4f93232010-12-14 14:56:30 +00001774 * 3.3.8 CREATE3res
1775 *
1776 * struct CREATE3resok {
1777 * post_op_fh3 obj;
1778 * post_op_attr obj_attributes;
1779 * wcc_data dir_wcc;
1780 * };
1781 *
1782 * struct CREATE3resfail {
1783 * wcc_data dir_wcc;
1784 * };
1785 *
1786 * union CREATE3res switch (nfsstat3 status) {
1787 * case NFS3_OK:
1788 * CREATE3resok resok;
1789 * default:
1790 * CREATE3resfail resfail;
1791 * };
1792 */
1793static int decode_create3resok(struct xdr_stream *xdr,
1794 struct nfs3_diropres *result)
1795{
1796 int error;
1797
1798 error = decode_post_op_fh3(xdr, result->fh);
1799 if (unlikely(error))
1800 goto out;
1801 error = decode_post_op_attr(xdr, result->fattr);
1802 if (unlikely(error))
1803 goto out;
1804 /* The server isn't required to return a file handle.
1805 * If it didn't, force the client to perform a LOOKUP
1806 * to determine the correct file handle and attribute
1807 * values for the new object. */
1808 if (result->fh->size == 0)
1809 result->fattr->valid = 0;
1810 error = decode_wcc_data(xdr, result->dir_attr);
1811out:
1812 return error;
1813}
1814
1815static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, __be32 *p,
1816 struct nfs3_diropres *result)
1817{
1818 struct xdr_stream xdr;
1819 enum nfs_stat status;
1820 int error;
1821
1822 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1823 error = decode_nfsstat3(&xdr, &status);
1824 if (unlikely(error))
1825 goto out;
1826 if (status != NFS3_OK)
1827 goto out_default;
1828 error = decode_create3resok(&xdr, result);
1829out:
1830 return error;
1831out_default:
1832 error = decode_wcc_data(&xdr, result->dir_attr);
1833 if (unlikely(error))
1834 goto out;
1835 return nfs_stat_to_errno(status);
1836}
1837
1838/*
1839 * 3.3.12 REMOVE3res
1840 *
1841 * struct REMOVE3resok {
1842 * wcc_data dir_wcc;
1843 * };
1844 *
1845 * struct REMOVE3resfail {
1846 * wcc_data dir_wcc;
1847 * };
1848 *
1849 * union REMOVE3res switch (nfsstat3 status) {
1850 * case NFS3_OK:
1851 * REMOVE3resok resok;
1852 * default:
1853 * REMOVE3resfail resfail;
1854 * };
1855 */
1856static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, __be32 *p,
1857 struct nfs_removeres *result)
1858{
1859 struct xdr_stream xdr;
1860 enum nfs_stat status;
1861 int error;
1862
1863 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1864 error = decode_nfsstat3(&xdr, &status);
1865 if (unlikely(error))
1866 goto out;
1867 error = decode_wcc_data(&xdr, result->dir_attr);
1868 if (unlikely(error))
1869 goto out;
1870 if (status != NFS3_OK)
1871 goto out_status;
1872out:
1873 return error;
1874out_status:
1875 return nfs_stat_to_errno(status);
1876}
1877
1878/*
Chuck Levere4f93232010-12-14 14:56:30 +00001879 * 3.3.14 RENAME3res
1880 *
1881 * struct RENAME3resok {
1882 * wcc_data fromdir_wcc;
1883 * wcc_data todir_wcc;
1884 * };
1885 *
1886 * struct RENAME3resfail {
1887 * wcc_data fromdir_wcc;
1888 * wcc_data todir_wcc;
1889 * };
1890 *
1891 * union RENAME3res switch (nfsstat3 status) {
1892 * case NFS3_OK:
1893 * RENAME3resok resok;
1894 * default:
1895 * RENAME3resfail resfail;
1896 * };
1897 */
1898static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, __be32 *p,
1899 struct nfs_renameres *result)
1900{
1901 struct xdr_stream xdr;
1902 enum nfs_stat status;
1903 int error;
1904
1905 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1906 error = decode_nfsstat3(&xdr, &status);
1907 if (unlikely(error))
1908 goto out;
1909 error = decode_wcc_data(&xdr, result->old_fattr);
1910 if (unlikely(error))
1911 goto out;
1912 error = decode_wcc_data(&xdr, result->new_fattr);
1913 if (unlikely(error))
1914 goto out;
1915 if (status != NFS3_OK)
1916 goto out_status;
1917out:
1918 return error;
1919out_status:
1920 return nfs_stat_to_errno(status);
1921}
1922
1923/*
Chuck Levere4f93232010-12-14 14:56:30 +00001924 * 3.3.15 LINK3res
1925 *
1926 * struct LINK3resok {
1927 * post_op_attr file_attributes;
1928 * wcc_data linkdir_wcc;
1929 * };
1930 *
1931 * struct LINK3resfail {
1932 * post_op_attr file_attributes;
1933 * wcc_data linkdir_wcc;
1934 * };
1935 *
1936 * union LINK3res switch (nfsstat3 status) {
1937 * case NFS3_OK:
1938 * LINK3resok resok;
1939 * default:
1940 * LINK3resfail resfail;
1941 * };
1942 */
1943static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, __be32 *p,
1944 struct nfs3_linkres *result)
1945{
1946 struct xdr_stream xdr;
1947 enum nfs_stat status;
1948 int error;
1949
1950 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1951 error = decode_nfsstat3(&xdr, &status);
1952 if (unlikely(error))
1953 goto out;
1954 error = decode_post_op_attr(&xdr, result->fattr);
1955 if (unlikely(error))
1956 goto out;
1957 error = decode_wcc_data(&xdr, result->dir_attr);
1958 if (unlikely(error))
1959 goto out;
1960 if (status != NFS3_OK)
1961 goto out_status;
1962out:
1963 return error;
1964out_status:
1965 return nfs_stat_to_errno(status);
1966}
1967
1968/**
1969 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
1970 * the local page cache
1971 * @xdr: XDR stream where entry resides
1972 * @entry: buffer to fill in with entry data
1973 * @server: nfs_server data for this directory
1974 * @plus: boolean indicating whether this should be a readdirplus entry
1975 *
1976 * Returns the position of the next item in the buffer, or an ERR_PTR.
1977 *
1978 * This function is not invoked during READDIR reply decoding, but
1979 * rather whenever an application invokes the getdents(2) system call
1980 * on a directory already in our cache.
1981 *
1982 * 3.3.16 entry3
1983 *
1984 * struct entry3 {
1985 * fileid3 fileid;
1986 * filename3 name;
1987 * cookie3 cookie;
1988 * fhandle3 filehandle;
1989 * post_op_attr3 attributes;
1990 * entry3 *nextentry;
1991 * };
1992 *
1993 * 3.3.17 entryplus3
1994 * struct entryplus3 {
1995 * fileid3 fileid;
1996 * filename3 name;
1997 * cookie3 cookie;
1998 * post_op_attr name_attributes;
1999 * post_op_fh3 name_handle;
2000 * entryplus3 *nextentry;
2001 * };
2002 */
2003__be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2004 struct nfs_server *server, int plus)
2005{
2006 struct nfs_entry old = *entry;
2007 __be32 *p;
2008 int error;
2009
2010 p = xdr_inline_decode(xdr, 4);
2011 if (unlikely(p == NULL))
2012 goto out_overflow;
2013 if (*p == xdr_zero) {
2014 p = xdr_inline_decode(xdr, 4);
2015 if (unlikely(p == NULL))
2016 goto out_overflow;
2017 if (*p == xdr_zero)
2018 return ERR_PTR(-EAGAIN);
2019 entry->eof = 1;
2020 return ERR_PTR(-EBADCOOKIE);
2021 }
2022
2023 error = decode_fileid3(xdr, &entry->ino);
2024 if (unlikely(error))
2025 return ERR_PTR(error);
2026
2027 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2028 if (unlikely(error))
2029 return ERR_PTR(error);
2030
2031 entry->prev_cookie = entry->cookie;
2032 error = decode_cookie3(xdr, &entry->cookie);
2033 if (unlikely(error))
2034 return ERR_PTR(error);
2035
2036 entry->d_type = DT_UNKNOWN;
2037
2038 if (plus) {
2039 entry->fattr->valid = 0;
2040 error = decode_post_op_attr(xdr, entry->fattr);
2041 if (unlikely(error))
2042 return ERR_PTR(error);
2043 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2044 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2045
2046 /* In fact, a post_op_fh3: */
2047 p = xdr_inline_decode(xdr, 4);
2048 if (unlikely(p == NULL))
2049 goto out_overflow;
2050 if (*p != xdr_zero) {
2051 error = decode_nfs_fh3(xdr, entry->fh);
2052 if (unlikely(error)) {
2053 if (error == -E2BIG)
2054 goto out_truncated;
2055 return ERR_PTR(error);
2056 }
2057 } else
2058 zero_nfs_fh3(entry->fh);
2059 }
2060
2061 /* Peek at the next entry to see if we're at EOD */
2062 p = xdr_inline_peek(xdr, 4 + 4);
2063 entry->eof = 0;
2064 if (p != NULL)
2065 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
2066 return p;
2067
2068out_overflow:
2069 print_overflow_msg(__func__, xdr);
2070 return ERR_PTR(-EAGAIN);
2071out_truncated:
2072 dprintk("NFS: directory entry contains invalid file handle\n");
2073 *entry = old;
2074 return ERR_PTR(-EAGAIN);
2075}
2076
2077/*
2078 * 3.3.16 READDIR3res
2079 *
2080 * struct dirlist3 {
2081 * entry3 *entries;
2082 * bool eof;
2083 * };
2084 *
2085 * struct READDIR3resok {
2086 * post_op_attr dir_attributes;
2087 * cookieverf3 cookieverf;
2088 * dirlist3 reply;
2089 * };
2090 *
2091 * struct READDIR3resfail {
2092 * post_op_attr dir_attributes;
2093 * };
2094 *
2095 * union READDIR3res switch (nfsstat3 status) {
2096 * case NFS3_OK:
2097 * READDIR3resok resok;
2098 * default:
2099 * READDIR3resfail resfail;
2100 * };
2101 *
2102 * Read the directory contents into the page cache, but otherwise
2103 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2104 * during subsequent nfs_readdir() calls.
2105 */
2106static int decode_dirlist3(struct xdr_stream *xdr)
2107{
2108 u32 recvd, pglen;
2109 size_t hdrlen;
2110
2111 pglen = xdr->buf->page_len;
2112 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2113 recvd = xdr->buf->len - hdrlen;
2114 if (unlikely(pglen > recvd))
2115 goto out_cheating;
2116out:
2117 xdr_read_pages(xdr, pglen);
2118 return pglen;
2119out_cheating:
2120 dprintk("NFS: server cheating in readdir result: "
2121 "pglen %u > recvd %u\n", pglen, recvd);
2122 pglen = recvd;
2123 goto out;
2124}
2125
2126static int decode_readdir3resok(struct xdr_stream *xdr,
2127 struct nfs3_readdirres *result)
2128{
2129 int error;
2130
2131 error = decode_post_op_attr(xdr, result->dir_attr);
2132 if (unlikely(error))
2133 goto out;
2134 /* XXX: do we need to check if result->verf != NULL ? */
2135 error = decode_cookieverf3(xdr, result->verf);
2136 if (unlikely(error))
2137 goto out;
2138 error = decode_dirlist3(xdr);
2139out:
2140 return error;
2141}
2142
2143static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, __be32 *p,
2144 struct nfs3_readdirres *result)
2145{
2146 struct xdr_stream xdr;
2147 enum nfs_stat status;
2148 int error;
2149
2150 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2151 error = decode_nfsstat3(&xdr, &status);
2152 if (unlikely(error))
2153 goto out;
2154 if (status != NFS3_OK)
2155 goto out_default;
2156 error = decode_readdir3resok(&xdr, result);
2157out:
2158 return error;
2159out_default:
2160 error = decode_post_op_attr(&xdr, result->dir_attr);
2161 if (unlikely(error))
2162 goto out;
2163 return nfs_stat_to_errno(status);
2164}
2165
2166/*
Chuck Levere4f93232010-12-14 14:56:30 +00002167 * 3.3.18 FSSTAT3res
2168 *
2169 * struct FSSTAT3resok {
2170 * post_op_attr obj_attributes;
2171 * size3 tbytes;
2172 * size3 fbytes;
2173 * size3 abytes;
2174 * size3 tfiles;
2175 * size3 ffiles;
2176 * size3 afiles;
2177 * uint32 invarsec;
2178 * };
2179 *
2180 * struct FSSTAT3resfail {
2181 * post_op_attr obj_attributes;
2182 * };
2183 *
2184 * union FSSTAT3res switch (nfsstat3 status) {
2185 * case NFS3_OK:
2186 * FSSTAT3resok resok;
2187 * default:
2188 * FSSTAT3resfail resfail;
2189 * };
2190 */
2191static int decode_fsstat3resok(struct xdr_stream *xdr,
2192 struct nfs_fsstat *result)
2193{
2194 __be32 *p;
2195
2196 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2197 if (unlikely(p == NULL))
2198 goto out_overflow;
2199 p = xdr_decode_size3(p, &result->tbytes);
2200 p = xdr_decode_size3(p, &result->fbytes);
2201 p = xdr_decode_size3(p, &result->abytes);
2202 p = xdr_decode_size3(p, &result->tfiles);
2203 p = xdr_decode_size3(p, &result->ffiles);
2204 xdr_decode_size3(p, &result->afiles);
2205 /* ignore invarsec */
2206 return 0;
2207out_overflow:
2208 print_overflow_msg(__func__, xdr);
2209 return -EIO;
2210}
2211
2212static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, __be32 *p,
2213 struct nfs_fsstat *result)
2214{
2215 struct xdr_stream xdr;
2216 enum nfs_stat status;
2217 int error;
2218
2219 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2220 error = decode_nfsstat3(&xdr, &status);
2221 if (unlikely(error))
2222 goto out;
2223 error = decode_post_op_attr(&xdr, result->fattr);
2224 if (unlikely(error))
2225 goto out;
2226 if (status != NFS3_OK)
2227 goto out_status;
2228 error = decode_fsstat3resok(&xdr, result);
2229out:
2230 return error;
2231out_status:
2232 return nfs_stat_to_errno(status);
2233}
2234
2235/*
Chuck Levere4f93232010-12-14 14:56:30 +00002236 * 3.3.19 FSINFO3res
2237 *
2238 * struct FSINFO3resok {
2239 * post_op_attr obj_attributes;
2240 * uint32 rtmax;
2241 * uint32 rtpref;
2242 * uint32 rtmult;
2243 * uint32 wtmax;
2244 * uint32 wtpref;
2245 * uint32 wtmult;
2246 * uint32 dtpref;
2247 * size3 maxfilesize;
2248 * nfstime3 time_delta;
2249 * uint32 properties;
2250 * };
2251 *
2252 * struct FSINFO3resfail {
2253 * post_op_attr obj_attributes;
2254 * };
2255 *
2256 * union FSINFO3res switch (nfsstat3 status) {
2257 * case NFS3_OK:
2258 * FSINFO3resok resok;
2259 * default:
2260 * FSINFO3resfail resfail;
2261 * };
2262 */
2263static int decode_fsinfo3resok(struct xdr_stream *xdr,
2264 struct nfs_fsinfo *result)
2265{
2266 __be32 *p;
2267
2268 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2269 if (unlikely(p == NULL))
2270 goto out_overflow;
2271 result->rtmax = be32_to_cpup(p++);
2272 result->rtpref = be32_to_cpup(p++);
2273 result->rtmult = be32_to_cpup(p++);
2274 result->wtmax = be32_to_cpup(p++);
2275 result->wtpref = be32_to_cpup(p++);
2276 result->wtmult = be32_to_cpup(p++);
2277 result->dtpref = be32_to_cpup(p++);
2278 p = xdr_decode_size3(p, &result->maxfilesize);
Chuck Leverf6048702010-12-14 14:57:02 +00002279 xdr_decode_nfstime3(p, &result->time_delta);
Chuck Levere4f93232010-12-14 14:56:30 +00002280
2281 /* ignore properties */
2282 result->lease_time = 0;
2283 return 0;
2284out_overflow:
2285 print_overflow_msg(__func__, xdr);
2286 return -EIO;
2287}
2288
2289static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, __be32 *p,
2290 struct nfs_fsinfo *result)
2291{
2292 struct xdr_stream xdr;
2293 enum nfs_stat status;
2294 int error;
2295
2296 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2297 error = decode_nfsstat3(&xdr, &status);
2298 if (unlikely(error))
2299 goto out;
2300 error = decode_post_op_attr(&xdr, result->fattr);
2301 if (unlikely(error))
2302 goto out;
2303 if (status != NFS3_OK)
2304 goto out_status;
2305 error = decode_fsinfo3resok(&xdr, result);
2306out:
2307 return error;
2308out_status:
2309 return nfs_stat_to_errno(status);
2310}
2311
2312/*
Chuck Levere4f93232010-12-14 14:56:30 +00002313 * 3.3.20 PATHCONF3res
2314 *
2315 * struct PATHCONF3resok {
2316 * post_op_attr obj_attributes;
2317 * uint32 linkmax;
2318 * uint32 name_max;
2319 * bool no_trunc;
2320 * bool chown_restricted;
2321 * bool case_insensitive;
2322 * bool case_preserving;
2323 * };
2324 *
2325 * struct PATHCONF3resfail {
2326 * post_op_attr obj_attributes;
2327 * };
2328 *
2329 * union PATHCONF3res switch (nfsstat3 status) {
2330 * case NFS3_OK:
2331 * PATHCONF3resok resok;
2332 * default:
2333 * PATHCONF3resfail resfail;
2334 * };
2335 */
2336static int decode_pathconf3resok(struct xdr_stream *xdr,
2337 struct nfs_pathconf *result)
2338{
2339 __be32 *p;
2340
2341 p = xdr_inline_decode(xdr, 4 * 6);
2342 if (unlikely(p == NULL))
2343 goto out_overflow;
2344 result->max_link = be32_to_cpup(p++);
2345 result->max_namelen = be32_to_cpup(p);
2346 /* ignore remaining fields */
2347 return 0;
2348out_overflow:
2349 print_overflow_msg(__func__, xdr);
2350 return -EIO;
2351}
2352
2353static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, __be32 *p,
2354 struct nfs_pathconf *result)
2355{
2356 struct xdr_stream xdr;
2357 enum nfs_stat status;
2358 int error;
2359
2360 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2361 error = decode_nfsstat3(&xdr, &status);
2362 if (unlikely(error))
2363 goto out;
2364 error = decode_post_op_attr(&xdr, result->fattr);
2365 if (unlikely(error))
2366 goto out;
2367 if (status != NFS3_OK)
2368 goto out_status;
2369 error = decode_pathconf3resok(&xdr, result);
2370out:
2371 return error;
2372out_status:
2373 return nfs_stat_to_errno(status);
2374}
2375
2376/*
Chuck Levere4f93232010-12-14 14:56:30 +00002377 * 3.3.21 COMMIT3res
2378 *
2379 * struct COMMIT3resok {
2380 * wcc_data file_wcc;
2381 * writeverf3 verf;
2382 * };
2383 *
2384 * struct COMMIT3resfail {
2385 * wcc_data file_wcc;
2386 * };
2387 *
2388 * union COMMIT3res switch (nfsstat3 status) {
2389 * case NFS3_OK:
2390 * COMMIT3resok resok;
2391 * default:
2392 * COMMIT3resfail resfail;
2393 * };
2394 */
2395static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, __be32 *p,
2396 struct nfs_writeres *result)
2397{
2398 struct xdr_stream xdr;
2399 enum nfs_stat status;
2400 int error;
2401
2402 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2403 error = decode_nfsstat3(&xdr, &status);
2404 if (unlikely(error))
2405 goto out;
2406 error = decode_wcc_data(&xdr, result->fattr);
2407 if (unlikely(error))
2408 goto out;
2409 if (status != NFS3_OK)
2410 goto out_status;
2411 error = decode_writeverf3(&xdr, result->verf->verifier);
2412out:
2413 return error;
2414out_status:
2415 return nfs_stat_to_errno(status);
2416}
2417
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002418#ifdef CONFIG_NFS_V3_ACL
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002419
Chuck Levere4f93232010-12-14 14:56:30 +00002420static inline int decode_getacl3resok(struct xdr_stream *xdr,
2421 struct nfs3_getaclres *result)
2422{
2423 struct posix_acl **acl;
2424 unsigned int *aclcnt;
2425 size_t hdrlen;
2426 int error;
2427
2428 error = decode_post_op_attr(xdr, result->fattr);
2429 if (unlikely(error))
2430 goto out;
2431 error = decode_uint32(xdr, &result->mask);
2432 if (unlikely(error))
2433 goto out;
2434 error = -EINVAL;
2435 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2436 goto out;
2437
2438 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2439
2440 acl = NULL;
2441 if (result->mask & NFS_ACL)
2442 acl = &result->acl_access;
2443 aclcnt = NULL;
2444 if (result->mask & NFS_ACLCNT)
2445 aclcnt = &result->acl_access_count;
2446 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2447 if (unlikely(error <= 0))
2448 goto out;
2449
2450 acl = NULL;
2451 if (result->mask & NFS_DFACL)
2452 acl = &result->acl_default;
2453 aclcnt = NULL;
2454 if (result->mask & NFS_DFACLCNT)
2455 aclcnt = &result->acl_default_count;
2456 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2457 if (unlikely(error <= 0))
2458 return error;
2459 error = 0;
2460out:
2461 return error;
2462}
2463
2464static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, __be32 *p,
2465 struct nfs3_getaclres *result)
2466{
2467 struct xdr_stream xdr;
2468 enum nfs_stat status;
2469 int error;
2470
2471 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2472 error = decode_nfsstat3(&xdr, &status);
2473 if (unlikely(error))
2474 goto out;
2475 if (status != NFS3_OK)
2476 goto out_default;
2477 error = decode_getacl3resok(&xdr, result);
2478out:
2479 return error;
2480out_default:
2481 return nfs_stat_to_errno(status);
2482}
2483
Chuck Levere4f93232010-12-14 14:56:30 +00002484static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, __be32 *p,
2485 struct nfs_fattr *result)
2486{
2487 struct xdr_stream xdr;
2488 enum nfs_stat status;
2489 int error;
2490
2491 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2492 error = decode_nfsstat3(&xdr, &status);
2493 if (unlikely(error))
2494 goto out;
2495 if (status != NFS3_OK)
2496 goto out_default;
2497 error = decode_post_op_attr(&xdr, result);
2498out:
2499 return error;
2500out_default:
2501 return nfs_stat_to_errno(status);
2502}
2503
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002504#endif /* CONFIG_NFS_V3_ACL */
2505
Linus Torvalds1da177e2005-04-16 15:20:36 -07002506#define PROC(proc, argtype, restype, timer) \
2507[NFS3PROC_##proc] = { \
2508 .p_proc = NFS3PROC_##proc, \
Chuck Leverad96b5b2010-12-14 14:56:01 +00002509 .p_encode = (kxdrproc_t)nfs3_xdr_enc_##argtype##3args, \
Chuck Leverf5fc3c502010-12-14 14:56:42 +00002510 .p_decode = (kxdrproc_t)nfs3_xdr_dec_##restype##3res, \
Chuck Leverad96b5b2010-12-14 14:56:01 +00002511 .p_arglen = NFS3_##argtype##args_sz, \
Chuck Leverf5fc3c502010-12-14 14:56:42 +00002512 .p_replen = NFS3_##restype##res_sz, \
Chuck Levercc0175c2006-03-20 13:44:22 -05002513 .p_timer = timer, \
2514 .p_statidx = NFS3PROC_##proc, \
2515 .p_name = #proc, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07002516 }
2517
2518struct rpc_procinfo nfs3_procedures[] = {
Chuck Leverf5fc3c502010-12-14 14:56:42 +00002519 PROC(GETATTR, getattr, getattr, 1),
2520 PROC(SETATTR, setattr, setattr, 0),
2521 PROC(LOOKUP, lookup, lookup, 2),
2522 PROC(ACCESS, access, access, 1),
2523 PROC(READLINK, readlink, readlink, 3),
2524 PROC(READ, read, read, 3),
2525 PROC(WRITE, write, write, 4),
2526 PROC(CREATE, create, create, 0),
2527 PROC(MKDIR, mkdir, create, 0),
2528 PROC(SYMLINK, symlink, create, 0),
2529 PROC(MKNOD, mknod, create, 0),
2530 PROC(REMOVE, remove, remove, 0),
2531 PROC(RMDIR, lookup, setattr, 0),
2532 PROC(RENAME, rename, rename, 0),
2533 PROC(LINK, link, link, 0),
2534 PROC(READDIR, readdir, readdir, 3),
2535 PROC(READDIRPLUS, readdirplus, readdir, 3),
2536 PROC(FSSTAT, getattr, fsstat, 0),
2537 PROC(FSINFO, getattr, fsinfo, 0),
2538 PROC(PATHCONF, getattr, pathconf, 0),
2539 PROC(COMMIT, commit, commit, 5),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002540};
2541
2542struct rpc_version nfs_version3 = {
2543 .number = 3,
Tobias Klausere8c96f82006-03-24 03:15:34 -08002544 .nrprocs = ARRAY_SIZE(nfs3_procedures),
Linus Torvalds1da177e2005-04-16 15:20:36 -07002545 .procs = nfs3_procedures
2546};
2547
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002548#ifdef CONFIG_NFS_V3_ACL
2549static struct rpc_procinfo nfs3_acl_procedures[] = {
2550 [ACLPROC3_GETACL] = {
2551 .p_proc = ACLPROC3_GETACL,
Chuck Leverad96b5b2010-12-14 14:56:01 +00002552 .p_encode = (kxdrproc_t)nfs3_xdr_enc_getacl3args,
Chuck Leverf5fc3c502010-12-14 14:56:42 +00002553 .p_decode = (kxdrproc_t)nfs3_xdr_dec_getacl3res,
Chuck Lever2bea90d2007-03-29 16:47:53 -04002554 .p_arglen = ACL3_getaclargs_sz,
2555 .p_replen = ACL3_getaclres_sz,
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002556 .p_timer = 1,
Chuck Levercc0175c2006-03-20 13:44:22 -05002557 .p_name = "GETACL",
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002558 },
2559 [ACLPROC3_SETACL] = {
2560 .p_proc = ACLPROC3_SETACL,
Chuck Leverad96b5b2010-12-14 14:56:01 +00002561 .p_encode = (kxdrproc_t)nfs3_xdr_enc_setacl3args,
Chuck Leverf5fc3c502010-12-14 14:56:42 +00002562 .p_decode = (kxdrproc_t)nfs3_xdr_dec_setacl3res,
Chuck Lever2bea90d2007-03-29 16:47:53 -04002563 .p_arglen = ACL3_setaclargs_sz,
2564 .p_replen = ACL3_setaclres_sz,
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002565 .p_timer = 0,
Chuck Levercc0175c2006-03-20 13:44:22 -05002566 .p_name = "SETACL",
Andreas Gruenbacherb7fa0552005-06-22 17:16:27 +00002567 },
2568};
2569
2570struct rpc_version nfsacl_version3 = {
2571 .number = 3,
2572 .nrprocs = sizeof(nfs3_acl_procedures)/
2573 sizeof(nfs3_acl_procedures[0]),
2574 .procs = nfs3_acl_procedures,
2575};
2576#endif /* CONFIG_NFS_V3_ACL */