]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/blame - fs/nfs/nfs3xdr.c
NFS: Pass mntfh as part of the nfs_mount_info structure
[mirror_ubuntu-bionic-kernel.git] / fs / nfs / nfs3xdr.c
CommitLineData
1da177e4
LT
1/*
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>
1da177e4
LT
12#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>
b7fa0554 22#include <linux/nfsacl.h>
f7b422b1 23#include "internal.h"
1da177e4
LT
24
25#define NFSDBG_FACILITY NFSDBG_XDR
26
27/* Mapping from NFS error code to "errno" error code. */
28#define errno_NFSERR_IO EIO
29
1da177e4
LT
30/*
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)
d9c407b1 40#define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
f5fc3c50 41#define NFS3_wcc_attr_sz (6)
1da177e4
LT
42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
f5fc3c50 44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
1da177e4 45#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
ad96b5b5
CL
46
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)
1da177e4
LT
50#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)
94a6d753 56#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
1da177e4 57#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
ad96b5b5 58#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
1da177e4
LT
59#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
60#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
d9c407b1
CL
61#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
1da177e4
LT
63#define NFS3_commitargs_sz (NFS3_fh_sz+3)
64
f5fc3c50
CL
65#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)
1da177e4
LT
68#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
b7fa0554 82#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
ae46141f
TM
83#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))
b7fa0554
AG
87#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
88
1da177e4
LT
89/*
90 * Map file type to S_IFMT bits
91 */
bca79478
TM
92static 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,
1da177e4
LT
101};
102
d9c407b1
CL
103/*
104 * 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
e4f93234
CL
118/*
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
d9c407b1 128
d9c407b1
CL
129/*
130 * 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
e4f93234
CL
146static 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 */
f6048709
CL
179static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
180{
181 return xdr_decode_hyper(p, fileid);
182}
183
e4f93234
CL
184static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
185{
186 return decode_uint64(xdr, fileid);
187}
188
d9c407b1
CL
189/*
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
e4f93234
CL
204static 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
d9c407b1
CL
231/*
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
e4f93234
CL
244static 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
d9c407b1
CL
277/*
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
e4f93234
CL
287static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
288{
289 return decode_uint64(xdr, cookie);
290}
291
d9c407b1
CL
292/*
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
e4f93234
CL
303static 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
d9c407b1
CL
317/*
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
e4f93234
CL
330static 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
d9c407b1
CL
378/*
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
f6048709
CL
397static __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
d9c407b1
CL
408/*
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
f6048709
CL
425static __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
d9c407b1
CL
437/*
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
e4f93234
CL
453static 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
9d5a6434
CL
483/*
484 * 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
f6048709
CL
498static __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
d9c407b1
CL
505/*
506 * 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
9d5a6434
CL
591 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;
d9c407b1
CL
630}
631
e4f93234
CL
632/*
633 * 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{
f6048709 653 umode_t fmode;
e4f93234
CL
654 __be32 *p;
655
656 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
657 if (unlikely(p == NULL))
658 goto out_overflow;
f6048709
CL
659
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);
3a1556e8 678 fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
f6048709
CL
679
680 fattr->valid |= NFS_ATTR_FATTR_V3;
e4f93234
CL
681 return 0;
682out_overflow:
683 print_overflow_msg(__func__, xdr);
684 return -EIO;
685}
686
687/*
688 * post_op_attr
689 *
690 * union post_op_attr switch (bool attributes_follow) {
691 * case TRUE:
692 * fattr3 attributes;
693 * case FALSE:
694 * void;
695 * };
696 */
697static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
698{
699 __be32 *p;
700
701 p = xdr_inline_decode(xdr, 4);
702 if (unlikely(p == NULL))
703 goto out_overflow;
704 if (*p != xdr_zero)
705 return decode_fattr3(xdr, fattr);
706 return 0;
707out_overflow:
708 print_overflow_msg(__func__, xdr);
709 return -EIO;
710}
711
712/*
713 * wcc_attr
714 * struct wcc_attr {
715 * size3 size;
716 * nfstime3 mtime;
717 * nfstime3 ctime;
718 * };
719 */
720static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
721{
722 __be32 *p;
723
724 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
725 if (unlikely(p == NULL))
726 goto out_overflow;
f6048709
CL
727
728 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
3a1556e8 729 | NFS_ATTR_FATTR_PRECHANGE
f6048709
CL
730 | NFS_ATTR_FATTR_PREMTIME
731 | NFS_ATTR_FATTR_PRECTIME;
732
733 p = xdr_decode_size3(p, &fattr->pre_size);
734 p = xdr_decode_nfstime3(p, &fattr->pre_mtime);
735 xdr_decode_nfstime3(p, &fattr->pre_ctime);
3a1556e8 736 fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime);
f6048709 737
e4f93234
CL
738 return 0;
739out_overflow:
740 print_overflow_msg(__func__, xdr);
741 return -EIO;
742}
743
744/*
745 * pre_op_attr
746 * union pre_op_attr switch (bool attributes_follow) {
747 * case TRUE:
748 * wcc_attr attributes;
749 * case FALSE:
750 * void;
751 * };
752 *
753 * wcc_data
754 *
755 * struct wcc_data {
756 * pre_op_attr before;
757 * post_op_attr after;
758 * };
759 */
760static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
761{
762 __be32 *p;
763
764 p = xdr_inline_decode(xdr, 4);
765 if (unlikely(p == NULL))
766 goto out_overflow;
767 if (*p != xdr_zero)
768 return decode_wcc_attr(xdr, fattr);
769 return 0;
770out_overflow:
771 print_overflow_msg(__func__, xdr);
772 return -EIO;
773}
774
775static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
776{
777 int error;
778
779 error = decode_pre_op_attr(xdr, fattr);
780 if (unlikely(error))
781 goto out;
782 error = decode_post_op_attr(xdr, fattr);
783out:
784 return error;
785}
786
787/*
788 * post_op_fh3
789 *
790 * union post_op_fh3 switch (bool handle_follows) {
791 * case TRUE:
792 * nfs_fh3 handle;
793 * case FALSE:
794 * void;
795 * };
796 */
797static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
798{
799 __be32 *p = xdr_inline_decode(xdr, 4);
800 if (unlikely(p == NULL))
801 goto out_overflow;
802 if (*p != xdr_zero)
803 return decode_nfs_fh3(xdr, fh);
804 zero_nfs_fh3(fh);
805 return 0;
806out_overflow:
807 print_overflow_msg(__func__, xdr);
808 return -EIO;
809}
810
d9c407b1
CL
811/*
812 * diropargs3
813 *
814 * struct diropargs3 {
815 * nfs_fh3 dir;
816 * filename3 name;
817 * };
818 */
819static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
820 const char *name, u32 length)
821{
822 encode_nfs_fh3(xdr, fh);
823 encode_filename3(xdr, name, length);
824}
825
826
1da177e4 827/*
499ff710
CL
828 * NFSv3 XDR encode functions
829 *
830 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
831 * "NFS Version 3 Protocol Specification".
1da177e4
LT
832 */
833
d9c407b1
CL
834/*
835 * 3.3.1 GETATTR3args
836 *
837 * struct GETATTR3args {
838 * nfs_fh3 object;
839 * };
840 */
9f06c719
CL
841static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req,
842 struct xdr_stream *xdr,
843 const struct nfs_fh *fh)
d9c407b1 844{
9f06c719 845 encode_nfs_fh3(xdr, fh);
d9c407b1
CL
846}
847
d9c407b1
CL
848/*
849 * 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;
9d5a6434 872 xdr_encode_nfstime3(p, &args->guardtime);
d9c407b1
CL
873 } else {
874 p = xdr_reserve_space(xdr, 4);
875 *p = xdr_zero;
876 }
877}
878
9f06c719
CL
879static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
880 struct xdr_stream *xdr,
881 const struct nfs3_sattrargs *args)
d9c407b1 882{
9f06c719
CL
883 encode_nfs_fh3(xdr, args->fh);
884 encode_sattr3(xdr, args->sattr);
885 encode_sattrguard3(xdr, args);
d9c407b1
CL
886}
887
d9c407b1
CL
888/*
889 * 3.3.3 LOOKUP3args
890 *
891 * struct LOOKUP3args {
892 * diropargs3 what;
893 * };
894 */
9f06c719
CL
895static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req,
896 struct xdr_stream *xdr,
897 const struct nfs3_diropargs *args)
d9c407b1 898{
9f06c719 899 encode_diropargs3(xdr, args->fh, args->name, args->len);
d9c407b1
CL
900}
901
d9c407b1
CL
902/*
903 * 3.3.4 ACCESS3args
904 *
905 * struct ACCESS3args {
906 * nfs_fh3 object;
907 * uint32 access;
908 * };
909 */
910static void encode_access3args(struct xdr_stream *xdr,
911 const struct nfs3_accessargs *args)
912{
913 encode_nfs_fh3(xdr, args->fh);
914 encode_uint32(xdr, args->access);
915}
916
9f06c719
CL
917static void nfs3_xdr_enc_access3args(struct rpc_rqst *req,
918 struct xdr_stream *xdr,
919 const struct nfs3_accessargs *args)
d9c407b1 920{
9f06c719 921 encode_access3args(xdr, args);
d9c407b1
CL
922}
923
924/*
925 * 3.3.5 READLINK3args
926 *
927 * struct READLINK3args {
928 * nfs_fh3 symlink;
929 * };
930 */
9f06c719
CL
931static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
932 struct xdr_stream *xdr,
933 const struct nfs3_readlinkargs *args)
d9c407b1 934{
9f06c719 935 encode_nfs_fh3(xdr, args->fh);
d9c407b1
CL
936 prepare_reply_buffer(req, args->pages, args->pgbase,
937 args->pglen, NFS3_readlinkres_sz);
d9c407b1
CL
938}
939
d9c407b1
CL
940/*
941 * 3.3.6 READ3args
942 *
943 * struct READ3args {
944 * nfs_fh3 file;
945 * offset3 offset;
946 * count3 count;
947 * };
948 */
949static void encode_read3args(struct xdr_stream *xdr,
950 const struct nfs_readargs *args)
951{
952 __be32 *p;
953
954 encode_nfs_fh3(xdr, args->fh);
955
956 p = xdr_reserve_space(xdr, 8 + 4);
957 p = xdr_encode_hyper(p, args->offset);
958 *p = cpu_to_be32(args->count);
959}
960
9f06c719
CL
961static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
962 struct xdr_stream *xdr,
963 const struct nfs_readargs *args)
d9c407b1 964{
9f06c719 965 encode_read3args(xdr, args);
d9c407b1
CL
966 prepare_reply_buffer(req, args->pages, args->pgbase,
967 args->count, NFS3_readres_sz);
968 req->rq_rcv_buf.flags |= XDRBUF_READ;
d9c407b1
CL
969}
970
d9c407b1
CL
971/*
972 * 3.3.7 WRITE3args
973 *
974 * enum stable_how {
975 * UNSTABLE = 0,
976 * DATA_SYNC = 1,
977 * FILE_SYNC = 2
978 * };
979 *
980 * struct WRITE3args {
981 * nfs_fh3 file;
982 * offset3 offset;
983 * count3 count;
984 * stable_how stable;
985 * opaque data<>;
986 * };
987 */
988static void encode_write3args(struct xdr_stream *xdr,
989 const struct nfs_writeargs *args)
990{
991 __be32 *p;
992
993 encode_nfs_fh3(xdr, args->fh);
994
995 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
996 p = xdr_encode_hyper(p, args->offset);
997 *p++ = cpu_to_be32(args->count);
d9c407b1 998 *p++ = cpu_to_be32(args->stable);
d9c407b1
CL
999 *p = cpu_to_be32(args->count);
1000 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1001}
1002
9f06c719
CL
1003static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
1004 struct xdr_stream *xdr,
1005 const struct nfs_writeargs *args)
d9c407b1 1006{
9f06c719
CL
1007 encode_write3args(xdr, args);
1008 xdr->buf->flags |= XDRBUF_WRITE;
d9c407b1
CL
1009}
1010
d9c407b1
CL
1011/*
1012 * 3.3.8 CREATE3args
1013 *
1014 * enum createmode3 {
1015 * UNCHECKED = 0,
1016 * GUARDED = 1,
1017 * EXCLUSIVE = 2
1018 * };
1019 *
1020 * union createhow3 switch (createmode3 mode) {
1021 * case UNCHECKED:
1022 * case GUARDED:
1023 * sattr3 obj_attributes;
1024 * case EXCLUSIVE:
1025 * createverf3 verf;
1026 * };
1027 *
1028 * struct CREATE3args {
1029 * diropargs3 where;
1030 * createhow3 how;
1031 * };
1032 */
1033static void encode_createhow3(struct xdr_stream *xdr,
1034 const struct nfs3_createargs *args)
1035{
1036 encode_uint32(xdr, args->createmode);
1037 switch (args->createmode) {
1038 case NFS3_CREATE_UNCHECKED:
1039 case NFS3_CREATE_GUARDED:
1040 encode_sattr3(xdr, args->sattr);
1041 break;
1042 case NFS3_CREATE_EXCLUSIVE:
1043 encode_createverf3(xdr, args->verifier);
1044 break;
1045 default:
1046 BUG();
1047 }
1048}
1049
9f06c719
CL
1050static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
1051 struct xdr_stream *xdr,
1052 const struct nfs3_createargs *args)
d9c407b1 1053{
9f06c719
CL
1054 encode_diropargs3(xdr, args->fh, args->name, args->len);
1055 encode_createhow3(xdr, args);
d9c407b1
CL
1056}
1057
d9c407b1
CL
1058/*
1059 * 3.3.9 MKDIR3args
1060 *
1061 * struct MKDIR3args {
1062 * diropargs3 where;
1063 * sattr3 attributes;
1064 * };
1065 */
9f06c719
CL
1066static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
1067 struct xdr_stream *xdr,
1068 const struct nfs3_mkdirargs *args)
d9c407b1 1069{
9f06c719
CL
1070 encode_diropargs3(xdr, args->fh, args->name, args->len);
1071 encode_sattr3(xdr, args->sattr);
d9c407b1
CL
1072}
1073
d9c407b1
CL
1074/*
1075 * 3.3.10 SYMLINK3args
1076 *
1077 * struct symlinkdata3 {
1078 * sattr3 symlink_attributes;
1079 * nfspath3 symlink_data;
1080 * };
1081 *
1082 * struct SYMLINK3args {
1083 * diropargs3 where;
1084 * symlinkdata3 symlink;
1085 * };
1086 */
1087static void encode_symlinkdata3(struct xdr_stream *xdr,
1088 const struct nfs3_symlinkargs *args)
1089{
1090 encode_sattr3(xdr, args->sattr);
1091 encode_nfspath3(xdr, args->pages, args->pathlen);
1092}
1093
9f06c719
CL
1094static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
1095 struct xdr_stream *xdr,
1096 const struct nfs3_symlinkargs *args)
d9c407b1 1097{
9f06c719
CL
1098 encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
1099 encode_symlinkdata3(xdr, args);
d9c407b1
CL
1100}
1101
d9c407b1
CL
1102/*
1103 * 3.3.11 MKNOD3args
1104 *
1105 * struct devicedata3 {
1106 * sattr3 dev_attributes;
1107 * specdata3 spec;
1108 * };
1109 *
1110 * union mknoddata3 switch (ftype3 type) {
1111 * case NF3CHR:
1112 * case NF3BLK:
1113 * devicedata3 device;
1114 * case NF3SOCK:
1115 * case NF3FIFO:
1116 * sattr3 pipe_attributes;
1117 * default:
1118 * void;
1119 * };
1120 *
1121 * struct MKNOD3args {
1122 * diropargs3 where;
1123 * mknoddata3 what;
1124 * };
1125 */
1126static void encode_devicedata3(struct xdr_stream *xdr,
1127 const struct nfs3_mknodargs *args)
1128{
1129 encode_sattr3(xdr, args->sattr);
1130 encode_specdata3(xdr, args->rdev);
1131}
1132
1133static void encode_mknoddata3(struct xdr_stream *xdr,
1134 const struct nfs3_mknodargs *args)
1135{
1136 encode_ftype3(xdr, args->type);
1137 switch (args->type) {
1138 case NF3CHR:
1139 case NF3BLK:
1140 encode_devicedata3(xdr, args);
1141 break;
1142 case NF3SOCK:
1143 case NF3FIFO:
1144 encode_sattr3(xdr, args->sattr);
1145 break;
1146 case NF3REG:
1147 case NF3DIR:
1148 break;
1149 default:
1150 BUG();
1151 }
1152}
1153
9f06c719
CL
1154static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
1155 struct xdr_stream *xdr,
1156 const struct nfs3_mknodargs *args)
d9c407b1 1157{
9f06c719
CL
1158 encode_diropargs3(xdr, args->fh, args->name, args->len);
1159 encode_mknoddata3(xdr, args);
d9c407b1
CL
1160}
1161
1162/*
1163 * 3.3.12 REMOVE3args
1164 *
1165 * struct REMOVE3args {
1166 * diropargs3 object;
1167 * };
1168 */
9f06c719
CL
1169static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req,
1170 struct xdr_stream *xdr,
1171 const struct nfs_removeargs *args)
d9c407b1 1172{
9f06c719 1173 encode_diropargs3(xdr, args->fh, args->name.name, args->name.len);
d9c407b1
CL
1174}
1175
d9c407b1
CL
1176/*
1177 * 3.3.14 RENAME3args
1178 *
1179 * struct RENAME3args {
1180 * diropargs3 from;
1181 * diropargs3 to;
1182 * };
1183 */
9f06c719
CL
1184static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req,
1185 struct xdr_stream *xdr,
1186 const struct nfs_renameargs *args)
d9c407b1
CL
1187{
1188 const struct qstr *old = args->old_name;
1189 const struct qstr *new = args->new_name;
d9c407b1 1190
9f06c719
CL
1191 encode_diropargs3(xdr, args->old_dir, old->name, old->len);
1192 encode_diropargs3(xdr, args->new_dir, new->name, new->len);
d9c407b1
CL
1193}
1194
d9c407b1
CL
1195/*
1196 * 3.3.15 LINK3args
1197 *
1198 * struct LINK3args {
1199 * nfs_fh3 file;
1200 * diropargs3 link;
1201 * };
1202 */
9f06c719
CL
1203static void nfs3_xdr_enc_link3args(struct rpc_rqst *req,
1204 struct xdr_stream *xdr,
1205 const struct nfs3_linkargs *args)
d9c407b1 1206{
9f06c719
CL
1207 encode_nfs_fh3(xdr, args->fromfh);
1208 encode_diropargs3(xdr, args->tofh, args->toname, args->tolen);
d9c407b1
CL
1209}
1210
d9c407b1
CL
1211/*
1212 * 3.3.16 READDIR3args
1213 *
1214 * struct READDIR3args {
1215 * nfs_fh3 dir;
1216 * cookie3 cookie;
1217 * cookieverf3 cookieverf;
1218 * count3 count;
1219 * };
1220 */
1221static void encode_readdir3args(struct xdr_stream *xdr,
1222 const struct nfs3_readdirargs *args)
1223{
1224 __be32 *p;
1225
1226 encode_nfs_fh3(xdr, args->fh);
1227
1228 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1229 p = xdr_encode_cookie3(p, args->cookie);
1230 p = xdr_encode_cookieverf3(p, args->verf);
1231 *p = cpu_to_be32(args->count);
1232}
1233
9f06c719
CL
1234static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
1235 struct xdr_stream *xdr,
1236 const struct nfs3_readdirargs *args)
d9c407b1 1237{
9f06c719 1238 encode_readdir3args(xdr, args);
d9c407b1
CL
1239 prepare_reply_buffer(req, args->pages, 0,
1240 args->count, NFS3_readdirres_sz);
d9c407b1
CL
1241}
1242
1243/*
1244 * 3.3.17 READDIRPLUS3args
1245 *
1246 * struct READDIRPLUS3args {
1247 * nfs_fh3 dir;
1248 * cookie3 cookie;
1249 * cookieverf3 cookieverf;
1250 * count3 dircount;
1251 * count3 maxcount;
1252 * };
1253 */
1254static void encode_readdirplus3args(struct xdr_stream *xdr,
1255 const struct nfs3_readdirargs *args)
1256{
1257 __be32 *p;
1258
1259 encode_nfs_fh3(xdr, args->fh);
1260
1261 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1262 p = xdr_encode_cookie3(p, args->cookie);
1263 p = xdr_encode_cookieverf3(p, args->verf);
1264
1265 /*
1266 * readdirplus: need dircount + buffer size.
1267 * We just make sure we make dircount big enough
1268 */
1269 *p++ = cpu_to_be32(args->count >> 3);
1270
1271 *p = cpu_to_be32(args->count);
1272}
1273
9f06c719
CL
1274static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
1275 struct xdr_stream *xdr,
1276 const struct nfs3_readdirargs *args)
d9c407b1 1277{
9f06c719 1278 encode_readdirplus3args(xdr, args);
d9c407b1
CL
1279 prepare_reply_buffer(req, args->pages, 0,
1280 args->count, NFS3_readdirres_sz);
d9c407b1
CL
1281}
1282
d9c407b1
CL
1283/*
1284 * 3.3.21 COMMIT3args
1285 *
1286 * struct COMMIT3args {
1287 * nfs_fh3 file;
1288 * offset3 offset;
1289 * count3 count;
1290 * };
1291 */
1292static void encode_commit3args(struct xdr_stream *xdr,
0b7c0153 1293 const struct nfs_commitargs *args)
d9c407b1
CL
1294{
1295 __be32 *p;
1296
1297 encode_nfs_fh3(xdr, args->fh);
1298
1299 p = xdr_reserve_space(xdr, 8 + 4);
1300 p = xdr_encode_hyper(p, args->offset);
1301 *p = cpu_to_be32(args->count);
1302}
1303
9f06c719
CL
1304static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
1305 struct xdr_stream *xdr,
0b7c0153 1306 const struct nfs_commitargs *args)
d9c407b1 1307{
9f06c719 1308 encode_commit3args(xdr, args);
d9c407b1
CL
1309}
1310
b7fa0554 1311#ifdef CONFIG_NFS_V3_ACL
b7fa0554 1312
9f06c719
CL
1313static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
1314 struct xdr_stream *xdr,
1315 const struct nfs3_getaclargs *args)
d9c407b1 1316{
9f06c719
CL
1317 encode_nfs_fh3(xdr, args->fh);
1318 encode_uint32(xdr, args->mask);
d9c407b1
CL
1319 if (args->mask & (NFS_ACL | NFS_DFACL))
1320 prepare_reply_buffer(req, args->pages, 0,
1321 NFSACL_MAXPAGES << PAGE_SHIFT,
1322 ACL3_getaclres_sz);
d9c407b1
CL
1323}
1324
9f06c719
CL
1325static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
1326 struct xdr_stream *xdr,
1327 const struct nfs3_setaclargs *args)
d9c407b1 1328{
d9c407b1
CL
1329 unsigned int base;
1330 int error;
1331
9f06c719
CL
1332 encode_nfs_fh3(xdr, NFS_FH(args->inode));
1333 encode_uint32(xdr, args->mask);
ee5dc773
CL
1334
1335 base = req->rq_slen;
d9c407b1 1336 if (args->npages != 0)
9f06c719 1337 xdr_write_pages(xdr, args->pages, 0, args->len);
ee5dc773
CL
1338 else
1339 xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE);
d9c407b1 1340
9f06c719 1341 error = nfsacl_encode(xdr->buf, base, args->inode,
d9c407b1
CL
1342 (args->mask & NFS_ACL) ?
1343 args->acl_access : NULL, 1, 0);
1344 BUG_ON(error < 0);
9f06c719 1345 error = nfsacl_encode(xdr->buf, base + error, args->inode,
d9c407b1
CL
1346 (args->mask & NFS_DFACL) ?
1347 args->acl_default : NULL, 1,
1348 NFS_ACL_DEFAULT);
1349 BUG_ON(error < 0);
d9c407b1
CL
1350}
1351
b7fa0554
AG
1352#endif /* CONFIG_NFS_V3_ACL */
1353
1da177e4 1354/*
b2cdd9c9
CL
1355 * NFSv3 XDR decode functions
1356 *
1357 * NFSv3 result types are defined in section 3.3 of RFC 1813:
1358 * "NFS Version 3 Protocol Specification".
1da177e4 1359 */
1da177e4
LT
1360
1361/*
e4f93234
CL
1362 * 3.3.1 GETATTR3res
1363 *
1364 * struct GETATTR3resok {
1365 * fattr3 obj_attributes;
1366 * };
1367 *
1368 * union GETATTR3res switch (nfsstat3 status) {
1369 * case NFS3_OK:
1370 * GETATTR3resok resok;
1371 * default:
1372 * void;
1373 * };
1da177e4 1374 */
bf269551
CL
1375static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
1376 struct xdr_stream *xdr,
e4f93234 1377 struct nfs_fattr *result)
1da177e4 1378{
e4f93234
CL
1379 enum nfs_stat status;
1380 int error;
1381
bf269551 1382 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1383 if (unlikely(error))
1384 goto out;
1385 if (status != NFS3_OK)
1386 goto out_default;
bf269551 1387 error = decode_fattr3(xdr, result);
e4f93234
CL
1388out:
1389 return error;
1390out_default:
1391 return nfs_stat_to_errno(status);
1392}
1393
e4f93234
CL
1394/*
1395 * 3.3.2 SETATTR3res
1396 *
1397 * struct SETATTR3resok {
1398 * wcc_data obj_wcc;
1399 * };
1400 *
1401 * struct SETATTR3resfail {
1402 * wcc_data obj_wcc;
1403 * };
1404 *
1405 * union SETATTR3res switch (nfsstat3 status) {
1406 * case NFS3_OK:
1407 * SETATTR3resok resok;
1408 * default:
1409 * SETATTR3resfail resfail;
1410 * };
1411 */
bf269551
CL
1412static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
1413 struct xdr_stream *xdr,
e4f93234
CL
1414 struct nfs_fattr *result)
1415{
e4f93234
CL
1416 enum nfs_stat status;
1417 int error;
1418
bf269551 1419 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1420 if (unlikely(error))
1421 goto out;
bf269551 1422 error = decode_wcc_data(xdr, result);
e4f93234
CL
1423 if (unlikely(error))
1424 goto out;
1425 if (status != NFS3_OK)
1426 goto out_status;
1427out:
1428 return error;
1429out_status:
1430 return nfs_stat_to_errno(status);
1431}
1432
e4f93234
CL
1433/*
1434 * 3.3.3 LOOKUP3res
1435 *
1436 * struct LOOKUP3resok {
1437 * nfs_fh3 object;
1438 * post_op_attr obj_attributes;
1439 * post_op_attr dir_attributes;
1440 * };
1441 *
1442 * struct LOOKUP3resfail {
1443 * post_op_attr dir_attributes;
1444 * };
1445 *
1446 * union LOOKUP3res switch (nfsstat3 status) {
1447 * case NFS3_OK:
1448 * LOOKUP3resok resok;
1449 * default:
1450 * LOOKUP3resfail resfail;
1451 * };
1452 */
bf269551
CL
1453static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
1454 struct xdr_stream *xdr,
e4f93234
CL
1455 struct nfs3_diropres *result)
1456{
e4f93234
CL
1457 enum nfs_stat status;
1458 int error;
1459
bf269551 1460 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1461 if (unlikely(error))
1462 goto out;
1463 if (status != NFS3_OK)
1464 goto out_default;
bf269551 1465 error = decode_nfs_fh3(xdr, result->fh);
e4f93234
CL
1466 if (unlikely(error))
1467 goto out;
bf269551 1468 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
1469 if (unlikely(error))
1470 goto out;
bf269551 1471 error = decode_post_op_attr(xdr, result->dir_attr);
e4f93234
CL
1472out:
1473 return error;
1474out_default:
bf269551 1475 error = decode_post_op_attr(xdr, result->dir_attr);
e4f93234
CL
1476 if (unlikely(error))
1477 goto out;
1478 return nfs_stat_to_errno(status);
1479}
1480
e4f93234
CL
1481/*
1482 * 3.3.4 ACCESS3res
1483 *
1484 * struct ACCESS3resok {
1485 * post_op_attr obj_attributes;
1486 * uint32 access;
1487 * };
1488 *
1489 * struct ACCESS3resfail {
1490 * post_op_attr obj_attributes;
1491 * };
1492 *
1493 * union ACCESS3res switch (nfsstat3 status) {
1494 * case NFS3_OK:
1495 * ACCESS3resok resok;
1496 * default:
1497 * ACCESS3resfail resfail;
1498 * };
1499 */
bf269551
CL
1500static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
1501 struct xdr_stream *xdr,
e4f93234
CL
1502 struct nfs3_accessres *result)
1503{
e4f93234
CL
1504 enum nfs_stat status;
1505 int error;
1506
bf269551 1507 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1508 if (unlikely(error))
1509 goto out;
bf269551 1510 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
1511 if (unlikely(error))
1512 goto out;
1513 if (status != NFS3_OK)
1514 goto out_default;
bf269551 1515 error = decode_uint32(xdr, &result->access);
e4f93234
CL
1516out:
1517 return error;
1518out_default:
1519 return nfs_stat_to_errno(status);
1520}
1521
e4f93234
CL
1522/*
1523 * 3.3.5 READLINK3res
1524 *
1525 * struct READLINK3resok {
1526 * post_op_attr symlink_attributes;
1527 * nfspath3 data;
1528 * };
1529 *
1530 * struct READLINK3resfail {
1531 * post_op_attr symlink_attributes;
1532 * };
1533 *
1534 * union READLINK3res switch (nfsstat3 status) {
1535 * case NFS3_OK:
1536 * READLINK3resok resok;
1537 * default:
1538 * READLINK3resfail resfail;
1539 * };
1540 */
bf269551
CL
1541static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
1542 struct xdr_stream *xdr,
e4f93234
CL
1543 struct nfs_fattr *result)
1544{
e4f93234
CL
1545 enum nfs_stat status;
1546 int error;
1547
bf269551 1548 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1549 if (unlikely(error))
1550 goto out;
bf269551 1551 error = decode_post_op_attr(xdr, result);
e4f93234
CL
1552 if (unlikely(error))
1553 goto out;
1554 if (status != NFS3_OK)
1555 goto out_default;
bf269551 1556 error = decode_nfspath3(xdr);
e4f93234
CL
1557out:
1558 return error;
1559out_default:
1560 return nfs_stat_to_errno(status);
1561}
1562
e4f93234
CL
1563/*
1564 * 3.3.6 READ3res
1565 *
1566 * struct READ3resok {
1567 * post_op_attr file_attributes;
1568 * count3 count;
1569 * bool eof;
1570 * opaque data<>;
1571 * };
1572 *
1573 * struct READ3resfail {
1574 * post_op_attr file_attributes;
1575 * };
1576 *
1577 * union READ3res switch (nfsstat3 status) {
1578 * case NFS3_OK:
1579 * READ3resok resok;
1580 * default:
1581 * READ3resfail resfail;
1582 * };
1583 */
1584static int decode_read3resok(struct xdr_stream *xdr,
1585 struct nfs_readres *result)
1586{
1587 u32 eof, count, ocount, recvd;
1588 size_t hdrlen;
1589 __be32 *p;
1590
1591 p = xdr_inline_decode(xdr, 4 + 4 + 4);
1592 if (unlikely(p == NULL))
1593 goto out_overflow;
1594 count = be32_to_cpup(p++);
1595 eof = be32_to_cpup(p++);
1596 ocount = be32_to_cpup(p++);
1597 if (unlikely(ocount != count))
1598 goto out_mismatch;
1599 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1600 recvd = xdr->buf->len - hdrlen;
1601 if (unlikely(count > recvd))
1602 goto out_cheating;
1603
1604out:
1605 xdr_read_pages(xdr, count);
1606 result->eof = eof;
1607 result->count = count;
1608 return count;
1609out_mismatch:
1610 dprintk("NFS: READ count doesn't match length of opaque: "
1611 "count %u != ocount %u\n", count, ocount);
1612 return -EIO;
1613out_cheating:
1614 dprintk("NFS: server cheating in read result: "
1615 "count %u > recvd %u\n", count, recvd);
1616 count = recvd;
1617 eof = 0;
1618 goto out;
1619out_overflow:
1620 print_overflow_msg(__func__, xdr);
1621 return -EIO;
1622}
1623
bf269551 1624static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
e4f93234
CL
1625 struct nfs_readres *result)
1626{
e4f93234
CL
1627 enum nfs_stat status;
1628 int error;
1629
bf269551 1630 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1631 if (unlikely(error))
1632 goto out;
bf269551 1633 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
1634 if (unlikely(error))
1635 goto out;
1636 if (status != NFS3_OK)
1637 goto out_status;
bf269551 1638 error = decode_read3resok(xdr, result);
e4f93234
CL
1639out:
1640 return error;
1641out_status:
1642 return nfs_stat_to_errno(status);
1643}
1644
e4f93234
CL
1645/*
1646 * 3.3.7 WRITE3res
1647 *
1648 * enum stable_how {
1649 * UNSTABLE = 0,
1650 * DATA_SYNC = 1,
1651 * FILE_SYNC = 2
1652 * };
1653 *
1654 * struct WRITE3resok {
1655 * wcc_data file_wcc;
1656 * count3 count;
1657 * stable_how committed;
1658 * writeverf3 verf;
1659 * };
1660 *
1661 * struct WRITE3resfail {
1662 * wcc_data file_wcc;
1663 * };
1664 *
1665 * union WRITE3res switch (nfsstat3 status) {
1666 * case NFS3_OK:
1667 * WRITE3resok resok;
1668 * default:
1669 * WRITE3resfail resfail;
1670 * };
1671 */
1672static int decode_write3resok(struct xdr_stream *xdr,
1673 struct nfs_writeres *result)
1674{
1675 __be32 *p;
1676
1677 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
1678 if (unlikely(p == NULL))
1679 goto out_overflow;
1680 result->count = be32_to_cpup(p++);
1681 result->verf->committed = be32_to_cpup(p++);
1682 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
1683 goto out_badvalue;
1684 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
1685 return result->count;
1686out_badvalue:
1687 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
1688 return -EIO;
1689out_overflow:
1690 print_overflow_msg(__func__, xdr);
1691 return -EIO;
1692}
1693
bf269551 1694static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
e4f93234
CL
1695 struct nfs_writeres *result)
1696{
e4f93234
CL
1697 enum nfs_stat status;
1698 int error;
1699
bf269551 1700 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1701 if (unlikely(error))
1702 goto out;
bf269551 1703 error = decode_wcc_data(xdr, result->fattr);
e4f93234
CL
1704 if (unlikely(error))
1705 goto out;
1706 if (status != NFS3_OK)
1707 goto out_status;
bf269551 1708 error = decode_write3resok(xdr, result);
e4f93234
CL
1709out:
1710 return error;
1711out_status:
1712 return nfs_stat_to_errno(status);
1713}
1714
e4f93234
CL
1715/*
1716 * 3.3.8 CREATE3res
1717 *
1718 * struct CREATE3resok {
1719 * post_op_fh3 obj;
1720 * post_op_attr obj_attributes;
1721 * wcc_data dir_wcc;
1722 * };
1723 *
1724 * struct CREATE3resfail {
1725 * wcc_data dir_wcc;
1726 * };
1727 *
1728 * union CREATE3res switch (nfsstat3 status) {
1729 * case NFS3_OK:
1730 * CREATE3resok resok;
1731 * default:
1732 * CREATE3resfail resfail;
1733 * };
1734 */
1735static int decode_create3resok(struct xdr_stream *xdr,
1736 struct nfs3_diropres *result)
1737{
1738 int error;
1739
1740 error = decode_post_op_fh3(xdr, result->fh);
1741 if (unlikely(error))
1742 goto out;
1743 error = decode_post_op_attr(xdr, result->fattr);
1744 if (unlikely(error))
1745 goto out;
1746 /* The server isn't required to return a file handle.
1747 * If it didn't, force the client to perform a LOOKUP
1748 * to determine the correct file handle and attribute
1749 * values for the new object. */
1750 if (result->fh->size == 0)
1751 result->fattr->valid = 0;
1752 error = decode_wcc_data(xdr, result->dir_attr);
1753out:
1754 return error;
1755}
1756
bf269551
CL
1757static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
1758 struct xdr_stream *xdr,
e4f93234
CL
1759 struct nfs3_diropres *result)
1760{
e4f93234
CL
1761 enum nfs_stat status;
1762 int error;
1763
bf269551 1764 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1765 if (unlikely(error))
1766 goto out;
1767 if (status != NFS3_OK)
1768 goto out_default;
bf269551 1769 error = decode_create3resok(xdr, result);
e4f93234
CL
1770out:
1771 return error;
1772out_default:
bf269551 1773 error = decode_wcc_data(xdr, result->dir_attr);
e4f93234
CL
1774 if (unlikely(error))
1775 goto out;
1776 return nfs_stat_to_errno(status);
1777}
1778
1779/*
1780 * 3.3.12 REMOVE3res
1781 *
1782 * struct REMOVE3resok {
1783 * wcc_data dir_wcc;
1784 * };
1785 *
1786 * struct REMOVE3resfail {
1787 * wcc_data dir_wcc;
1788 * };
1789 *
1790 * union REMOVE3res switch (nfsstat3 status) {
1791 * case NFS3_OK:
1792 * REMOVE3resok resok;
1793 * default:
1794 * REMOVE3resfail resfail;
1795 * };
1796 */
bf269551
CL
1797static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
1798 struct xdr_stream *xdr,
e4f93234
CL
1799 struct nfs_removeres *result)
1800{
e4f93234
CL
1801 enum nfs_stat status;
1802 int error;
1803
bf269551 1804 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1805 if (unlikely(error))
1806 goto out;
bf269551 1807 error = decode_wcc_data(xdr, result->dir_attr);
e4f93234
CL
1808 if (unlikely(error))
1809 goto out;
1810 if (status != NFS3_OK)
1811 goto out_status;
1812out:
1813 return error;
1814out_status:
1815 return nfs_stat_to_errno(status);
1816}
1817
e4f93234
CL
1818/*
1819 * 3.3.14 RENAME3res
1820 *
1821 * struct RENAME3resok {
1822 * wcc_data fromdir_wcc;
1823 * wcc_data todir_wcc;
1824 * };
1825 *
1826 * struct RENAME3resfail {
1827 * wcc_data fromdir_wcc;
1828 * wcc_data todir_wcc;
1829 * };
1830 *
1831 * union RENAME3res switch (nfsstat3 status) {
1832 * case NFS3_OK:
1833 * RENAME3resok resok;
1834 * default:
1835 * RENAME3resfail resfail;
1836 * };
1837 */
bf269551
CL
1838static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
1839 struct xdr_stream *xdr,
e4f93234
CL
1840 struct nfs_renameres *result)
1841{
e4f93234
CL
1842 enum nfs_stat status;
1843 int error;
1844
bf269551 1845 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1846 if (unlikely(error))
1847 goto out;
bf269551 1848 error = decode_wcc_data(xdr, result->old_fattr);
e4f93234
CL
1849 if (unlikely(error))
1850 goto out;
bf269551 1851 error = decode_wcc_data(xdr, result->new_fattr);
e4f93234
CL
1852 if (unlikely(error))
1853 goto out;
1854 if (status != NFS3_OK)
1855 goto out_status;
1856out:
1857 return error;
1858out_status:
1859 return nfs_stat_to_errno(status);
1860}
1861
e4f93234
CL
1862/*
1863 * 3.3.15 LINK3res
1864 *
1865 * struct LINK3resok {
1866 * post_op_attr file_attributes;
1867 * wcc_data linkdir_wcc;
1868 * };
1869 *
1870 * struct LINK3resfail {
1871 * post_op_attr file_attributes;
1872 * wcc_data linkdir_wcc;
1873 * };
1874 *
1875 * union LINK3res switch (nfsstat3 status) {
1876 * case NFS3_OK:
1877 * LINK3resok resok;
1878 * default:
1879 * LINK3resfail resfail;
1880 * };
1881 */
bf269551 1882static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
e4f93234
CL
1883 struct nfs3_linkres *result)
1884{
e4f93234
CL
1885 enum nfs_stat status;
1886 int error;
1887
bf269551 1888 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
1889 if (unlikely(error))
1890 goto out;
bf269551 1891 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
1892 if (unlikely(error))
1893 goto out;
bf269551 1894 error = decode_wcc_data(xdr, result->dir_attr);
e4f93234
CL
1895 if (unlikely(error))
1896 goto out;
1897 if (status != NFS3_OK)
1898 goto out_status;
1899out:
1900 return error;
1901out_status:
1902 return nfs_stat_to_errno(status);
1903}
1904
1905/**
1906 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
1907 * the local page cache
1908 * @xdr: XDR stream where entry resides
1909 * @entry: buffer to fill in with entry data
e4f93234
CL
1910 * @plus: boolean indicating whether this should be a readdirplus entry
1911 *
573c4e1e
CL
1912 * Returns zero if successful, otherwise a negative errno value is
1913 * returned.
e4f93234
CL
1914 *
1915 * This function is not invoked during READDIR reply decoding, but
1916 * rather whenever an application invokes the getdents(2) system call
1917 * on a directory already in our cache.
1918 *
1919 * 3.3.16 entry3
1920 *
1921 * struct entry3 {
1922 * fileid3 fileid;
1923 * filename3 name;
1924 * cookie3 cookie;
1925 * fhandle3 filehandle;
1926 * post_op_attr3 attributes;
1927 * entry3 *nextentry;
1928 * };
1929 *
1930 * 3.3.17 entryplus3
1931 * struct entryplus3 {
1932 * fileid3 fileid;
1933 * filename3 name;
1934 * cookie3 cookie;
1935 * post_op_attr name_attributes;
1936 * post_op_fh3 name_handle;
1937 * entryplus3 *nextentry;
1938 * };
1939 */
573c4e1e
CL
1940int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1941 int plus)
e4f93234
CL
1942{
1943 struct nfs_entry old = *entry;
1944 __be32 *p;
1945 int error;
1946
1947 p = xdr_inline_decode(xdr, 4);
1948 if (unlikely(p == NULL))
1949 goto out_overflow;
1950 if (*p == xdr_zero) {
1951 p = xdr_inline_decode(xdr, 4);
1952 if (unlikely(p == NULL))
1953 goto out_overflow;
1954 if (*p == xdr_zero)
573c4e1e 1955 return -EAGAIN;
e4f93234 1956 entry->eof = 1;
573c4e1e 1957 return -EBADCOOKIE;
e4f93234
CL
1958 }
1959
1960 error = decode_fileid3(xdr, &entry->ino);
1961 if (unlikely(error))
573c4e1e 1962 return error;
e4f93234
CL
1963
1964 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
1965 if (unlikely(error))
573c4e1e 1966 return error;
e4f93234
CL
1967
1968 entry->prev_cookie = entry->cookie;
1969 error = decode_cookie3(xdr, &entry->cookie);
1970 if (unlikely(error))
573c4e1e 1971 return error;
e4f93234
CL
1972
1973 entry->d_type = DT_UNKNOWN;
1974
1975 if (plus) {
1976 entry->fattr->valid = 0;
1977 error = decode_post_op_attr(xdr, entry->fattr);
1978 if (unlikely(error))
573c4e1e 1979 return error;
e4f93234
CL
1980 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
1981 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1982
1983 /* In fact, a post_op_fh3: */
1984 p = xdr_inline_decode(xdr, 4);
1985 if (unlikely(p == NULL))
1986 goto out_overflow;
1987 if (*p != xdr_zero) {
1988 error = decode_nfs_fh3(xdr, entry->fh);
1989 if (unlikely(error)) {
1990 if (error == -E2BIG)
1991 goto out_truncated;
573c4e1e 1992 return error;
e4f93234
CL
1993 }
1994 } else
1995 zero_nfs_fh3(entry->fh);
1996 }
1997
573c4e1e 1998 return 0;
e4f93234
CL
1999
2000out_overflow:
2001 print_overflow_msg(__func__, xdr);
573c4e1e 2002 return -EAGAIN;
e4f93234
CL
2003out_truncated:
2004 dprintk("NFS: directory entry contains invalid file handle\n");
2005 *entry = old;
573c4e1e 2006 return -EAGAIN;
e4f93234
CL
2007}
2008
2009/*
2010 * 3.3.16 READDIR3res
2011 *
2012 * struct dirlist3 {
2013 * entry3 *entries;
2014 * bool eof;
2015 * };
2016 *
2017 * struct READDIR3resok {
2018 * post_op_attr dir_attributes;
2019 * cookieverf3 cookieverf;
2020 * dirlist3 reply;
2021 * };
2022 *
2023 * struct READDIR3resfail {
2024 * post_op_attr dir_attributes;
2025 * };
2026 *
2027 * union READDIR3res switch (nfsstat3 status) {
2028 * case NFS3_OK:
2029 * READDIR3resok resok;
2030 * default:
2031 * READDIR3resfail resfail;
2032 * };
2033 *
2034 * Read the directory contents into the page cache, but otherwise
2035 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2036 * during subsequent nfs_readdir() calls.
2037 */
2038static int decode_dirlist3(struct xdr_stream *xdr)
2039{
2040 u32 recvd, pglen;
2041 size_t hdrlen;
2042
2043 pglen = xdr->buf->page_len;
2044 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2045 recvd = xdr->buf->len - hdrlen;
2046 if (unlikely(pglen > recvd))
2047 goto out_cheating;
2048out:
2049 xdr_read_pages(xdr, pglen);
2050 return pglen;
2051out_cheating:
2052 dprintk("NFS: server cheating in readdir result: "
2053 "pglen %u > recvd %u\n", pglen, recvd);
2054 pglen = recvd;
2055 goto out;
2056}
2057
2058static int decode_readdir3resok(struct xdr_stream *xdr,
2059 struct nfs3_readdirres *result)
2060{
2061 int error;
2062
2063 error = decode_post_op_attr(xdr, result->dir_attr);
2064 if (unlikely(error))
2065 goto out;
2066 /* XXX: do we need to check if result->verf != NULL ? */
2067 error = decode_cookieverf3(xdr, result->verf);
2068 if (unlikely(error))
2069 goto out;
2070 error = decode_dirlist3(xdr);
2071out:
2072 return error;
2073}
2074
bf269551
CL
2075static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
2076 struct xdr_stream *xdr,
e4f93234
CL
2077 struct nfs3_readdirres *result)
2078{
e4f93234
CL
2079 enum nfs_stat status;
2080 int error;
2081
bf269551 2082 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2083 if (unlikely(error))
2084 goto out;
2085 if (status != NFS3_OK)
2086 goto out_default;
bf269551 2087 error = decode_readdir3resok(xdr, result);
e4f93234
CL
2088out:
2089 return error;
2090out_default:
bf269551 2091 error = decode_post_op_attr(xdr, result->dir_attr);
e4f93234
CL
2092 if (unlikely(error))
2093 goto out;
2094 return nfs_stat_to_errno(status);
2095}
2096
e4f93234
CL
2097/*
2098 * 3.3.18 FSSTAT3res
2099 *
2100 * struct FSSTAT3resok {
2101 * post_op_attr obj_attributes;
2102 * size3 tbytes;
2103 * size3 fbytes;
2104 * size3 abytes;
2105 * size3 tfiles;
2106 * size3 ffiles;
2107 * size3 afiles;
2108 * uint32 invarsec;
2109 * };
2110 *
2111 * struct FSSTAT3resfail {
2112 * post_op_attr obj_attributes;
2113 * };
2114 *
2115 * union FSSTAT3res switch (nfsstat3 status) {
2116 * case NFS3_OK:
2117 * FSSTAT3resok resok;
2118 * default:
2119 * FSSTAT3resfail resfail;
2120 * };
2121 */
2122static int decode_fsstat3resok(struct xdr_stream *xdr,
2123 struct nfs_fsstat *result)
2124{
2125 __be32 *p;
2126
2127 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2128 if (unlikely(p == NULL))
2129 goto out_overflow;
2130 p = xdr_decode_size3(p, &result->tbytes);
2131 p = xdr_decode_size3(p, &result->fbytes);
2132 p = xdr_decode_size3(p, &result->abytes);
2133 p = xdr_decode_size3(p, &result->tfiles);
2134 p = xdr_decode_size3(p, &result->ffiles);
2135 xdr_decode_size3(p, &result->afiles);
2136 /* ignore invarsec */
2137 return 0;
2138out_overflow:
2139 print_overflow_msg(__func__, xdr);
2140 return -EIO;
2141}
2142
bf269551
CL
2143static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
2144 struct xdr_stream *xdr,
e4f93234
CL
2145 struct nfs_fsstat *result)
2146{
e4f93234
CL
2147 enum nfs_stat status;
2148 int error;
2149
bf269551 2150 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2151 if (unlikely(error))
2152 goto out;
bf269551 2153 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
2154 if (unlikely(error))
2155 goto out;
2156 if (status != NFS3_OK)
2157 goto out_status;
bf269551 2158 error = decode_fsstat3resok(xdr, result);
e4f93234
CL
2159out:
2160 return error;
2161out_status:
2162 return nfs_stat_to_errno(status);
2163}
2164
e4f93234
CL
2165/*
2166 * 3.3.19 FSINFO3res
2167 *
2168 * struct FSINFO3resok {
2169 * post_op_attr obj_attributes;
2170 * uint32 rtmax;
2171 * uint32 rtpref;
2172 * uint32 rtmult;
2173 * uint32 wtmax;
2174 * uint32 wtpref;
2175 * uint32 wtmult;
2176 * uint32 dtpref;
2177 * size3 maxfilesize;
2178 * nfstime3 time_delta;
2179 * uint32 properties;
2180 * };
2181 *
2182 * struct FSINFO3resfail {
2183 * post_op_attr obj_attributes;
2184 * };
2185 *
2186 * union FSINFO3res switch (nfsstat3 status) {
2187 * case NFS3_OK:
2188 * FSINFO3resok resok;
2189 * default:
2190 * FSINFO3resfail resfail;
2191 * };
2192 */
2193static int decode_fsinfo3resok(struct xdr_stream *xdr,
2194 struct nfs_fsinfo *result)
2195{
2196 __be32 *p;
2197
2198 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2199 if (unlikely(p == NULL))
2200 goto out_overflow;
2201 result->rtmax = be32_to_cpup(p++);
2202 result->rtpref = be32_to_cpup(p++);
2203 result->rtmult = be32_to_cpup(p++);
2204 result->wtmax = be32_to_cpup(p++);
2205 result->wtpref = be32_to_cpup(p++);
2206 result->wtmult = be32_to_cpup(p++);
2207 result->dtpref = be32_to_cpup(p++);
2208 p = xdr_decode_size3(p, &result->maxfilesize);
f6048709 2209 xdr_decode_nfstime3(p, &result->time_delta);
e4f93234
CL
2210
2211 /* ignore properties */
2212 result->lease_time = 0;
2213 return 0;
2214out_overflow:
2215 print_overflow_msg(__func__, xdr);
2216 return -EIO;
2217}
2218
bf269551
CL
2219static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
2220 struct xdr_stream *xdr,
e4f93234
CL
2221 struct nfs_fsinfo *result)
2222{
e4f93234
CL
2223 enum nfs_stat status;
2224 int error;
2225
bf269551 2226 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2227 if (unlikely(error))
2228 goto out;
bf269551 2229 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
2230 if (unlikely(error))
2231 goto out;
2232 if (status != NFS3_OK)
2233 goto out_status;
bf269551 2234 error = decode_fsinfo3resok(xdr, result);
e4f93234
CL
2235out:
2236 return error;
2237out_status:
2238 return nfs_stat_to_errno(status);
2239}
2240
e4f93234
CL
2241/*
2242 * 3.3.20 PATHCONF3res
2243 *
2244 * struct PATHCONF3resok {
2245 * post_op_attr obj_attributes;
2246 * uint32 linkmax;
2247 * uint32 name_max;
2248 * bool no_trunc;
2249 * bool chown_restricted;
2250 * bool case_insensitive;
2251 * bool case_preserving;
2252 * };
2253 *
2254 * struct PATHCONF3resfail {
2255 * post_op_attr obj_attributes;
2256 * };
2257 *
2258 * union PATHCONF3res switch (nfsstat3 status) {
2259 * case NFS3_OK:
2260 * PATHCONF3resok resok;
2261 * default:
2262 * PATHCONF3resfail resfail;
2263 * };
2264 */
2265static int decode_pathconf3resok(struct xdr_stream *xdr,
2266 struct nfs_pathconf *result)
2267{
2268 __be32 *p;
2269
2270 p = xdr_inline_decode(xdr, 4 * 6);
2271 if (unlikely(p == NULL))
2272 goto out_overflow;
2273 result->max_link = be32_to_cpup(p++);
2274 result->max_namelen = be32_to_cpup(p);
2275 /* ignore remaining fields */
2276 return 0;
2277out_overflow:
2278 print_overflow_msg(__func__, xdr);
2279 return -EIO;
2280}
2281
bf269551
CL
2282static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
2283 struct xdr_stream *xdr,
e4f93234
CL
2284 struct nfs_pathconf *result)
2285{
e4f93234
CL
2286 enum nfs_stat status;
2287 int error;
2288
bf269551 2289 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2290 if (unlikely(error))
2291 goto out;
bf269551 2292 error = decode_post_op_attr(xdr, result->fattr);
e4f93234
CL
2293 if (unlikely(error))
2294 goto out;
2295 if (status != NFS3_OK)
2296 goto out_status;
bf269551 2297 error = decode_pathconf3resok(xdr, result);
e4f93234
CL
2298out:
2299 return error;
2300out_status:
2301 return nfs_stat_to_errno(status);
2302}
2303
e4f93234
CL
2304/*
2305 * 3.3.21 COMMIT3res
2306 *
2307 * struct COMMIT3resok {
2308 * wcc_data file_wcc;
2309 * writeverf3 verf;
2310 * };
2311 *
2312 * struct COMMIT3resfail {
2313 * wcc_data file_wcc;
2314 * };
2315 *
2316 * union COMMIT3res switch (nfsstat3 status) {
2317 * case NFS3_OK:
2318 * COMMIT3resok resok;
2319 * default:
2320 * COMMIT3resfail resfail;
2321 * };
2322 */
bf269551
CL
2323static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
2324 struct xdr_stream *xdr,
0b7c0153 2325 struct nfs_commitres *result)
e4f93234 2326{
e4f93234
CL
2327 enum nfs_stat status;
2328 int error;
2329
bf269551 2330 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2331 if (unlikely(error))
2332 goto out;
bf269551 2333 error = decode_wcc_data(xdr, result->fattr);
e4f93234
CL
2334 if (unlikely(error))
2335 goto out;
2336 if (status != NFS3_OK)
2337 goto out_status;
bf269551 2338 error = decode_writeverf3(xdr, result->verf->verifier);
e4f93234
CL
2339out:
2340 return error;
2341out_status:
2342 return nfs_stat_to_errno(status);
2343}
2344
b7fa0554 2345#ifdef CONFIG_NFS_V3_ACL
b7fa0554 2346
e4f93234
CL
2347static inline int decode_getacl3resok(struct xdr_stream *xdr,
2348 struct nfs3_getaclres *result)
2349{
2350 struct posix_acl **acl;
2351 unsigned int *aclcnt;
2352 size_t hdrlen;
2353 int error;
2354
2355 error = decode_post_op_attr(xdr, result->fattr);
2356 if (unlikely(error))
2357 goto out;
2358 error = decode_uint32(xdr, &result->mask);
2359 if (unlikely(error))
2360 goto out;
2361 error = -EINVAL;
2362 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2363 goto out;
2364
2365 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2366
2367 acl = NULL;
2368 if (result->mask & NFS_ACL)
2369 acl = &result->acl_access;
2370 aclcnt = NULL;
2371 if (result->mask & NFS_ACLCNT)
2372 aclcnt = &result->acl_access_count;
2373 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2374 if (unlikely(error <= 0))
2375 goto out;
2376
2377 acl = NULL;
2378 if (result->mask & NFS_DFACL)
2379 acl = &result->acl_default;
2380 aclcnt = NULL;
2381 if (result->mask & NFS_DFACLCNT)
2382 aclcnt = &result->acl_default_count;
2383 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2384 if (unlikely(error <= 0))
2385 return error;
2386 error = 0;
2387out:
2388 return error;
2389}
2390
bf269551
CL
2391static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req,
2392 struct xdr_stream *xdr,
e4f93234
CL
2393 struct nfs3_getaclres *result)
2394{
e4f93234
CL
2395 enum nfs_stat status;
2396 int error;
2397
bf269551 2398 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2399 if (unlikely(error))
2400 goto out;
2401 if (status != NFS3_OK)
2402 goto out_default;
bf269551 2403 error = decode_getacl3resok(xdr, result);
e4f93234
CL
2404out:
2405 return error;
2406out_default:
2407 return nfs_stat_to_errno(status);
2408}
2409
bf269551
CL
2410static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
2411 struct xdr_stream *xdr,
e4f93234
CL
2412 struct nfs_fattr *result)
2413{
e4f93234
CL
2414 enum nfs_stat status;
2415 int error;
2416
bf269551 2417 error = decode_nfsstat3(xdr, &status);
e4f93234
CL
2418 if (unlikely(error))
2419 goto out;
2420 if (status != NFS3_OK)
2421 goto out_default;
bf269551 2422 error = decode_post_op_attr(xdr, result);
e4f93234
CL
2423out:
2424 return error;
2425out_default:
2426 return nfs_stat_to_errno(status);
2427}
2428
b7fa0554
AG
2429#endif /* CONFIG_NFS_V3_ACL */
2430
1da177e4
LT
2431#define PROC(proc, argtype, restype, timer) \
2432[NFS3PROC_##proc] = { \
2433 .p_proc = NFS3PROC_##proc, \
9f06c719 2434 .p_encode = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args, \
bf269551 2435 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res, \
ad96b5b5 2436 .p_arglen = NFS3_##argtype##args_sz, \
f5fc3c50 2437 .p_replen = NFS3_##restype##res_sz, \
cc0175c1
CL
2438 .p_timer = timer, \
2439 .p_statidx = NFS3PROC_##proc, \
2440 .p_name = #proc, \
1da177e4
LT
2441 }
2442
2443struct rpc_procinfo nfs3_procedures[] = {
f5fc3c50
CL
2444 PROC(GETATTR, getattr, getattr, 1),
2445 PROC(SETATTR, setattr, setattr, 0),
2446 PROC(LOOKUP, lookup, lookup, 2),
2447 PROC(ACCESS, access, access, 1),
2448 PROC(READLINK, readlink, readlink, 3),
2449 PROC(READ, read, read, 3),
2450 PROC(WRITE, write, write, 4),
2451 PROC(CREATE, create, create, 0),
2452 PROC(MKDIR, mkdir, create, 0),
2453 PROC(SYMLINK, symlink, create, 0),
2454 PROC(MKNOD, mknod, create, 0),
2455 PROC(REMOVE, remove, remove, 0),
2456 PROC(RMDIR, lookup, setattr, 0),
2457 PROC(RENAME, rename, rename, 0),
2458 PROC(LINK, link, link, 0),
2459 PROC(READDIR, readdir, readdir, 3),
2460 PROC(READDIRPLUS, readdirplus, readdir, 3),
2461 PROC(FSSTAT, getattr, fsstat, 0),
2462 PROC(FSINFO, getattr, fsinfo, 0),
2463 PROC(PATHCONF, getattr, pathconf, 0),
2464 PROC(COMMIT, commit, commit, 5),
1da177e4
LT
2465};
2466
a613fa16 2467const struct rpc_version nfs_version3 = {
1da177e4 2468 .number = 3,
e8c96f8c 2469 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1da177e4
LT
2470 .procs = nfs3_procedures
2471};
2472
b7fa0554
AG
2473#ifdef CONFIG_NFS_V3_ACL
2474static struct rpc_procinfo nfs3_acl_procedures[] = {
2475 [ACLPROC3_GETACL] = {
2476 .p_proc = ACLPROC3_GETACL,
9f06c719 2477 .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args,
bf269551 2478 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res,
2bea90d4
CL
2479 .p_arglen = ACL3_getaclargs_sz,
2480 .p_replen = ACL3_getaclres_sz,
b7fa0554 2481 .p_timer = 1,
cc0175c1 2482 .p_name = "GETACL",
b7fa0554
AG
2483 },
2484 [ACLPROC3_SETACL] = {
2485 .p_proc = ACLPROC3_SETACL,
9f06c719 2486 .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args,
bf269551 2487 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res,
2bea90d4
CL
2488 .p_arglen = ACL3_setaclargs_sz,
2489 .p_replen = ACL3_setaclres_sz,
b7fa0554 2490 .p_timer = 0,
cc0175c1 2491 .p_name = "SETACL",
b7fa0554
AG
2492 },
2493};
2494
a613fa16 2495const struct rpc_version nfsacl_version3 = {
b7fa0554
AG
2496 .number = 3,
2497 .nrprocs = sizeof(nfs3_acl_procedures)/
2498 sizeof(nfs3_acl_procedures[0]),
2499 .procs = nfs3_acl_procedures,
2500};
2501#endif /* CONFIG_NFS_V3_ACL */