NFS: Pass mntfh as part of the nfs_mount_info structure
[deliverable/linux.git] / fs / nfs / nfs3xdr.c
... / ...
CommitLineData
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>
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>
22#include <linux/nfsacl.h>
23#include "internal.h"
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
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)
40#define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
41#define NFS3_wcc_attr_sz (6)
42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
45#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
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)
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)
56#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
57#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
58#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
59#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
60#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
61#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
63#define NFS3_commitargs_sz (NFS3_fh_sz+3)
64
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)
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
82#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
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))
87#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
88
89/*
90 * Map file type to S_IFMT bits
91 */
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,
101};
102
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
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
128
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
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 */
179static __be32 *xdr_decode_fileid3(__be32 *p, u64 *fileid)
180{
181 return xdr_decode_hyper(p, fileid);
182}
183
184static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
185{
186 return decode_uint64(xdr, fileid);
187}
188
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
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
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
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
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
287static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
288{
289 return decode_uint64(xdr, cookie);
290}
291
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
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
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
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
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
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
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
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
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
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
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
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
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
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;
630}
631
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{
653 umode_t fmode;
654 __be32 *p;
655
656 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
657 if (unlikely(p == NULL))
658 goto out_overflow;
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);
678 fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
679
680 fattr->valid |= NFS_ATTR_FATTR_V3;
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;
727
728 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
729 | NFS_ATTR_FATTR_PRECHANGE
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);
736 fattr->pre_change_attr = nfs_timespec_to_change_attr(&fattr->pre_ctime);
737
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
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
827/*
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".
832 */
833
834/*
835 * 3.3.1 GETATTR3args
836 *
837 * struct GETATTR3args {
838 * nfs_fh3 object;
839 * };
840 */
841static void nfs3_xdr_enc_getattr3args(struct rpc_rqst *req,
842 struct xdr_stream *xdr,
843 const struct nfs_fh *fh)
844{
845 encode_nfs_fh3(xdr, fh);
846}
847
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;
872 xdr_encode_nfstime3(p, &args->guardtime);
873 } else {
874 p = xdr_reserve_space(xdr, 4);
875 *p = xdr_zero;
876 }
877}
878
879static void nfs3_xdr_enc_setattr3args(struct rpc_rqst *req,
880 struct xdr_stream *xdr,
881 const struct nfs3_sattrargs *args)
882{
883 encode_nfs_fh3(xdr, args->fh);
884 encode_sattr3(xdr, args->sattr);
885 encode_sattrguard3(xdr, args);
886}
887
888/*
889 * 3.3.3 LOOKUP3args
890 *
891 * struct LOOKUP3args {
892 * diropargs3 what;
893 * };
894 */
895static void nfs3_xdr_enc_lookup3args(struct rpc_rqst *req,
896 struct xdr_stream *xdr,
897 const struct nfs3_diropargs *args)
898{
899 encode_diropargs3(xdr, args->fh, args->name, args->len);
900}
901
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
917static void nfs3_xdr_enc_access3args(struct rpc_rqst *req,
918 struct xdr_stream *xdr,
919 const struct nfs3_accessargs *args)
920{
921 encode_access3args(xdr, args);
922}
923
924/*
925 * 3.3.5 READLINK3args
926 *
927 * struct READLINK3args {
928 * nfs_fh3 symlink;
929 * };
930 */
931static void nfs3_xdr_enc_readlink3args(struct rpc_rqst *req,
932 struct xdr_stream *xdr,
933 const struct nfs3_readlinkargs *args)
934{
935 encode_nfs_fh3(xdr, args->fh);
936 prepare_reply_buffer(req, args->pages, args->pgbase,
937 args->pglen, NFS3_readlinkres_sz);
938}
939
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
961static void nfs3_xdr_enc_read3args(struct rpc_rqst *req,
962 struct xdr_stream *xdr,
963 const struct nfs_readargs *args)
964{
965 encode_read3args(xdr, args);
966 prepare_reply_buffer(req, args->pages, args->pgbase,
967 args->count, NFS3_readres_sz);
968 req->rq_rcv_buf.flags |= XDRBUF_READ;
969}
970
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);
998 *p++ = cpu_to_be32(args->stable);
999 *p = cpu_to_be32(args->count);
1000 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1001}
1002
1003static void nfs3_xdr_enc_write3args(struct rpc_rqst *req,
1004 struct xdr_stream *xdr,
1005 const struct nfs_writeargs *args)
1006{
1007 encode_write3args(xdr, args);
1008 xdr->buf->flags |= XDRBUF_WRITE;
1009}
1010
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
1050static void nfs3_xdr_enc_create3args(struct rpc_rqst *req,
1051 struct xdr_stream *xdr,
1052 const struct nfs3_createargs *args)
1053{
1054 encode_diropargs3(xdr, args->fh, args->name, args->len);
1055 encode_createhow3(xdr, args);
1056}
1057
1058/*
1059 * 3.3.9 MKDIR3args
1060 *
1061 * struct MKDIR3args {
1062 * diropargs3 where;
1063 * sattr3 attributes;
1064 * };
1065 */
1066static void nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req,
1067 struct xdr_stream *xdr,
1068 const struct nfs3_mkdirargs *args)
1069{
1070 encode_diropargs3(xdr, args->fh, args->name, args->len);
1071 encode_sattr3(xdr, args->sattr);
1072}
1073
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
1094static void nfs3_xdr_enc_symlink3args(struct rpc_rqst *req,
1095 struct xdr_stream *xdr,
1096 const struct nfs3_symlinkargs *args)
1097{
1098 encode_diropargs3(xdr, args->fromfh, args->fromname, args->fromlen);
1099 encode_symlinkdata3(xdr, args);
1100}
1101
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
1154static void nfs3_xdr_enc_mknod3args(struct rpc_rqst *req,
1155 struct xdr_stream *xdr,
1156 const struct nfs3_mknodargs *args)
1157{
1158 encode_diropargs3(xdr, args->fh, args->name, args->len);
1159 encode_mknoddata3(xdr, args);
1160}
1161
1162/*
1163 * 3.3.12 REMOVE3args
1164 *
1165 * struct REMOVE3args {
1166 * diropargs3 object;
1167 * };
1168 */
1169static void nfs3_xdr_enc_remove3args(struct rpc_rqst *req,
1170 struct xdr_stream *xdr,
1171 const struct nfs_removeargs *args)
1172{
1173 encode_diropargs3(xdr, args->fh, args->name.name, args->name.len);
1174}
1175
1176/*
1177 * 3.3.14 RENAME3args
1178 *
1179 * struct RENAME3args {
1180 * diropargs3 from;
1181 * diropargs3 to;
1182 * };
1183 */
1184static void nfs3_xdr_enc_rename3args(struct rpc_rqst *req,
1185 struct xdr_stream *xdr,
1186 const struct nfs_renameargs *args)
1187{
1188 const struct qstr *old = args->old_name;
1189 const struct qstr *new = args->new_name;
1190
1191 encode_diropargs3(xdr, args->old_dir, old->name, old->len);
1192 encode_diropargs3(xdr, args->new_dir, new->name, new->len);
1193}
1194
1195/*
1196 * 3.3.15 LINK3args
1197 *
1198 * struct LINK3args {
1199 * nfs_fh3 file;
1200 * diropargs3 link;
1201 * };
1202 */
1203static void nfs3_xdr_enc_link3args(struct rpc_rqst *req,
1204 struct xdr_stream *xdr,
1205 const struct nfs3_linkargs *args)
1206{
1207 encode_nfs_fh3(xdr, args->fromfh);
1208 encode_diropargs3(xdr, args->tofh, args->toname, args->tolen);
1209}
1210
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
1234static void nfs3_xdr_enc_readdir3args(struct rpc_rqst *req,
1235 struct xdr_stream *xdr,
1236 const struct nfs3_readdirargs *args)
1237{
1238 encode_readdir3args(xdr, args);
1239 prepare_reply_buffer(req, args->pages, 0,
1240 args->count, NFS3_readdirres_sz);
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
1274static void nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req,
1275 struct xdr_stream *xdr,
1276 const struct nfs3_readdirargs *args)
1277{
1278 encode_readdirplus3args(xdr, args);
1279 prepare_reply_buffer(req, args->pages, 0,
1280 args->count, NFS3_readdirres_sz);
1281}
1282
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,
1293 const struct nfs_commitargs *args)
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
1304static void nfs3_xdr_enc_commit3args(struct rpc_rqst *req,
1305 struct xdr_stream *xdr,
1306 const struct nfs_commitargs *args)
1307{
1308 encode_commit3args(xdr, args);
1309}
1310
1311#ifdef CONFIG_NFS_V3_ACL
1312
1313static void nfs3_xdr_enc_getacl3args(struct rpc_rqst *req,
1314 struct xdr_stream *xdr,
1315 const struct nfs3_getaclargs *args)
1316{
1317 encode_nfs_fh3(xdr, args->fh);
1318 encode_uint32(xdr, args->mask);
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);
1323}
1324
1325static void nfs3_xdr_enc_setacl3args(struct rpc_rqst *req,
1326 struct xdr_stream *xdr,
1327 const struct nfs3_setaclargs *args)
1328{
1329 unsigned int base;
1330 int error;
1331
1332 encode_nfs_fh3(xdr, NFS_FH(args->inode));
1333 encode_uint32(xdr, args->mask);
1334
1335 base = req->rq_slen;
1336 if (args->npages != 0)
1337 xdr_write_pages(xdr, args->pages, 0, args->len);
1338 else
1339 xdr_reserve_space(xdr, NFS_ACL_INLINE_BUFSIZE);
1340
1341 error = nfsacl_encode(xdr->buf, base, args->inode,
1342 (args->mask & NFS_ACL) ?
1343 args->acl_access : NULL, 1, 0);
1344 BUG_ON(error < 0);
1345 error = nfsacl_encode(xdr->buf, base + error, args->inode,
1346 (args->mask & NFS_DFACL) ?
1347 args->acl_default : NULL, 1,
1348 NFS_ACL_DEFAULT);
1349 BUG_ON(error < 0);
1350}
1351
1352#endif /* CONFIG_NFS_V3_ACL */
1353
1354/*
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".
1359 */
1360
1361/*
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 * };
1374 */
1375static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req,
1376 struct xdr_stream *xdr,
1377 struct nfs_fattr *result)
1378{
1379 enum nfs_stat status;
1380 int error;
1381
1382 error = decode_nfsstat3(xdr, &status);
1383 if (unlikely(error))
1384 goto out;
1385 if (status != NFS3_OK)
1386 goto out_default;
1387 error = decode_fattr3(xdr, result);
1388out:
1389 return error;
1390out_default:
1391 return nfs_stat_to_errno(status);
1392}
1393
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 */
1412static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req,
1413 struct xdr_stream *xdr,
1414 struct nfs_fattr *result)
1415{
1416 enum nfs_stat status;
1417 int error;
1418
1419 error = decode_nfsstat3(xdr, &status);
1420 if (unlikely(error))
1421 goto out;
1422 error = decode_wcc_data(xdr, result);
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
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 */
1453static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req,
1454 struct xdr_stream *xdr,
1455 struct nfs3_diropres *result)
1456{
1457 enum nfs_stat status;
1458 int error;
1459
1460 error = decode_nfsstat3(xdr, &status);
1461 if (unlikely(error))
1462 goto out;
1463 if (status != NFS3_OK)
1464 goto out_default;
1465 error = decode_nfs_fh3(xdr, result->fh);
1466 if (unlikely(error))
1467 goto out;
1468 error = decode_post_op_attr(xdr, result->fattr);
1469 if (unlikely(error))
1470 goto out;
1471 error = decode_post_op_attr(xdr, result->dir_attr);
1472out:
1473 return error;
1474out_default:
1475 error = decode_post_op_attr(xdr, result->dir_attr);
1476 if (unlikely(error))
1477 goto out;
1478 return nfs_stat_to_errno(status);
1479}
1480
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 */
1500static int nfs3_xdr_dec_access3res(struct rpc_rqst *req,
1501 struct xdr_stream *xdr,
1502 struct nfs3_accessres *result)
1503{
1504 enum nfs_stat status;
1505 int error;
1506
1507 error = decode_nfsstat3(xdr, &status);
1508 if (unlikely(error))
1509 goto out;
1510 error = decode_post_op_attr(xdr, result->fattr);
1511 if (unlikely(error))
1512 goto out;
1513 if (status != NFS3_OK)
1514 goto out_default;
1515 error = decode_uint32(xdr, &result->access);
1516out:
1517 return error;
1518out_default:
1519 return nfs_stat_to_errno(status);
1520}
1521
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 */
1541static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req,
1542 struct xdr_stream *xdr,
1543 struct nfs_fattr *result)
1544{
1545 enum nfs_stat status;
1546 int error;
1547
1548 error = decode_nfsstat3(xdr, &status);
1549 if (unlikely(error))
1550 goto out;
1551 error = decode_post_op_attr(xdr, result);
1552 if (unlikely(error))
1553 goto out;
1554 if (status != NFS3_OK)
1555 goto out_default;
1556 error = decode_nfspath3(xdr);
1557out:
1558 return error;
1559out_default:
1560 return nfs_stat_to_errno(status);
1561}
1562
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
1624static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1625 struct nfs_readres *result)
1626{
1627 enum nfs_stat status;
1628 int error;
1629
1630 error = decode_nfsstat3(xdr, &status);
1631 if (unlikely(error))
1632 goto out;
1633 error = decode_post_op_attr(xdr, result->fattr);
1634 if (unlikely(error))
1635 goto out;
1636 if (status != NFS3_OK)
1637 goto out_status;
1638 error = decode_read3resok(xdr, result);
1639out:
1640 return error;
1641out_status:
1642 return nfs_stat_to_errno(status);
1643}
1644
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
1694static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1695 struct nfs_writeres *result)
1696{
1697 enum nfs_stat status;
1698 int error;
1699
1700 error = decode_nfsstat3(xdr, &status);
1701 if (unlikely(error))
1702 goto out;
1703 error = decode_wcc_data(xdr, result->fattr);
1704 if (unlikely(error))
1705 goto out;
1706 if (status != NFS3_OK)
1707 goto out_status;
1708 error = decode_write3resok(xdr, result);
1709out:
1710 return error;
1711out_status:
1712 return nfs_stat_to_errno(status);
1713}
1714
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
1757static int nfs3_xdr_dec_create3res(struct rpc_rqst *req,
1758 struct xdr_stream *xdr,
1759 struct nfs3_diropres *result)
1760{
1761 enum nfs_stat status;
1762 int error;
1763
1764 error = decode_nfsstat3(xdr, &status);
1765 if (unlikely(error))
1766 goto out;
1767 if (status != NFS3_OK)
1768 goto out_default;
1769 error = decode_create3resok(xdr, result);
1770out:
1771 return error;
1772out_default:
1773 error = decode_wcc_data(xdr, result->dir_attr);
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 */
1797static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req,
1798 struct xdr_stream *xdr,
1799 struct nfs_removeres *result)
1800{
1801 enum nfs_stat status;
1802 int error;
1803
1804 error = decode_nfsstat3(xdr, &status);
1805 if (unlikely(error))
1806 goto out;
1807 error = decode_wcc_data(xdr, result->dir_attr);
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
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 */
1838static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req,
1839 struct xdr_stream *xdr,
1840 struct nfs_renameres *result)
1841{
1842 enum nfs_stat status;
1843 int error;
1844
1845 error = decode_nfsstat3(xdr, &status);
1846 if (unlikely(error))
1847 goto out;
1848 error = decode_wcc_data(xdr, result->old_fattr);
1849 if (unlikely(error))
1850 goto out;
1851 error = decode_wcc_data(xdr, result->new_fattr);
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
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 */
1882static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, struct xdr_stream *xdr,
1883 struct nfs3_linkres *result)
1884{
1885 enum nfs_stat status;
1886 int error;
1887
1888 error = decode_nfsstat3(xdr, &status);
1889 if (unlikely(error))
1890 goto out;
1891 error = decode_post_op_attr(xdr, result->fattr);
1892 if (unlikely(error))
1893 goto out;
1894 error = decode_wcc_data(xdr, result->dir_attr);
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
1910 * @plus: boolean indicating whether this should be a readdirplus entry
1911 *
1912 * Returns zero if successful, otherwise a negative errno value is
1913 * returned.
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 */
1940int nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1941 int plus)
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)
1955 return -EAGAIN;
1956 entry->eof = 1;
1957 return -EBADCOOKIE;
1958 }
1959
1960 error = decode_fileid3(xdr, &entry->ino);
1961 if (unlikely(error))
1962 return error;
1963
1964 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
1965 if (unlikely(error))
1966 return error;
1967
1968 entry->prev_cookie = entry->cookie;
1969 error = decode_cookie3(xdr, &entry->cookie);
1970 if (unlikely(error))
1971 return error;
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))
1979 return error;
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;
1992 return error;
1993 }
1994 } else
1995 zero_nfs_fh3(entry->fh);
1996 }
1997
1998 return 0;
1999
2000out_overflow:
2001 print_overflow_msg(__func__, xdr);
2002 return -EAGAIN;
2003out_truncated:
2004 dprintk("NFS: directory entry contains invalid file handle\n");
2005 *entry = old;
2006 return -EAGAIN;
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
2075static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req,
2076 struct xdr_stream *xdr,
2077 struct nfs3_readdirres *result)
2078{
2079 enum nfs_stat status;
2080 int error;
2081
2082 error = decode_nfsstat3(xdr, &status);
2083 if (unlikely(error))
2084 goto out;
2085 if (status != NFS3_OK)
2086 goto out_default;
2087 error = decode_readdir3resok(xdr, result);
2088out:
2089 return error;
2090out_default:
2091 error = decode_post_op_attr(xdr, result->dir_attr);
2092 if (unlikely(error))
2093 goto out;
2094 return nfs_stat_to_errno(status);
2095}
2096
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
2143static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req,
2144 struct xdr_stream *xdr,
2145 struct nfs_fsstat *result)
2146{
2147 enum nfs_stat status;
2148 int error;
2149
2150 error = decode_nfsstat3(xdr, &status);
2151 if (unlikely(error))
2152 goto out;
2153 error = decode_post_op_attr(xdr, result->fattr);
2154 if (unlikely(error))
2155 goto out;
2156 if (status != NFS3_OK)
2157 goto out_status;
2158 error = decode_fsstat3resok(xdr, result);
2159out:
2160 return error;
2161out_status:
2162 return nfs_stat_to_errno(status);
2163}
2164
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);
2209 xdr_decode_nfstime3(p, &result->time_delta);
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
2219static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req,
2220 struct xdr_stream *xdr,
2221 struct nfs_fsinfo *result)
2222{
2223 enum nfs_stat status;
2224 int error;
2225
2226 error = decode_nfsstat3(xdr, &status);
2227 if (unlikely(error))
2228 goto out;
2229 error = decode_post_op_attr(xdr, result->fattr);
2230 if (unlikely(error))
2231 goto out;
2232 if (status != NFS3_OK)
2233 goto out_status;
2234 error = decode_fsinfo3resok(xdr, result);
2235out:
2236 return error;
2237out_status:
2238 return nfs_stat_to_errno(status);
2239}
2240
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
2282static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req,
2283 struct xdr_stream *xdr,
2284 struct nfs_pathconf *result)
2285{
2286 enum nfs_stat status;
2287 int error;
2288
2289 error = decode_nfsstat3(xdr, &status);
2290 if (unlikely(error))
2291 goto out;
2292 error = decode_post_op_attr(xdr, result->fattr);
2293 if (unlikely(error))
2294 goto out;
2295 if (status != NFS3_OK)
2296 goto out_status;
2297 error = decode_pathconf3resok(xdr, result);
2298out:
2299 return error;
2300out_status:
2301 return nfs_stat_to_errno(status);
2302}
2303
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 */
2323static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req,
2324 struct xdr_stream *xdr,
2325 struct nfs_commitres *result)
2326{
2327 enum nfs_stat status;
2328 int error;
2329
2330 error = decode_nfsstat3(xdr, &status);
2331 if (unlikely(error))
2332 goto out;
2333 error = decode_wcc_data(xdr, result->fattr);
2334 if (unlikely(error))
2335 goto out;
2336 if (status != NFS3_OK)
2337 goto out_status;
2338 error = decode_writeverf3(xdr, result->verf->verifier);
2339out:
2340 return error;
2341out_status:
2342 return nfs_stat_to_errno(status);
2343}
2344
2345#ifdef CONFIG_NFS_V3_ACL
2346
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
2391static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req,
2392 struct xdr_stream *xdr,
2393 struct nfs3_getaclres *result)
2394{
2395 enum nfs_stat status;
2396 int error;
2397
2398 error = decode_nfsstat3(xdr, &status);
2399 if (unlikely(error))
2400 goto out;
2401 if (status != NFS3_OK)
2402 goto out_default;
2403 error = decode_getacl3resok(xdr, result);
2404out:
2405 return error;
2406out_default:
2407 return nfs_stat_to_errno(status);
2408}
2409
2410static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req,
2411 struct xdr_stream *xdr,
2412 struct nfs_fattr *result)
2413{
2414 enum nfs_stat status;
2415 int error;
2416
2417 error = decode_nfsstat3(xdr, &status);
2418 if (unlikely(error))
2419 goto out;
2420 if (status != NFS3_OK)
2421 goto out_default;
2422 error = decode_post_op_attr(xdr, result);
2423out:
2424 return error;
2425out_default:
2426 return nfs_stat_to_errno(status);
2427}
2428
2429#endif /* CONFIG_NFS_V3_ACL */
2430
2431#define PROC(proc, argtype, restype, timer) \
2432[NFS3PROC_##proc] = { \
2433 .p_proc = NFS3PROC_##proc, \
2434 .p_encode = (kxdreproc_t)nfs3_xdr_enc_##argtype##3args, \
2435 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_##restype##3res, \
2436 .p_arglen = NFS3_##argtype##args_sz, \
2437 .p_replen = NFS3_##restype##res_sz, \
2438 .p_timer = timer, \
2439 .p_statidx = NFS3PROC_##proc, \
2440 .p_name = #proc, \
2441 }
2442
2443struct rpc_procinfo nfs3_procedures[] = {
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),
2465};
2466
2467const struct rpc_version nfs_version3 = {
2468 .number = 3,
2469 .nrprocs = ARRAY_SIZE(nfs3_procedures),
2470 .procs = nfs3_procedures
2471};
2472
2473#ifdef CONFIG_NFS_V3_ACL
2474static struct rpc_procinfo nfs3_acl_procedures[] = {
2475 [ACLPROC3_GETACL] = {
2476 .p_proc = ACLPROC3_GETACL,
2477 .p_encode = (kxdreproc_t)nfs3_xdr_enc_getacl3args,
2478 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_getacl3res,
2479 .p_arglen = ACL3_getaclargs_sz,
2480 .p_replen = ACL3_getaclres_sz,
2481 .p_timer = 1,
2482 .p_name = "GETACL",
2483 },
2484 [ACLPROC3_SETACL] = {
2485 .p_proc = ACLPROC3_SETACL,
2486 .p_encode = (kxdreproc_t)nfs3_xdr_enc_setacl3args,
2487 .p_decode = (kxdrdproc_t)nfs3_xdr_dec_setacl3res,
2488 .p_arglen = ACL3_setaclargs_sz,
2489 .p_replen = ACL3_setaclres_sz,
2490 .p_timer = 0,
2491 .p_name = "SETACL",
2492 },
2493};
2494
2495const struct rpc_version nfsacl_version3 = {
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 */
This page took 0.055165 seconds and 5 git commands to generate.