NFS: Introduce new-style XDR decoding functions for NFSv2
[linux-2.6/linux-acpi-2.6/ibm-acpi-2.6.git] / fs / nfs / nfs3xdr.c
blob0f07c6d55131223e2fa7aa615013dc1256c2dfae
1 /*
2 * linux/fs/nfs/nfs3xdr.c
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
6 * Copyright (C) 1996, 1997 Olaf Kirch
7 */
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"
25 #define NFSDBG_FACILITY NFSDBG_XDR
27 /* Mapping from NFS error code to "errno" error code. */
28 #define errno_NFSERR_IO EIO
31 * Declare the space requirements for NFS arguments and replies as
32 * number of 32bit-words
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_fsstat_sz
46 #define NFS3_fsinfo_sz
47 #define NFS3_pathconf_sz
48 #define NFS3_entry_sz (NFS3_filename_sz+3)
49 #define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
51 #define NFS3_getattrargs_sz (NFS3_fh_sz)
52 #define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
53 #define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz)
54 #define NFS3_accessargs_sz (NFS3_fh_sz+1)
55 #define NFS3_readlinkargs_sz (NFS3_fh_sz)
56 #define NFS3_readargs_sz (NFS3_fh_sz+3)
57 #define NFS3_writeargs_sz (NFS3_fh_sz+5)
58 #define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
60 #define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
61 #define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
62 #define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
63 #define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
64 #define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
65 #define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
66 #define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
67 #define NFS3_commitargs_sz (NFS3_fh_sz+3)
69 #define NFS3_attrstat_sz (1+NFS3_fattr_sz)
70 #define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
71 #define NFS3_removeres_sz (NFS3_wccstat_sz)
72 #define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
73 #define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
74 #define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
75 #define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
76 #define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
77 #define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78 #define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
79 #define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
80 #define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
81 #define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
82 #define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
83 #define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
84 #define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
86 #define ACL3_getaclargs_sz (NFS3_fh_sz+1)
87 #define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
88 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
89 #define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
90 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
91 #define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
94 * Map file type to S_IFMT bits
96 static const umode_t nfs_type2fmt[] = {
97 [NF3BAD] = 0,
98 [NF3REG] = S_IFREG,
99 [NF3DIR] = S_IFDIR,
100 [NF3BLK] = S_IFBLK,
101 [NF3CHR] = S_IFCHR,
102 [NF3LNK] = S_IFLNK,
103 [NF3SOCK] = S_IFSOCK,
104 [NF3FIFO] = S_IFIFO,
108 * While encoding arguments, set up the reply buffer in advance to
109 * receive reply data directly into the page cache.
111 static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
112 unsigned int base, unsigned int len,
113 unsigned int bufsize)
115 struct rpc_auth *auth = req->rq_cred->cr_auth;
116 unsigned int replen;
118 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
119 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
123 * Handle decode buffer overflows out-of-line.
125 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
127 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
128 "Remaining buffer length is %tu words.\n",
129 func, xdr->end - xdr->p);
134 * Common NFS XDR functions as inlines
136 static inline __be32 *
137 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
139 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
140 memcpy(fh->data, p, fh->size);
141 return p + XDR_QUADLEN(fh->size);
143 return NULL;
146 static inline __be32 *
147 xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
149 __be32 *p;
150 p = xdr_inline_decode(xdr, 4);
151 if (unlikely(!p))
152 goto out_overflow;
153 fh->size = ntohl(*p++);
155 if (fh->size <= NFS3_FHSIZE) {
156 p = xdr_inline_decode(xdr, fh->size);
157 if (unlikely(!p))
158 goto out_overflow;
159 memcpy(fh->data, p, fh->size);
160 return p + XDR_QUADLEN(fh->size);
162 return NULL;
164 out_overflow:
165 print_overflow_msg(__func__, xdr);
166 return ERR_PTR(-EIO);
170 * Encode/decode time.
172 static inline __be32 *
173 xdr_decode_time3(__be32 *p, struct timespec *timep)
175 timep->tv_sec = ntohl(*p++);
176 timep->tv_nsec = ntohl(*p++);
177 return p;
180 static __be32 *
181 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
183 unsigned int type, major, minor;
184 umode_t fmode;
186 type = ntohl(*p++);
187 if (type > NF3FIFO)
188 type = NF3NON;
189 fmode = nfs_type2fmt[type];
190 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
191 fattr->nlink = ntohl(*p++);
192 fattr->uid = ntohl(*p++);
193 fattr->gid = ntohl(*p++);
194 p = xdr_decode_hyper(p, &fattr->size);
195 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
197 /* Turn remote device info into Linux-specific dev_t */
198 major = ntohl(*p++);
199 minor = ntohl(*p++);
200 fattr->rdev = MKDEV(major, minor);
201 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
202 fattr->rdev = 0;
204 p = xdr_decode_hyper(p, &fattr->fsid.major);
205 fattr->fsid.minor = 0;
206 p = xdr_decode_hyper(p, &fattr->fileid);
207 p = xdr_decode_time3(p, &fattr->atime);
208 p = xdr_decode_time3(p, &fattr->mtime);
209 p = xdr_decode_time3(p, &fattr->ctime);
211 /* Update the mode bits */
212 fattr->valid |= NFS_ATTR_FATTR_V3;
213 return p;
216 static inline __be32 *
217 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
219 p = xdr_decode_hyper(p, &fattr->pre_size);
220 p = xdr_decode_time3(p, &fattr->pre_mtime);
221 p = xdr_decode_time3(p, &fattr->pre_ctime);
222 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
223 | NFS_ATTR_FATTR_PREMTIME
224 | NFS_ATTR_FATTR_PRECTIME;
225 return p;
228 static inline __be32 *
229 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
231 if (*p++)
232 p = xdr_decode_fattr(p, fattr);
233 return p;
236 static inline __be32 *
237 xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
239 __be32 *p;
241 p = xdr_inline_decode(xdr, 4);
242 if (unlikely(!p))
243 goto out_overflow;
244 if (ntohl(*p++)) {
245 p = xdr_inline_decode(xdr, 84);
246 if (unlikely(!p))
247 goto out_overflow;
248 p = xdr_decode_fattr(p, fattr);
250 return p;
251 out_overflow:
252 print_overflow_msg(__func__, xdr);
253 return ERR_PTR(-EIO);
256 static inline __be32 *
257 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
259 if (*p++)
260 return xdr_decode_wcc_attr(p, fattr);
261 return p;
265 static inline __be32 *
266 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
268 p = xdr_decode_pre_op_attr(p, fattr);
269 return xdr_decode_post_op_attr(p, fattr);
274 * Encode/decode NFSv3 basic data types
276 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
277 * "NFS Version 3 Protocol Specification".
279 * Not all basic data types have their own encoding and decoding
280 * functions. For run-time efficiency, some data types are encoded
281 * or decoded inline.
284 static void encode_uint32(struct xdr_stream *xdr, u32 value)
286 __be32 *p = xdr_reserve_space(xdr, 4);
287 *p = cpu_to_be32(value);
290 static int decode_uint32(struct xdr_stream *xdr, u32 *value)
292 __be32 *p;
294 p = xdr_inline_decode(xdr, 4);
295 if (unlikely(p == NULL))
296 goto out_overflow;
297 *value = be32_to_cpup(p);
298 return 0;
299 out_overflow:
300 print_overflow_msg(__func__, xdr);
301 return -EIO;
304 static int decode_uint64(struct xdr_stream *xdr, u64 *value)
306 __be32 *p;
308 p = xdr_inline_decode(xdr, 8);
309 if (unlikely(p == NULL))
310 goto out_overflow;
311 xdr_decode_hyper(p, value);
312 return 0;
313 out_overflow:
314 print_overflow_msg(__func__, xdr);
315 return -EIO;
319 * fileid3
321 * typedef uint64 fileid3;
323 static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
325 return decode_uint64(xdr, fileid);
329 * filename3
331 * typedef string filename3<>;
333 static void encode_filename3(struct xdr_stream *xdr,
334 const char *name, u32 length)
336 __be32 *p;
338 BUG_ON(length > NFS3_MAXNAMLEN);
339 p = xdr_reserve_space(xdr, 4 + length);
340 xdr_encode_opaque(p, name, length);
343 static int decode_inline_filename3(struct xdr_stream *xdr,
344 const char **name, u32 *length)
346 __be32 *p;
347 u32 count;
349 p = xdr_inline_decode(xdr, 4);
350 if (unlikely(p == NULL))
351 goto out_overflow;
352 count = be32_to_cpup(p);
353 if (count > NFS3_MAXNAMLEN)
354 goto out_nametoolong;
355 p = xdr_inline_decode(xdr, count);
356 if (unlikely(p == NULL))
357 goto out_overflow;
358 *name = (const char *)p;
359 *length = count;
360 return 0;
362 out_nametoolong:
363 dprintk("NFS: returned filename too long: %u\n", count);
364 return -ENAMETOOLONG;
365 out_overflow:
366 print_overflow_msg(__func__, xdr);
367 return -EIO;
371 * nfspath3
373 * typedef string nfspath3<>;
375 static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
376 const u32 length)
378 BUG_ON(length > NFS3_MAXPATHLEN);
379 encode_uint32(xdr, length);
380 xdr_write_pages(xdr, pages, 0, length);
383 static int decode_nfspath3(struct xdr_stream *xdr)
385 u32 recvd, count;
386 size_t hdrlen;
387 __be32 *p;
389 p = xdr_inline_decode(xdr, 4);
390 if (unlikely(p == NULL))
391 goto out_overflow;
392 count = be32_to_cpup(p);
393 if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
394 goto out_nametoolong;
395 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
396 recvd = xdr->buf->len - hdrlen;
397 if (unlikely(count > recvd))
398 goto out_cheating;
400 xdr_read_pages(xdr, count);
401 xdr_terminate_string(xdr->buf, count);
402 return 0;
404 out_nametoolong:
405 dprintk("NFS: returned pathname too long: %u\n", count);
406 return -ENAMETOOLONG;
407 out_cheating:
408 dprintk("NFS: server cheating in pathname result: "
409 "count %u > recvd %u\n", count, recvd);
410 return -EIO;
411 out_overflow:
412 print_overflow_msg(__func__, xdr);
413 return -EIO;
417 * cookie3
419 * typedef uint64 cookie3
421 static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
423 return xdr_encode_hyper(p, cookie);
426 static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
428 return decode_uint64(xdr, cookie);
432 * cookieverf3
434 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
436 static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
438 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
439 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
442 static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
444 __be32 *p;
446 p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
447 if (unlikely(p == NULL))
448 goto out_overflow;
449 memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
450 return 0;
451 out_overflow:
452 print_overflow_msg(__func__, xdr);
453 return -EIO;
457 * createverf3
459 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
461 static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
463 __be32 *p;
465 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
466 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
469 static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
471 __be32 *p;
473 p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
474 if (unlikely(p == NULL))
475 goto out_overflow;
476 memcpy(verifier, p, NFS3_WRITEVERFSIZE);
477 return 0;
478 out_overflow:
479 print_overflow_msg(__func__, xdr);
480 return -EIO;
484 * size3
486 * typedef uint64 size3;
488 static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
490 return xdr_decode_hyper(p, size);
494 * nfsstat3
496 * enum nfsstat3 {
497 * NFS3_OK = 0,
498 * ...
501 #define NFS3_OK NFS_OK
503 static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
505 __be32 *p;
507 p = xdr_inline_decode(xdr, 4);
508 if (unlikely(p == NULL))
509 goto out_overflow;
510 *status = be32_to_cpup(p);
511 return 0;
512 out_overflow:
513 print_overflow_msg(__func__, xdr);
514 return -EIO;
518 * ftype3
520 * enum ftype3 {
521 * NF3REG = 1,
522 * NF3DIR = 2,
523 * NF3BLK = 3,
524 * NF3CHR = 4,
525 * NF3LNK = 5,
526 * NF3SOCK = 6,
527 * NF3FIFO = 7
528 * };
530 static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
532 BUG_ON(type > NF3FIFO);
533 encode_uint32(xdr, type);
537 * specdata3
539 * struct specdata3 {
540 * uint32 specdata1;
541 * uint32 specdata2;
542 * };
544 static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
546 __be32 *p;
548 p = xdr_reserve_space(xdr, 8);
549 *p++ = cpu_to_be32(MAJOR(rdev));
550 *p = cpu_to_be32(MINOR(rdev));
554 * nfs_fh3
556 * struct nfs_fh3 {
557 * opaque data<NFS3_FHSIZE>;
558 * };
560 static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
562 __be32 *p;
564 BUG_ON(fh->size > NFS3_FHSIZE);
565 p = xdr_reserve_space(xdr, 4 + fh->size);
566 xdr_encode_opaque(p, fh->data, fh->size);
569 static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
571 u32 length;
572 __be32 *p;
574 p = xdr_inline_decode(xdr, 4);
575 if (unlikely(p == NULL))
576 goto out_overflow;
577 length = be32_to_cpup(p++);
578 if (unlikely(length > NFS3_FHSIZE))
579 goto out_toobig;
580 p = xdr_inline_decode(xdr, length);
581 if (unlikely(p == NULL))
582 goto out_overflow;
583 fh->size = length;
584 memcpy(fh->data, p, length);
585 return 0;
586 out_toobig:
587 dprintk("NFS: file handle size (%u) too big\n", length);
588 return -E2BIG;
589 out_overflow:
590 print_overflow_msg(__func__, xdr);
591 return -EIO;
594 static void zero_nfs_fh3(struct nfs_fh *fh)
596 memset(fh, 0, sizeof(*fh));
600 * nfstime3
602 * struct nfstime3 {
603 * uint32 seconds;
604 * uint32 nseconds;
605 * };
607 static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
609 *p++ = cpu_to_be32(timep->tv_sec);
610 *p++ = cpu_to_be32(timep->tv_nsec);
611 return p;
615 * sattr3
617 * enum time_how {
618 * DONT_CHANGE = 0,
619 * SET_TO_SERVER_TIME = 1,
620 * SET_TO_CLIENT_TIME = 2
621 * };
623 * union set_mode3 switch (bool set_it) {
624 * case TRUE:
625 * mode3 mode;
626 * default:
627 * void;
628 * };
630 * union set_uid3 switch (bool set_it) {
631 * case TRUE:
632 * uid3 uid;
633 * default:
634 * void;
635 * };
637 * union set_gid3 switch (bool set_it) {
638 * case TRUE:
639 * gid3 gid;
640 * default:
641 * void;
642 * };
644 * union set_size3 switch (bool set_it) {
645 * case TRUE:
646 * size3 size;
647 * default:
648 * void;
649 * };
651 * union set_atime switch (time_how set_it) {
652 * case SET_TO_CLIENT_TIME:
653 * nfstime3 atime;
654 * default:
655 * void;
656 * };
658 * union set_mtime switch (time_how set_it) {
659 * case SET_TO_CLIENT_TIME:
660 * nfstime3 mtime;
661 * default:
662 * void;
663 * };
665 * struct sattr3 {
666 * set_mode3 mode;
667 * set_uid3 uid;
668 * set_gid3 gid;
669 * set_size3 size;
670 * set_atime atime;
671 * set_mtime mtime;
672 * };
674 static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
676 u32 nbytes;
677 __be32 *p;
680 * In order to make only a single xdr_reserve_space() call,
681 * pre-compute the total number of bytes to be reserved.
682 * Six boolean values, one for each set_foo field, are always
683 * present in the encoded result, so start there.
685 nbytes = 6 * 4;
686 if (attr->ia_valid & ATTR_MODE)
687 nbytes += 4;
688 if (attr->ia_valid & ATTR_UID)
689 nbytes += 4;
690 if (attr->ia_valid & ATTR_GID)
691 nbytes += 4;
692 if (attr->ia_valid & ATTR_SIZE)
693 nbytes += 8;
694 if (attr->ia_valid & ATTR_ATIME_SET)
695 nbytes += 8;
696 if (attr->ia_valid & ATTR_MTIME_SET)
697 nbytes += 8;
698 p = xdr_reserve_space(xdr, nbytes);
700 if (attr->ia_valid & ATTR_MODE) {
701 *p++ = xdr_one;
702 *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
703 } else
704 *p++ = xdr_zero;
706 if (attr->ia_valid & ATTR_UID) {
707 *p++ = xdr_one;
708 *p++ = cpu_to_be32(attr->ia_uid);
709 } else
710 *p++ = xdr_zero;
712 if (attr->ia_valid & ATTR_GID) {
713 *p++ = xdr_one;
714 *p++ = cpu_to_be32(attr->ia_gid);
715 } else
716 *p++ = xdr_zero;
718 if (attr->ia_valid & ATTR_SIZE) {
719 *p++ = xdr_one;
720 p = xdr_encode_hyper(p, (u64)attr->ia_size);
721 } else
722 *p++ = xdr_zero;
724 if (attr->ia_valid & ATTR_ATIME_SET) {
725 *p++ = xdr_two;
726 p = xdr_encode_nfstime3(p, &attr->ia_atime);
727 } else if (attr->ia_valid & ATTR_ATIME) {
728 *p++ = xdr_one;
729 } else
730 *p++ = xdr_zero;
732 if (attr->ia_valid & ATTR_MTIME_SET) {
733 *p++ = xdr_two;
734 xdr_encode_nfstime3(p, &attr->ia_mtime);
735 } else if (attr->ia_valid & ATTR_MTIME) {
736 *p = xdr_one;
737 } else
738 *p = xdr_zero;
742 * fattr3
744 * struct fattr3 {
745 * ftype3 type;
746 * mode3 mode;
747 * uint32 nlink;
748 * uid3 uid;
749 * gid3 gid;
750 * size3 size;
751 * size3 used;
752 * specdata3 rdev;
753 * uint64 fsid;
754 * fileid3 fileid;
755 * nfstime3 atime;
756 * nfstime3 mtime;
757 * nfstime3 ctime;
758 * };
760 static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
762 __be32 *p;
764 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
765 if (unlikely(p == NULL))
766 goto out_overflow;
767 xdr_decode_fattr(p, fattr);
768 return 0;
769 out_overflow:
770 print_overflow_msg(__func__, xdr);
771 return -EIO;
775 * post_op_attr
777 * union post_op_attr switch (bool attributes_follow) {
778 * case TRUE:
779 * fattr3 attributes;
780 * case FALSE:
781 * void;
782 * };
784 static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
786 __be32 *p;
788 p = xdr_inline_decode(xdr, 4);
789 if (unlikely(p == NULL))
790 goto out_overflow;
791 if (*p != xdr_zero)
792 return decode_fattr3(xdr, fattr);
793 return 0;
794 out_overflow:
795 print_overflow_msg(__func__, xdr);
796 return -EIO;
800 * wcc_attr
801 * struct wcc_attr {
802 * size3 size;
803 * nfstime3 mtime;
804 * nfstime3 ctime;
805 * };
807 static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
809 __be32 *p;
811 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
812 if (unlikely(p == NULL))
813 goto out_overflow;
814 xdr_decode_wcc_attr(p, fattr);
815 return 0;
816 out_overflow:
817 print_overflow_msg(__func__, xdr);
818 return -EIO;
822 * pre_op_attr
823 * union pre_op_attr switch (bool attributes_follow) {
824 * case TRUE:
825 * wcc_attr attributes;
826 * case FALSE:
827 * void;
828 * };
830 * wcc_data
832 * struct wcc_data {
833 * pre_op_attr before;
834 * post_op_attr after;
835 * };
837 static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
839 __be32 *p;
841 p = xdr_inline_decode(xdr, 4);
842 if (unlikely(p == NULL))
843 goto out_overflow;
844 if (*p != xdr_zero)
845 return decode_wcc_attr(xdr, fattr);
846 return 0;
847 out_overflow:
848 print_overflow_msg(__func__, xdr);
849 return -EIO;
852 static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
854 int error;
856 error = decode_pre_op_attr(xdr, fattr);
857 if (unlikely(error))
858 goto out;
859 error = decode_post_op_attr(xdr, fattr);
860 out:
861 return error;
865 * post_op_fh3
867 * union post_op_fh3 switch (bool handle_follows) {
868 * case TRUE:
869 * nfs_fh3 handle;
870 * case FALSE:
871 * void;
872 * };
874 static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
876 __be32 *p = xdr_inline_decode(xdr, 4);
877 if (unlikely(p == NULL))
878 goto out_overflow;
879 if (*p != xdr_zero)
880 return decode_nfs_fh3(xdr, fh);
881 zero_nfs_fh3(fh);
882 return 0;
883 out_overflow:
884 print_overflow_msg(__func__, xdr);
885 return -EIO;
889 * diropargs3
891 * struct diropargs3 {
892 * nfs_fh3 dir;
893 * filename3 name;
894 * };
896 static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
897 const char *name, u32 length)
899 encode_nfs_fh3(xdr, fh);
900 encode_filename3(xdr, name, length);
905 * NFSv3 XDR encode functions
907 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
908 * "NFS Version 3 Protocol Specification".
912 * 3.3.1 GETATTR3args
914 * struct GETATTR3args {
915 * nfs_fh3 object;
916 * };
918 static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
919 const struct nfs_fh *fh)
921 struct xdr_stream xdr;
923 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
924 encode_nfs_fh3(&xdr, fh);
925 return 0;
929 * 3.3.2 SETATTR3args
931 * union sattrguard3 switch (bool check) {
932 * case TRUE:
933 * nfstime3 obj_ctime;
934 * case FALSE:
935 * void;
936 * };
938 * struct SETATTR3args {
939 * nfs_fh3 object;
940 * sattr3 new_attributes;
941 * sattrguard3 guard;
942 * };
944 static void encode_sattrguard3(struct xdr_stream *xdr,
945 const struct nfs3_sattrargs *args)
947 __be32 *p;
949 if (args->guard) {
950 p = xdr_reserve_space(xdr, 4 + 8);
951 *p++ = xdr_one;
952 xdr_encode_nfstime3(p, &args->guardtime);
953 } else {
954 p = xdr_reserve_space(xdr, 4);
955 *p = xdr_zero;
959 static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
960 const struct nfs3_sattrargs *args)
962 struct xdr_stream xdr;
964 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
965 encode_nfs_fh3(&xdr, args->fh);
966 encode_sattr3(&xdr, args->sattr);
967 encode_sattrguard3(&xdr, args);
968 return 0;
972 * 3.3.3 LOOKUP3args
974 * struct LOOKUP3args {
975 * diropargs3 what;
976 * };
978 static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
979 const struct nfs3_diropargs *args)
981 struct xdr_stream xdr;
983 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
984 encode_diropargs3(&xdr, args->fh, args->name, args->len);
985 return 0;
989 * 3.3.4 ACCESS3args
991 * struct ACCESS3args {
992 * nfs_fh3 object;
993 * uint32 access;
994 * };
996 static void encode_access3args(struct xdr_stream *xdr,
997 const struct nfs3_accessargs *args)
999 encode_nfs_fh3(xdr, args->fh);
1000 encode_uint32(xdr, args->access);
1003 static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
1004 const struct nfs3_accessargs *args)
1006 struct xdr_stream xdr;
1008 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1009 encode_access3args(&xdr, args);
1010 return 0;
1014 * 3.3.5 READLINK3args
1016 * struct READLINK3args {
1017 * nfs_fh3 symlink;
1018 * };
1020 static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
1021 const struct nfs3_readlinkargs *args)
1023 struct xdr_stream xdr;
1025 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1026 encode_nfs_fh3(&xdr, args->fh);
1027 prepare_reply_buffer(req, args->pages, args->pgbase,
1028 args->pglen, NFS3_readlinkres_sz);
1029 return 0;
1033 * 3.3.6 READ3args
1035 * struct READ3args {
1036 * nfs_fh3 file;
1037 * offset3 offset;
1038 * count3 count;
1039 * };
1041 static void encode_read3args(struct xdr_stream *xdr,
1042 const struct nfs_readargs *args)
1044 __be32 *p;
1046 encode_nfs_fh3(xdr, args->fh);
1048 p = xdr_reserve_space(xdr, 8 + 4);
1049 p = xdr_encode_hyper(p, args->offset);
1050 *p = cpu_to_be32(args->count);
1053 static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
1054 const struct nfs_readargs *args)
1056 struct xdr_stream xdr;
1058 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1059 encode_read3args(&xdr, args);
1060 prepare_reply_buffer(req, args->pages, args->pgbase,
1061 args->count, NFS3_readres_sz);
1062 req->rq_rcv_buf.flags |= XDRBUF_READ;
1063 return 0;
1067 * 3.3.7 WRITE3args
1069 * enum stable_how {
1070 * UNSTABLE = 0,
1071 * DATA_SYNC = 1,
1072 * FILE_SYNC = 2
1073 * };
1075 * struct WRITE3args {
1076 * nfs_fh3 file;
1077 * offset3 offset;
1078 * count3 count;
1079 * stable_how stable;
1080 * opaque data<>;
1081 * };
1083 static void encode_write3args(struct xdr_stream *xdr,
1084 const struct nfs_writeargs *args)
1086 __be32 *p;
1088 encode_nfs_fh3(xdr, args->fh);
1090 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
1091 p = xdr_encode_hyper(p, args->offset);
1092 *p++ = cpu_to_be32(args->count);
1094 BUG_ON(args->stable > NFS_FILE_SYNC);
1095 *p++ = cpu_to_be32(args->stable);
1097 *p = cpu_to_be32(args->count);
1098 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1101 static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
1102 const struct nfs_writeargs *args)
1104 struct xdr_stream xdr;
1106 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1107 encode_write3args(&xdr, args);
1108 xdr.buf->flags |= XDRBUF_WRITE;
1109 return 0;
1113 * 3.3.8 CREATE3args
1115 * enum createmode3 {
1116 * UNCHECKED = 0,
1117 * GUARDED = 1,
1118 * EXCLUSIVE = 2
1119 * };
1121 * union createhow3 switch (createmode3 mode) {
1122 * case UNCHECKED:
1123 * case GUARDED:
1124 * sattr3 obj_attributes;
1125 * case EXCLUSIVE:
1126 * createverf3 verf;
1127 * };
1129 * struct CREATE3args {
1130 * diropargs3 where;
1131 * createhow3 how;
1132 * };
1134 static void encode_createhow3(struct xdr_stream *xdr,
1135 const struct nfs3_createargs *args)
1137 encode_uint32(xdr, args->createmode);
1138 switch (args->createmode) {
1139 case NFS3_CREATE_UNCHECKED:
1140 case NFS3_CREATE_GUARDED:
1141 encode_sattr3(xdr, args->sattr);
1142 break;
1143 case NFS3_CREATE_EXCLUSIVE:
1144 encode_createverf3(xdr, args->verifier);
1145 break;
1146 default:
1147 BUG();
1151 static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
1152 const struct nfs3_createargs *args)
1154 struct xdr_stream xdr;
1156 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1157 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1158 encode_createhow3(&xdr, args);
1159 return 0;
1163 * 3.3.9 MKDIR3args
1165 * struct MKDIR3args {
1166 * diropargs3 where;
1167 * sattr3 attributes;
1168 * };
1170 static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
1171 const struct nfs3_mkdirargs *args)
1173 struct xdr_stream xdr;
1175 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1176 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1177 encode_sattr3(&xdr, args->sattr);
1178 return 0;
1182 * 3.3.10 SYMLINK3args
1184 * struct symlinkdata3 {
1185 * sattr3 symlink_attributes;
1186 * nfspath3 symlink_data;
1187 * };
1189 * struct SYMLINK3args {
1190 * diropargs3 where;
1191 * symlinkdata3 symlink;
1192 * };
1194 static void encode_symlinkdata3(struct xdr_stream *xdr,
1195 const struct nfs3_symlinkargs *args)
1197 encode_sattr3(xdr, args->sattr);
1198 encode_nfspath3(xdr, args->pages, args->pathlen);
1201 static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
1202 const struct nfs3_symlinkargs *args)
1204 struct xdr_stream xdr;
1206 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1207 encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
1208 encode_symlinkdata3(&xdr, args);
1209 return 0;
1213 * 3.3.11 MKNOD3args
1215 * struct devicedata3 {
1216 * sattr3 dev_attributes;
1217 * specdata3 spec;
1218 * };
1220 * union mknoddata3 switch (ftype3 type) {
1221 * case NF3CHR:
1222 * case NF3BLK:
1223 * devicedata3 device;
1224 * case NF3SOCK:
1225 * case NF3FIFO:
1226 * sattr3 pipe_attributes;
1227 * default:
1228 * void;
1229 * };
1231 * struct MKNOD3args {
1232 * diropargs3 where;
1233 * mknoddata3 what;
1234 * };
1236 static void encode_devicedata3(struct xdr_stream *xdr,
1237 const struct nfs3_mknodargs *args)
1239 encode_sattr3(xdr, args->sattr);
1240 encode_specdata3(xdr, args->rdev);
1243 static void encode_mknoddata3(struct xdr_stream *xdr,
1244 const struct nfs3_mknodargs *args)
1246 encode_ftype3(xdr, args->type);
1247 switch (args->type) {
1248 case NF3CHR:
1249 case NF3BLK:
1250 encode_devicedata3(xdr, args);
1251 break;
1252 case NF3SOCK:
1253 case NF3FIFO:
1254 encode_sattr3(xdr, args->sattr);
1255 break;
1256 case NF3REG:
1257 case NF3DIR:
1258 break;
1259 default:
1260 BUG();
1264 static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
1265 const struct nfs3_mknodargs *args)
1267 struct xdr_stream xdr;
1269 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1270 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1271 encode_mknoddata3(&xdr, args);
1272 return 0;
1276 * 3.3.12 REMOVE3args
1278 * struct REMOVE3args {
1279 * diropargs3 object;
1280 * };
1282 static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
1283 const struct nfs_removeargs *args)
1285 struct xdr_stream xdr;
1287 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1288 encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
1289 return 0;
1293 * 3.3.14 RENAME3args
1295 * struct RENAME3args {
1296 * diropargs3 from;
1297 * diropargs3 to;
1298 * };
1300 static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
1301 const struct nfs_renameargs *args)
1303 const struct qstr *old = args->old_name;
1304 const struct qstr *new = args->new_name;
1305 struct xdr_stream xdr;
1307 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1308 encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
1309 encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
1310 return 0;
1314 * 3.3.15 LINK3args
1316 * struct LINK3args {
1317 * nfs_fh3 file;
1318 * diropargs3 link;
1319 * };
1321 static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
1322 const struct nfs3_linkargs *args)
1324 struct xdr_stream xdr;
1326 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1327 encode_nfs_fh3(&xdr, args->fromfh);
1328 encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
1329 return 0;
1333 * 3.3.16 READDIR3args
1335 * struct READDIR3args {
1336 * nfs_fh3 dir;
1337 * cookie3 cookie;
1338 * cookieverf3 cookieverf;
1339 * count3 count;
1340 * };
1342 static void encode_readdir3args(struct xdr_stream *xdr,
1343 const struct nfs3_readdirargs *args)
1345 __be32 *p;
1347 encode_nfs_fh3(xdr, args->fh);
1349 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1350 p = xdr_encode_cookie3(p, args->cookie);
1351 p = xdr_encode_cookieverf3(p, args->verf);
1352 *p = cpu_to_be32(args->count);
1355 static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1356 const struct nfs3_readdirargs *args)
1358 struct xdr_stream xdr;
1360 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1361 encode_readdir3args(&xdr, args);
1362 prepare_reply_buffer(req, args->pages, 0,
1363 args->count, NFS3_readdirres_sz);
1364 return 0;
1368 * 3.3.17 READDIRPLUS3args
1370 * struct READDIRPLUS3args {
1371 * nfs_fh3 dir;
1372 * cookie3 cookie;
1373 * cookieverf3 cookieverf;
1374 * count3 dircount;
1375 * count3 maxcount;
1376 * };
1378 static void encode_readdirplus3args(struct xdr_stream *xdr,
1379 const struct nfs3_readdirargs *args)
1381 __be32 *p;
1383 encode_nfs_fh3(xdr, args->fh);
1385 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1386 p = xdr_encode_cookie3(p, args->cookie);
1387 p = xdr_encode_cookieverf3(p, args->verf);
1390 * readdirplus: need dircount + buffer size.
1391 * We just make sure we make dircount big enough
1393 *p++ = cpu_to_be32(args->count >> 3);
1395 *p = cpu_to_be32(args->count);
1398 static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1399 const struct nfs3_readdirargs *args)
1401 struct xdr_stream xdr;
1403 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1404 encode_readdirplus3args(&xdr, args);
1405 prepare_reply_buffer(req, args->pages, 0,
1406 args->count, NFS3_readdirres_sz);
1407 return 0;
1411 * Decode the result of a readdir call.
1412 * We just check for syntactical correctness.
1414 static int
1415 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1417 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1418 struct kvec *iov = rcvbuf->head;
1419 struct page **page;
1420 size_t hdrlen;
1421 u32 recvd, pglen;
1422 int status;
1424 status = ntohl(*p++);
1425 /* Decode post_op_attrs */
1426 p = xdr_decode_post_op_attr(p, res->dir_attr);
1427 if (status)
1428 return nfs_stat_to_errno(status);
1429 /* Decode verifier cookie */
1430 if (res->verf) {
1431 res->verf[0] = *p++;
1432 res->verf[1] = *p++;
1433 } else {
1434 p += 2;
1437 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1438 if (iov->iov_len < hdrlen) {
1439 dprintk("NFS: READDIR reply header overflowed:"
1440 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1441 return -errno_NFSERR_IO;
1442 } else if (iov->iov_len != hdrlen) {
1443 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
1444 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1447 pglen = rcvbuf->page_len;
1448 recvd = rcvbuf->len - hdrlen;
1449 if (pglen > recvd)
1450 pglen = recvd;
1451 page = rcvbuf->pages;
1453 return pglen;
1457 * 3.3.21 COMMIT3args
1459 * struct COMMIT3args {
1460 * nfs_fh3 file;
1461 * offset3 offset;
1462 * count3 count;
1463 * };
1465 static void encode_commit3args(struct xdr_stream *xdr,
1466 const struct nfs_writeargs *args)
1468 __be32 *p;
1470 encode_nfs_fh3(xdr, args->fh);
1472 p = xdr_reserve_space(xdr, 8 + 4);
1473 p = xdr_encode_hyper(p, args->offset);
1474 *p = cpu_to_be32(args->count);
1477 static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1478 const struct nfs_writeargs *args)
1480 struct xdr_stream xdr;
1482 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1483 encode_commit3args(&xdr, args);
1484 return 0;
1487 #ifdef CONFIG_NFS_V3_ACL
1489 static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1490 const struct nfs3_getaclargs *args)
1492 struct xdr_stream xdr;
1494 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1495 encode_nfs_fh3(&xdr, args->fh);
1496 encode_uint32(&xdr, args->mask);
1497 if (args->mask & (NFS_ACL | NFS_DFACL))
1498 prepare_reply_buffer(req, args->pages, 0,
1499 NFSACL_MAXPAGES << PAGE_SHIFT,
1500 ACL3_getaclres_sz);
1501 return 0;
1504 static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1505 const struct nfs3_setaclargs *args)
1507 struct xdr_stream xdr;
1508 unsigned int base;
1509 int error;
1511 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1512 encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1513 encode_uint32(&xdr, args->mask);
1514 if (args->npages != 0)
1515 xdr_write_pages(&xdr, args->pages, 0, args->len);
1517 base = req->rq_slen;
1518 error = nfsacl_encode(xdr.buf, base, args->inode,
1519 (args->mask & NFS_ACL) ?
1520 args->acl_access : NULL, 1, 0);
1521 BUG_ON(error < 0);
1522 error = nfsacl_encode(xdr.buf, base + error, args->inode,
1523 (args->mask & NFS_DFACL) ?
1524 args->acl_default : NULL, 1,
1525 NFS_ACL_DEFAULT);
1526 BUG_ON(error < 0);
1527 return 0;
1530 #endif /* CONFIG_NFS_V3_ACL */
1533 * NFS XDR decode functions
1537 * Decode attrstat reply.
1539 static int
1540 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1542 int status;
1544 if ((status = ntohl(*p++)))
1545 return nfs_stat_to_errno(status);
1546 xdr_decode_fattr(p, fattr);
1547 return 0;
1551 * 3.3.1 GETATTR3res
1553 * struct GETATTR3resok {
1554 * fattr3 obj_attributes;
1555 * };
1557 * union GETATTR3res switch (nfsstat3 status) {
1558 * case NFS3_OK:
1559 * GETATTR3resok resok;
1560 * default:
1561 * void;
1562 * };
1564 static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, __be32 *p,
1565 struct nfs_fattr *result)
1567 struct xdr_stream xdr;
1568 enum nfs_stat status;
1569 int error;
1571 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1572 error = decode_nfsstat3(&xdr, &status);
1573 if (unlikely(error))
1574 goto out;
1575 if (status != NFS3_OK)
1576 goto out_default;
1577 error = decode_fattr3(&xdr, result);
1578 out:
1579 return error;
1580 out_default:
1581 return nfs_stat_to_errno(status);
1585 * Decode status+wcc_data reply
1586 * SATTR, REMOVE, RMDIR
1588 static int
1589 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1591 int status;
1593 if ((status = ntohl(*p++)))
1594 status = nfs_stat_to_errno(status);
1595 xdr_decode_wcc_data(p, fattr);
1596 return status;
1600 * 3.3.2 SETATTR3res
1602 * struct SETATTR3resok {
1603 * wcc_data obj_wcc;
1604 * };
1606 * struct SETATTR3resfail {
1607 * wcc_data obj_wcc;
1608 * };
1610 * union SETATTR3res switch (nfsstat3 status) {
1611 * case NFS3_OK:
1612 * SETATTR3resok resok;
1613 * default:
1614 * SETATTR3resfail resfail;
1615 * };
1617 static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, __be32 *p,
1618 struct nfs_fattr *result)
1620 struct xdr_stream xdr;
1621 enum nfs_stat status;
1622 int error;
1624 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1625 error = decode_nfsstat3(&xdr, &status);
1626 if (unlikely(error))
1627 goto out;
1628 error = decode_wcc_data(&xdr, result);
1629 if (unlikely(error))
1630 goto out;
1631 if (status != NFS3_OK)
1632 goto out_status;
1633 out:
1634 return error;
1635 out_status:
1636 return nfs_stat_to_errno(status);
1639 static int
1640 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1642 return nfs3_xdr_wccstat(req, p, res->dir_attr);
1646 * Decode LOOKUP reply
1648 static int
1649 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1651 int status;
1653 if ((status = ntohl(*p++))) {
1654 status = nfs_stat_to_errno(status);
1655 } else {
1656 if (!(p = xdr_decode_fhandle(p, res->fh)))
1657 return -errno_NFSERR_IO;
1658 p = xdr_decode_post_op_attr(p, res->fattr);
1660 xdr_decode_post_op_attr(p, res->dir_attr);
1661 return status;
1665 * 3.3.3 LOOKUP3res
1667 * struct LOOKUP3resok {
1668 * nfs_fh3 object;
1669 * post_op_attr obj_attributes;
1670 * post_op_attr dir_attributes;
1671 * };
1673 * struct LOOKUP3resfail {
1674 * post_op_attr dir_attributes;
1675 * };
1677 * union LOOKUP3res switch (nfsstat3 status) {
1678 * case NFS3_OK:
1679 * LOOKUP3resok resok;
1680 * default:
1681 * LOOKUP3resfail resfail;
1682 * };
1684 static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, __be32 *p,
1685 struct nfs3_diropres *result)
1687 struct xdr_stream xdr;
1688 enum nfs_stat status;
1689 int error;
1691 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1692 error = decode_nfsstat3(&xdr, &status);
1693 if (unlikely(error))
1694 goto out;
1695 if (status != NFS3_OK)
1696 goto out_default;
1697 error = decode_nfs_fh3(&xdr, result->fh);
1698 if (unlikely(error))
1699 goto out;
1700 error = decode_post_op_attr(&xdr, result->fattr);
1701 if (unlikely(error))
1702 goto out;
1703 error = decode_post_op_attr(&xdr, result->dir_attr);
1704 out:
1705 return error;
1706 out_default:
1707 error = decode_post_op_attr(&xdr, result->dir_attr);
1708 if (unlikely(error))
1709 goto out;
1710 return nfs_stat_to_errno(status);
1714 * Decode ACCESS reply
1716 static int
1717 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1719 int status = ntohl(*p++);
1721 p = xdr_decode_post_op_attr(p, res->fattr);
1722 if (status)
1723 return nfs_stat_to_errno(status);
1724 res->access = ntohl(*p++);
1725 return 0;
1729 * 3.3.4 ACCESS3res
1731 * struct ACCESS3resok {
1732 * post_op_attr obj_attributes;
1733 * uint32 access;
1734 * };
1736 * struct ACCESS3resfail {
1737 * post_op_attr obj_attributes;
1738 * };
1740 * union ACCESS3res switch (nfsstat3 status) {
1741 * case NFS3_OK:
1742 * ACCESS3resok resok;
1743 * default:
1744 * ACCESS3resfail resfail;
1745 * };
1747 static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, __be32 *p,
1748 struct nfs3_accessres *result)
1750 struct xdr_stream xdr;
1751 enum nfs_stat status;
1752 int error;
1754 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1755 error = decode_nfsstat3(&xdr, &status);
1756 if (unlikely(error))
1757 goto out;
1758 error = decode_post_op_attr(&xdr, result->fattr);
1759 if (unlikely(error))
1760 goto out;
1761 if (status != NFS3_OK)
1762 goto out_default;
1763 error = decode_uint32(&xdr, &result->access);
1764 out:
1765 return error;
1766 out_default:
1767 return nfs_stat_to_errno(status);
1771 * Decode READLINK reply
1773 static int
1774 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1776 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1777 struct kvec *iov = rcvbuf->head;
1778 size_t hdrlen;
1779 u32 len, recvd;
1780 int status;
1782 status = ntohl(*p++);
1783 p = xdr_decode_post_op_attr(p, fattr);
1785 if (status != 0)
1786 return nfs_stat_to_errno(status);
1788 /* Convert length of symlink */
1789 len = ntohl(*p++);
1790 if (len >= rcvbuf->page_len) {
1791 dprintk("nfs: server returned giant symlink!\n");
1792 return -ENAMETOOLONG;
1795 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1796 if (iov->iov_len < hdrlen) {
1797 dprintk("NFS: READLINK reply header overflowed:"
1798 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1799 return -errno_NFSERR_IO;
1800 } else if (iov->iov_len != hdrlen) {
1801 dprintk("NFS: READLINK header is short. "
1802 "iovec will be shifted.\n");
1803 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1805 recvd = req->rq_rcv_buf.len - hdrlen;
1806 if (recvd < len) {
1807 dprintk("NFS: server cheating in readlink reply: "
1808 "count %u > recvd %u\n", len, recvd);
1809 return -EIO;
1812 xdr_terminate_string(rcvbuf, len);
1813 return 0;
1817 * 3.3.5 READLINK3res
1819 * struct READLINK3resok {
1820 * post_op_attr symlink_attributes;
1821 * nfspath3 data;
1822 * };
1824 * struct READLINK3resfail {
1825 * post_op_attr symlink_attributes;
1826 * };
1828 * union READLINK3res switch (nfsstat3 status) {
1829 * case NFS3_OK:
1830 * READLINK3resok resok;
1831 * default:
1832 * READLINK3resfail resfail;
1833 * };
1835 static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, __be32 *p,
1836 struct nfs_fattr *result)
1838 struct xdr_stream xdr;
1839 enum nfs_stat status;
1840 int error;
1842 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1843 error = decode_nfsstat3(&xdr, &status);
1844 if (unlikely(error))
1845 goto out;
1846 error = decode_post_op_attr(&xdr, result);
1847 if (unlikely(error))
1848 goto out;
1849 if (status != NFS3_OK)
1850 goto out_default;
1851 error = decode_nfspath3(&xdr);
1852 out:
1853 return error;
1854 out_default:
1855 return nfs_stat_to_errno(status);
1859 * Decode READ reply
1861 static int
1862 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1864 struct kvec *iov = req->rq_rcv_buf.head;
1865 size_t hdrlen;
1866 u32 count, ocount, recvd;
1867 int status;
1869 status = ntohl(*p++);
1870 p = xdr_decode_post_op_attr(p, res->fattr);
1872 if (status != 0)
1873 return nfs_stat_to_errno(status);
1875 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1876 * in that it puts the count both in the res struct and in the
1877 * opaque data count. */
1878 count = ntohl(*p++);
1879 res->eof = ntohl(*p++);
1880 ocount = ntohl(*p++);
1882 if (ocount != count) {
1883 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1884 return -errno_NFSERR_IO;
1887 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1888 if (iov->iov_len < hdrlen) {
1889 dprintk("NFS: READ reply header overflowed:"
1890 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1891 return -errno_NFSERR_IO;
1892 } else if (iov->iov_len != hdrlen) {
1893 dprintk("NFS: READ header is short. iovec will be shifted.\n");
1894 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
1897 recvd = req->rq_rcv_buf.len - hdrlen;
1898 if (count > recvd) {
1899 dprintk("NFS: server cheating in read reply: "
1900 "count %u > recvd %u\n", count, recvd);
1901 count = recvd;
1902 res->eof = 0;
1905 if (count < res->count)
1906 res->count = count;
1908 return count;
1912 * 3.3.6 READ3res
1914 * struct READ3resok {
1915 * post_op_attr file_attributes;
1916 * count3 count;
1917 * bool eof;
1918 * opaque data<>;
1919 * };
1921 * struct READ3resfail {
1922 * post_op_attr file_attributes;
1923 * };
1925 * union READ3res switch (nfsstat3 status) {
1926 * case NFS3_OK:
1927 * READ3resok resok;
1928 * default:
1929 * READ3resfail resfail;
1930 * };
1932 static int decode_read3resok(struct xdr_stream *xdr,
1933 struct nfs_readres *result)
1935 u32 eof, count, ocount, recvd;
1936 size_t hdrlen;
1937 __be32 *p;
1939 p = xdr_inline_decode(xdr, 4 + 4 + 4);
1940 if (unlikely(p == NULL))
1941 goto out_overflow;
1942 count = be32_to_cpup(p++);
1943 eof = be32_to_cpup(p++);
1944 ocount = be32_to_cpup(p++);
1945 if (unlikely(ocount != count))
1946 goto out_mismatch;
1947 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1948 recvd = xdr->buf->len - hdrlen;
1949 if (unlikely(count > recvd))
1950 goto out_cheating;
1952 out:
1953 xdr_read_pages(xdr, count);
1954 result->eof = eof;
1955 result->count = count;
1956 return count;
1957 out_mismatch:
1958 dprintk("NFS: READ count doesn't match length of opaque: "
1959 "count %u != ocount %u\n", count, ocount);
1960 return -EIO;
1961 out_cheating:
1962 dprintk("NFS: server cheating in read result: "
1963 "count %u > recvd %u\n", count, recvd);
1964 count = recvd;
1965 eof = 0;
1966 goto out;
1967 out_overflow:
1968 print_overflow_msg(__func__, xdr);
1969 return -EIO;
1972 static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, __be32 *p,
1973 struct nfs_readres *result)
1975 struct xdr_stream xdr;
1976 enum nfs_stat status;
1977 int error;
1979 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1980 error = decode_nfsstat3(&xdr, &status);
1981 if (unlikely(error))
1982 goto out;
1983 error = decode_post_op_attr(&xdr, result->fattr);
1984 if (unlikely(error))
1985 goto out;
1986 if (status != NFS3_OK)
1987 goto out_status;
1988 error = decode_read3resok(&xdr, result);
1989 out:
1990 return error;
1991 out_status:
1992 return nfs_stat_to_errno(status);
1996 * Decode WRITE response
1998 static int
1999 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
2001 int status;
2003 status = ntohl(*p++);
2004 p = xdr_decode_wcc_data(p, res->fattr);
2006 if (status != 0)
2007 return nfs_stat_to_errno(status);
2009 res->count = ntohl(*p++);
2010 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
2011 res->verf->verifier[0] = *p++;
2012 res->verf->verifier[1] = *p++;
2014 return res->count;
2018 * 3.3.7 WRITE3res
2020 * enum stable_how {
2021 * UNSTABLE = 0,
2022 * DATA_SYNC = 1,
2023 * FILE_SYNC = 2
2024 * };
2026 * struct WRITE3resok {
2027 * wcc_data file_wcc;
2028 * count3 count;
2029 * stable_how committed;
2030 * writeverf3 verf;
2031 * };
2033 * struct WRITE3resfail {
2034 * wcc_data file_wcc;
2035 * };
2037 * union WRITE3res switch (nfsstat3 status) {
2038 * case NFS3_OK:
2039 * WRITE3resok resok;
2040 * default:
2041 * WRITE3resfail resfail;
2042 * };
2044 static int decode_write3resok(struct xdr_stream *xdr,
2045 struct nfs_writeres *result)
2047 __be32 *p;
2049 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
2050 if (unlikely(p == NULL))
2051 goto out_overflow;
2052 result->count = be32_to_cpup(p++);
2053 result->verf->committed = be32_to_cpup(p++);
2054 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
2055 goto out_badvalue;
2056 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
2057 return result->count;
2058 out_badvalue:
2059 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
2060 return -EIO;
2061 out_overflow:
2062 print_overflow_msg(__func__, xdr);
2063 return -EIO;
2066 static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, __be32 *p,
2067 struct nfs_writeres *result)
2069 struct xdr_stream xdr;
2070 enum nfs_stat status;
2071 int error;
2073 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2074 error = decode_nfsstat3(&xdr, &status);
2075 if (unlikely(error))
2076 goto out;
2077 error = decode_wcc_data(&xdr, result->fattr);
2078 if (unlikely(error))
2079 goto out;
2080 if (status != NFS3_OK)
2081 goto out_status;
2082 error = decode_write3resok(&xdr, result);
2083 out:
2084 return error;
2085 out_status:
2086 return nfs_stat_to_errno(status);
2090 * Decode a CREATE response
2092 static int
2093 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
2095 int status;
2097 status = ntohl(*p++);
2098 if (status == 0) {
2099 if (*p++) {
2100 if (!(p = xdr_decode_fhandle(p, res->fh)))
2101 return -errno_NFSERR_IO;
2102 p = xdr_decode_post_op_attr(p, res->fattr);
2103 } else {
2104 memset(res->fh, 0, sizeof(*res->fh));
2105 /* Do decode post_op_attr but set it to NULL */
2106 p = xdr_decode_post_op_attr(p, res->fattr);
2107 res->fattr->valid = 0;
2109 } else {
2110 status = nfs_stat_to_errno(status);
2112 p = xdr_decode_wcc_data(p, res->dir_attr);
2113 return status;
2117 * 3.3.8 CREATE3res
2119 * struct CREATE3resok {
2120 * post_op_fh3 obj;
2121 * post_op_attr obj_attributes;
2122 * wcc_data dir_wcc;
2123 * };
2125 * struct CREATE3resfail {
2126 * wcc_data dir_wcc;
2127 * };
2129 * union CREATE3res switch (nfsstat3 status) {
2130 * case NFS3_OK:
2131 * CREATE3resok resok;
2132 * default:
2133 * CREATE3resfail resfail;
2134 * };
2136 static int decode_create3resok(struct xdr_stream *xdr,
2137 struct nfs3_diropres *result)
2139 int error;
2141 error = decode_post_op_fh3(xdr, result->fh);
2142 if (unlikely(error))
2143 goto out;
2144 error = decode_post_op_attr(xdr, result->fattr);
2145 if (unlikely(error))
2146 goto out;
2147 /* The server isn't required to return a file handle.
2148 * If it didn't, force the client to perform a LOOKUP
2149 * to determine the correct file handle and attribute
2150 * values for the new object. */
2151 if (result->fh->size == 0)
2152 result->fattr->valid = 0;
2153 error = decode_wcc_data(xdr, result->dir_attr);
2154 out:
2155 return error;
2158 static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, __be32 *p,
2159 struct nfs3_diropres *result)
2161 struct xdr_stream xdr;
2162 enum nfs_stat status;
2163 int error;
2165 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2166 error = decode_nfsstat3(&xdr, &status);
2167 if (unlikely(error))
2168 goto out;
2169 if (status != NFS3_OK)
2170 goto out_default;
2171 error = decode_create3resok(&xdr, result);
2172 out:
2173 return error;
2174 out_default:
2175 error = decode_wcc_data(&xdr, result->dir_attr);
2176 if (unlikely(error))
2177 goto out;
2178 return nfs_stat_to_errno(status);
2182 * 3.3.12 REMOVE3res
2184 * struct REMOVE3resok {
2185 * wcc_data dir_wcc;
2186 * };
2188 * struct REMOVE3resfail {
2189 * wcc_data dir_wcc;
2190 * };
2192 * union REMOVE3res switch (nfsstat3 status) {
2193 * case NFS3_OK:
2194 * REMOVE3resok resok;
2195 * default:
2196 * REMOVE3resfail resfail;
2197 * };
2199 static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, __be32 *p,
2200 struct nfs_removeres *result)
2202 struct xdr_stream xdr;
2203 enum nfs_stat status;
2204 int error;
2206 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2207 error = decode_nfsstat3(&xdr, &status);
2208 if (unlikely(error))
2209 goto out;
2210 error = decode_wcc_data(&xdr, result->dir_attr);
2211 if (unlikely(error))
2212 goto out;
2213 if (status != NFS3_OK)
2214 goto out_status;
2215 out:
2216 return error;
2217 out_status:
2218 return nfs_stat_to_errno(status);
2222 * Decode RENAME reply
2224 static int
2225 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
2227 int status;
2229 if ((status = ntohl(*p++)) != 0)
2230 status = nfs_stat_to_errno(status);
2231 p = xdr_decode_wcc_data(p, res->old_fattr);
2232 p = xdr_decode_wcc_data(p, res->new_fattr);
2233 return status;
2237 * 3.3.14 RENAME3res
2239 * struct RENAME3resok {
2240 * wcc_data fromdir_wcc;
2241 * wcc_data todir_wcc;
2242 * };
2244 * struct RENAME3resfail {
2245 * wcc_data fromdir_wcc;
2246 * wcc_data todir_wcc;
2247 * };
2249 * union RENAME3res switch (nfsstat3 status) {
2250 * case NFS3_OK:
2251 * RENAME3resok resok;
2252 * default:
2253 * RENAME3resfail resfail;
2254 * };
2256 static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, __be32 *p,
2257 struct nfs_renameres *result)
2259 struct xdr_stream xdr;
2260 enum nfs_stat status;
2261 int error;
2263 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2264 error = decode_nfsstat3(&xdr, &status);
2265 if (unlikely(error))
2266 goto out;
2267 error = decode_wcc_data(&xdr, result->old_fattr);
2268 if (unlikely(error))
2269 goto out;
2270 error = decode_wcc_data(&xdr, result->new_fattr);
2271 if (unlikely(error))
2272 goto out;
2273 if (status != NFS3_OK)
2274 goto out_status;
2275 out:
2276 return error;
2277 out_status:
2278 return nfs_stat_to_errno(status);
2282 * Decode LINK reply
2284 static int
2285 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
2287 int status;
2289 if ((status = ntohl(*p++)) != 0)
2290 status = nfs_stat_to_errno(status);
2291 p = xdr_decode_post_op_attr(p, res->fattr);
2292 p = xdr_decode_wcc_data(p, res->dir_attr);
2293 return status;
2297 * 3.3.15 LINK3res
2299 * struct LINK3resok {
2300 * post_op_attr file_attributes;
2301 * wcc_data linkdir_wcc;
2302 * };
2304 * struct LINK3resfail {
2305 * post_op_attr file_attributes;
2306 * wcc_data linkdir_wcc;
2307 * };
2309 * union LINK3res switch (nfsstat3 status) {
2310 * case NFS3_OK:
2311 * LINK3resok resok;
2312 * default:
2313 * LINK3resfail resfail;
2314 * };
2316 static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, __be32 *p,
2317 struct nfs3_linkres *result)
2319 struct xdr_stream xdr;
2320 enum nfs_stat status;
2321 int error;
2323 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2324 error = decode_nfsstat3(&xdr, &status);
2325 if (unlikely(error))
2326 goto out;
2327 error = decode_post_op_attr(&xdr, result->fattr);
2328 if (unlikely(error))
2329 goto out;
2330 error = decode_wcc_data(&xdr, result->dir_attr);
2331 if (unlikely(error))
2332 goto out;
2333 if (status != NFS3_OK)
2334 goto out_status;
2335 out:
2336 return error;
2337 out_status:
2338 return nfs_stat_to_errno(status);
2342 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
2343 * the local page cache
2344 * @xdr: XDR stream where entry resides
2345 * @entry: buffer to fill in with entry data
2346 * @server: nfs_server data for this directory
2347 * @plus: boolean indicating whether this should be a readdirplus entry
2349 * Returns the position of the next item in the buffer, or an ERR_PTR.
2351 * This function is not invoked during READDIR reply decoding, but
2352 * rather whenever an application invokes the getdents(2) system call
2353 * on a directory already in our cache.
2355 * 3.3.16 entry3
2357 * struct entry3 {
2358 * fileid3 fileid;
2359 * filename3 name;
2360 * cookie3 cookie;
2361 * fhandle3 filehandle;
2362 * post_op_attr3 attributes;
2363 * entry3 *nextentry;
2364 * };
2366 * 3.3.17 entryplus3
2367 * struct entryplus3 {
2368 * fileid3 fileid;
2369 * filename3 name;
2370 * cookie3 cookie;
2371 * post_op_attr name_attributes;
2372 * post_op_fh3 name_handle;
2373 * entryplus3 *nextentry;
2374 * };
2376 __be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2377 struct nfs_server *server, int plus)
2379 struct nfs_entry old = *entry;
2380 __be32 *p;
2381 int error;
2383 p = xdr_inline_decode(xdr, 4);
2384 if (unlikely(p == NULL))
2385 goto out_overflow;
2386 if (*p == xdr_zero) {
2387 p = xdr_inline_decode(xdr, 4);
2388 if (unlikely(p == NULL))
2389 goto out_overflow;
2390 if (*p == xdr_zero)
2391 return ERR_PTR(-EAGAIN);
2392 entry->eof = 1;
2393 return ERR_PTR(-EBADCOOKIE);
2396 error = decode_fileid3(xdr, &entry->ino);
2397 if (unlikely(error))
2398 return ERR_PTR(error);
2400 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2401 if (unlikely(error))
2402 return ERR_PTR(error);
2404 entry->prev_cookie = entry->cookie;
2405 error = decode_cookie3(xdr, &entry->cookie);
2406 if (unlikely(error))
2407 return ERR_PTR(error);
2409 entry->d_type = DT_UNKNOWN;
2411 if (plus) {
2412 entry->fattr->valid = 0;
2413 error = decode_post_op_attr(xdr, entry->fattr);
2414 if (unlikely(error))
2415 return ERR_PTR(error);
2416 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2417 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2419 /* In fact, a post_op_fh3: */
2420 p = xdr_inline_decode(xdr, 4);
2421 if (unlikely(p == NULL))
2422 goto out_overflow;
2423 if (*p != xdr_zero) {
2424 error = decode_nfs_fh3(xdr, entry->fh);
2425 if (unlikely(error)) {
2426 if (error == -E2BIG)
2427 goto out_truncated;
2428 return ERR_PTR(error);
2430 } else
2431 zero_nfs_fh3(entry->fh);
2434 /* Peek at the next entry to see if we're at EOD */
2435 p = xdr_inline_peek(xdr, 4 + 4);
2436 entry->eof = 0;
2437 if (p != NULL)
2438 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
2439 return p;
2441 out_overflow:
2442 print_overflow_msg(__func__, xdr);
2443 return ERR_PTR(-EAGAIN);
2444 out_truncated:
2445 dprintk("NFS: directory entry contains invalid file handle\n");
2446 *entry = old;
2447 return ERR_PTR(-EAGAIN);
2451 * 3.3.16 READDIR3res
2453 * struct dirlist3 {
2454 * entry3 *entries;
2455 * bool eof;
2456 * };
2458 * struct READDIR3resok {
2459 * post_op_attr dir_attributes;
2460 * cookieverf3 cookieverf;
2461 * dirlist3 reply;
2462 * };
2464 * struct READDIR3resfail {
2465 * post_op_attr dir_attributes;
2466 * };
2468 * union READDIR3res switch (nfsstat3 status) {
2469 * case NFS3_OK:
2470 * READDIR3resok resok;
2471 * default:
2472 * READDIR3resfail resfail;
2473 * };
2475 * Read the directory contents into the page cache, but otherwise
2476 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2477 * during subsequent nfs_readdir() calls.
2479 static int decode_dirlist3(struct xdr_stream *xdr)
2481 u32 recvd, pglen;
2482 size_t hdrlen;
2484 pglen = xdr->buf->page_len;
2485 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2486 recvd = xdr->buf->len - hdrlen;
2487 if (unlikely(pglen > recvd))
2488 goto out_cheating;
2489 out:
2490 xdr_read_pages(xdr, pglen);
2491 return pglen;
2492 out_cheating:
2493 dprintk("NFS: server cheating in readdir result: "
2494 "pglen %u > recvd %u\n", pglen, recvd);
2495 pglen = recvd;
2496 goto out;
2499 static int decode_readdir3resok(struct xdr_stream *xdr,
2500 struct nfs3_readdirres *result)
2502 int error;
2504 error = decode_post_op_attr(xdr, result->dir_attr);
2505 if (unlikely(error))
2506 goto out;
2507 /* XXX: do we need to check if result->verf != NULL ? */
2508 error = decode_cookieverf3(xdr, result->verf);
2509 if (unlikely(error))
2510 goto out;
2511 error = decode_dirlist3(xdr);
2512 out:
2513 return error;
2516 static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, __be32 *p,
2517 struct nfs3_readdirres *result)
2519 struct xdr_stream xdr;
2520 enum nfs_stat status;
2521 int error;
2523 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2524 error = decode_nfsstat3(&xdr, &status);
2525 if (unlikely(error))
2526 goto out;
2527 if (status != NFS3_OK)
2528 goto out_default;
2529 error = decode_readdir3resok(&xdr, result);
2530 out:
2531 return error;
2532 out_default:
2533 error = decode_post_op_attr(&xdr, result->dir_attr);
2534 if (unlikely(error))
2535 goto out;
2536 return nfs_stat_to_errno(status);
2540 * Decode FSSTAT reply
2542 static int
2543 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
2545 int status;
2547 status = ntohl(*p++);
2549 p = xdr_decode_post_op_attr(p, res->fattr);
2550 if (status != 0)
2551 return nfs_stat_to_errno(status);
2553 p = xdr_decode_hyper(p, &res->tbytes);
2554 p = xdr_decode_hyper(p, &res->fbytes);
2555 p = xdr_decode_hyper(p, &res->abytes);
2556 p = xdr_decode_hyper(p, &res->tfiles);
2557 p = xdr_decode_hyper(p, &res->ffiles);
2558 p = xdr_decode_hyper(p, &res->afiles);
2560 /* ignore invarsec */
2561 return 0;
2565 * 3.3.18 FSSTAT3res
2567 * struct FSSTAT3resok {
2568 * post_op_attr obj_attributes;
2569 * size3 tbytes;
2570 * size3 fbytes;
2571 * size3 abytes;
2572 * size3 tfiles;
2573 * size3 ffiles;
2574 * size3 afiles;
2575 * uint32 invarsec;
2576 * };
2578 * struct FSSTAT3resfail {
2579 * post_op_attr obj_attributes;
2580 * };
2582 * union FSSTAT3res switch (nfsstat3 status) {
2583 * case NFS3_OK:
2584 * FSSTAT3resok resok;
2585 * default:
2586 * FSSTAT3resfail resfail;
2587 * };
2589 static int decode_fsstat3resok(struct xdr_stream *xdr,
2590 struct nfs_fsstat *result)
2592 __be32 *p;
2594 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2595 if (unlikely(p == NULL))
2596 goto out_overflow;
2597 p = xdr_decode_size3(p, &result->tbytes);
2598 p = xdr_decode_size3(p, &result->fbytes);
2599 p = xdr_decode_size3(p, &result->abytes);
2600 p = xdr_decode_size3(p, &result->tfiles);
2601 p = xdr_decode_size3(p, &result->ffiles);
2602 xdr_decode_size3(p, &result->afiles);
2603 /* ignore invarsec */
2604 return 0;
2605 out_overflow:
2606 print_overflow_msg(__func__, xdr);
2607 return -EIO;
2610 static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, __be32 *p,
2611 struct nfs_fsstat *result)
2613 struct xdr_stream xdr;
2614 enum nfs_stat status;
2615 int error;
2617 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2618 error = decode_nfsstat3(&xdr, &status);
2619 if (unlikely(error))
2620 goto out;
2621 error = decode_post_op_attr(&xdr, result->fattr);
2622 if (unlikely(error))
2623 goto out;
2624 if (status != NFS3_OK)
2625 goto out_status;
2626 error = decode_fsstat3resok(&xdr, result);
2627 out:
2628 return error;
2629 out_status:
2630 return nfs_stat_to_errno(status);
2634 * Decode FSINFO reply
2636 static int
2637 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
2639 int status;
2641 status = ntohl(*p++);
2643 p = xdr_decode_post_op_attr(p, res->fattr);
2644 if (status != 0)
2645 return nfs_stat_to_errno(status);
2647 res->rtmax = ntohl(*p++);
2648 res->rtpref = ntohl(*p++);
2649 res->rtmult = ntohl(*p++);
2650 res->wtmax = ntohl(*p++);
2651 res->wtpref = ntohl(*p++);
2652 res->wtmult = ntohl(*p++);
2653 res->dtpref = ntohl(*p++);
2654 p = xdr_decode_hyper(p, &res->maxfilesize);
2655 p = xdr_decode_time3(p, &res->time_delta);
2657 /* ignore properties */
2658 res->lease_time = 0;
2659 return 0;
2663 * 3.3.19 FSINFO3res
2665 * struct FSINFO3resok {
2666 * post_op_attr obj_attributes;
2667 * uint32 rtmax;
2668 * uint32 rtpref;
2669 * uint32 rtmult;
2670 * uint32 wtmax;
2671 * uint32 wtpref;
2672 * uint32 wtmult;
2673 * uint32 dtpref;
2674 * size3 maxfilesize;
2675 * nfstime3 time_delta;
2676 * uint32 properties;
2677 * };
2679 * struct FSINFO3resfail {
2680 * post_op_attr obj_attributes;
2681 * };
2683 * union FSINFO3res switch (nfsstat3 status) {
2684 * case NFS3_OK:
2685 * FSINFO3resok resok;
2686 * default:
2687 * FSINFO3resfail resfail;
2688 * };
2690 static int decode_fsinfo3resok(struct xdr_stream *xdr,
2691 struct nfs_fsinfo *result)
2693 __be32 *p;
2695 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2696 if (unlikely(p == NULL))
2697 goto out_overflow;
2698 result->rtmax = be32_to_cpup(p++);
2699 result->rtpref = be32_to_cpup(p++);
2700 result->rtmult = be32_to_cpup(p++);
2701 result->wtmax = be32_to_cpup(p++);
2702 result->wtpref = be32_to_cpup(p++);
2703 result->wtmult = be32_to_cpup(p++);
2704 result->dtpref = be32_to_cpup(p++);
2705 p = xdr_decode_size3(p, &result->maxfilesize);
2706 xdr_decode_time3(p, &result->time_delta);
2708 /* ignore properties */
2709 result->lease_time = 0;
2710 return 0;
2711 out_overflow:
2712 print_overflow_msg(__func__, xdr);
2713 return -EIO;
2716 static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, __be32 *p,
2717 struct nfs_fsinfo *result)
2719 struct xdr_stream xdr;
2720 enum nfs_stat status;
2721 int error;
2723 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2724 error = decode_nfsstat3(&xdr, &status);
2725 if (unlikely(error))
2726 goto out;
2727 error = decode_post_op_attr(&xdr, result->fattr);
2728 if (unlikely(error))
2729 goto out;
2730 if (status != NFS3_OK)
2731 goto out_status;
2732 error = decode_fsinfo3resok(&xdr, result);
2733 out:
2734 return error;
2735 out_status:
2736 return nfs_stat_to_errno(status);
2740 * Decode PATHCONF reply
2742 static int
2743 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
2745 int status;
2747 status = ntohl(*p++);
2749 p = xdr_decode_post_op_attr(p, res->fattr);
2750 if (status != 0)
2751 return nfs_stat_to_errno(status);
2752 res->max_link = ntohl(*p++);
2753 res->max_namelen = ntohl(*p++);
2755 /* ignore remaining fields */
2756 return 0;
2760 * 3.3.20 PATHCONF3res
2762 * struct PATHCONF3resok {
2763 * post_op_attr obj_attributes;
2764 * uint32 linkmax;
2765 * uint32 name_max;
2766 * bool no_trunc;
2767 * bool chown_restricted;
2768 * bool case_insensitive;
2769 * bool case_preserving;
2770 * };
2772 * struct PATHCONF3resfail {
2773 * post_op_attr obj_attributes;
2774 * };
2776 * union PATHCONF3res switch (nfsstat3 status) {
2777 * case NFS3_OK:
2778 * PATHCONF3resok resok;
2779 * default:
2780 * PATHCONF3resfail resfail;
2781 * };
2783 static int decode_pathconf3resok(struct xdr_stream *xdr,
2784 struct nfs_pathconf *result)
2786 __be32 *p;
2788 p = xdr_inline_decode(xdr, 4 * 6);
2789 if (unlikely(p == NULL))
2790 goto out_overflow;
2791 result->max_link = be32_to_cpup(p++);
2792 result->max_namelen = be32_to_cpup(p);
2793 /* ignore remaining fields */
2794 return 0;
2795 out_overflow:
2796 print_overflow_msg(__func__, xdr);
2797 return -EIO;
2800 static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, __be32 *p,
2801 struct nfs_pathconf *result)
2803 struct xdr_stream xdr;
2804 enum nfs_stat status;
2805 int error;
2807 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2808 error = decode_nfsstat3(&xdr, &status);
2809 if (unlikely(error))
2810 goto out;
2811 error = decode_post_op_attr(&xdr, result->fattr);
2812 if (unlikely(error))
2813 goto out;
2814 if (status != NFS3_OK)
2815 goto out_status;
2816 error = decode_pathconf3resok(&xdr, result);
2817 out:
2818 return error;
2819 out_status:
2820 return nfs_stat_to_errno(status);
2824 * Decode COMMIT reply
2826 static int
2827 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
2829 int status;
2831 status = ntohl(*p++);
2832 p = xdr_decode_wcc_data(p, res->fattr);
2833 if (status != 0)
2834 return nfs_stat_to_errno(status);
2836 res->verf->verifier[0] = *p++;
2837 res->verf->verifier[1] = *p++;
2838 return 0;
2842 * 3.3.21 COMMIT3res
2844 * struct COMMIT3resok {
2845 * wcc_data file_wcc;
2846 * writeverf3 verf;
2847 * };
2849 * struct COMMIT3resfail {
2850 * wcc_data file_wcc;
2851 * };
2853 * union COMMIT3res switch (nfsstat3 status) {
2854 * case NFS3_OK:
2855 * COMMIT3resok resok;
2856 * default:
2857 * COMMIT3resfail resfail;
2858 * };
2860 static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, __be32 *p,
2861 struct nfs_writeres *result)
2863 struct xdr_stream xdr;
2864 enum nfs_stat status;
2865 int error;
2867 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2868 error = decode_nfsstat3(&xdr, &status);
2869 if (unlikely(error))
2870 goto out;
2871 error = decode_wcc_data(&xdr, result->fattr);
2872 if (unlikely(error))
2873 goto out;
2874 if (status != NFS3_OK)
2875 goto out_status;
2876 error = decode_writeverf3(&xdr, result->verf->verifier);
2877 out:
2878 return error;
2879 out_status:
2880 return nfs_stat_to_errno(status);
2883 #ifdef CONFIG_NFS_V3_ACL
2885 * Decode GETACL reply
2887 static int
2888 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
2889 struct nfs3_getaclres *res)
2891 struct xdr_buf *buf = &req->rq_rcv_buf;
2892 int status = ntohl(*p++);
2893 struct posix_acl **acl;
2894 unsigned int *aclcnt;
2895 int err, base;
2897 if (status != 0)
2898 return nfs_stat_to_errno(status);
2899 p = xdr_decode_post_op_attr(p, res->fattr);
2900 res->mask = ntohl(*p++);
2901 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2902 return -EINVAL;
2903 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
2905 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
2906 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
2907 err = nfsacl_decode(buf, base, aclcnt, acl);
2909 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
2910 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
2911 if (err > 0)
2912 err = nfsacl_decode(buf, base + err, aclcnt, acl);
2913 return (err > 0) ? 0 : err;
2916 static inline int decode_getacl3resok(struct xdr_stream *xdr,
2917 struct nfs3_getaclres *result)
2919 struct posix_acl **acl;
2920 unsigned int *aclcnt;
2921 size_t hdrlen;
2922 int error;
2924 error = decode_post_op_attr(xdr, result->fattr);
2925 if (unlikely(error))
2926 goto out;
2927 error = decode_uint32(xdr, &result->mask);
2928 if (unlikely(error))
2929 goto out;
2930 error = -EINVAL;
2931 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2932 goto out;
2934 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2936 acl = NULL;
2937 if (result->mask & NFS_ACL)
2938 acl = &result->acl_access;
2939 aclcnt = NULL;
2940 if (result->mask & NFS_ACLCNT)
2941 aclcnt = &result->acl_access_count;
2942 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2943 if (unlikely(error <= 0))
2944 goto out;
2946 acl = NULL;
2947 if (result->mask & NFS_DFACL)
2948 acl = &result->acl_default;
2949 aclcnt = NULL;
2950 if (result->mask & NFS_DFACLCNT)
2951 aclcnt = &result->acl_default_count;
2952 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2953 if (unlikely(error <= 0))
2954 return error;
2955 error = 0;
2956 out:
2957 return error;
2960 static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, __be32 *p,
2961 struct nfs3_getaclres *result)
2963 struct xdr_stream xdr;
2964 enum nfs_stat status;
2965 int error;
2967 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2968 error = decode_nfsstat3(&xdr, &status);
2969 if (unlikely(error))
2970 goto out;
2971 if (status != NFS3_OK)
2972 goto out_default;
2973 error = decode_getacl3resok(&xdr, result);
2974 out:
2975 return error;
2976 out_default:
2977 return nfs_stat_to_errno(status);
2981 * Decode setacl reply.
2983 static int
2984 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
2986 int status = ntohl(*p++);
2988 if (status)
2989 return nfs_stat_to_errno(status);
2990 xdr_decode_post_op_attr(p, fattr);
2991 return 0;
2994 static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, __be32 *p,
2995 struct nfs_fattr *result)
2997 struct xdr_stream xdr;
2998 enum nfs_stat status;
2999 int error;
3001 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
3002 error = decode_nfsstat3(&xdr, &status);
3003 if (unlikely(error))
3004 goto out;
3005 if (status != NFS3_OK)
3006 goto out_default;
3007 error = decode_post_op_attr(&xdr, result);
3008 out:
3009 return error;
3010 out_default:
3011 return nfs_stat_to_errno(status);
3014 #endif /* CONFIG_NFS_V3_ACL */
3016 #define PROC(proc, argtype, restype, timer) \
3017 [NFS3PROC_##proc] = { \
3018 .p_proc = NFS3PROC_##proc, \
3019 .p_encode = (kxdrproc_t)nfs3_xdr_enc_##argtype##3args, \
3020 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
3021 .p_arglen = NFS3_##argtype##args_sz, \
3022 .p_replen = NFS3_##restype##_sz, \
3023 .p_timer = timer, \
3024 .p_statidx = NFS3PROC_##proc, \
3025 .p_name = #proc, \
3028 struct rpc_procinfo nfs3_procedures[] = {
3029 PROC(GETATTR, getattr, attrstat, 1),
3030 PROC(SETATTR, setattr, wccstat, 0),
3031 PROC(LOOKUP, lookup, lookupres, 2),
3032 PROC(ACCESS, access, accessres, 1),
3033 PROC(READLINK, readlink, readlinkres, 3),
3034 PROC(READ, read, readres, 3),
3035 PROC(WRITE, write, writeres, 4),
3036 PROC(CREATE, create, createres, 0),
3037 PROC(MKDIR, mkdir, createres, 0),
3038 PROC(SYMLINK, symlink, createres, 0),
3039 PROC(MKNOD, mknod, createres, 0),
3040 PROC(REMOVE, remove, removeres, 0),
3041 PROC(RMDIR, lookup, wccstat, 0),
3042 PROC(RENAME, rename, renameres, 0),
3043 PROC(LINK, link, linkres, 0),
3044 PROC(READDIR, readdir, readdirres, 3),
3045 PROC(READDIRPLUS, readdirplus, readdirres, 3),
3046 PROC(FSSTAT, getattr, fsstatres, 0),
3047 PROC(FSINFO, getattr, fsinfores, 0),
3048 PROC(PATHCONF, getattr, pathconfres, 0),
3049 PROC(COMMIT, commit, commitres, 5),
3052 struct rpc_version nfs_version3 = {
3053 .number = 3,
3054 .nrprocs = ARRAY_SIZE(nfs3_procedures),
3055 .procs = nfs3_procedures
3058 #ifdef CONFIG_NFS_V3_ACL
3059 static struct rpc_procinfo nfs3_acl_procedures[] = {
3060 [ACLPROC3_GETACL] = {
3061 .p_proc = ACLPROC3_GETACL,
3062 .p_encode = (kxdrproc_t)nfs3_xdr_enc_getacl3args,
3063 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
3064 .p_arglen = ACL3_getaclargs_sz,
3065 .p_replen = ACL3_getaclres_sz,
3066 .p_timer = 1,
3067 .p_name = "GETACL",
3069 [ACLPROC3_SETACL] = {
3070 .p_proc = ACLPROC3_SETACL,
3071 .p_encode = (kxdrproc_t)nfs3_xdr_enc_setacl3args,
3072 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
3073 .p_arglen = ACL3_setaclargs_sz,
3074 .p_replen = ACL3_setaclres_sz,
3075 .p_timer = 0,
3076 .p_name = "SETACL",
3080 struct rpc_version nfsacl_version3 = {
3081 .number = 3,
3082 .nrprocs = sizeof(nfs3_acl_procedures)/
3083 sizeof(nfs3_acl_procedures[0]),
3084 .procs = nfs3_acl_procedures,
3086 #endif /* CONFIG_NFS_V3_ACL */