]> git.kernelconcepts.de Git - mv-sheeva.git/blob - fs/nfs/nfs3xdr.c
b0af263e4db9c2aff0f8162d0ada368ce2fcc0c6
[mv-sheeva.git] / fs / nfs / nfs3xdr.c
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_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)
50
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)
68
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)
85
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)
92
93 /*
94  * Map file type to S_IFMT bits
95  */
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,
105 };
106
107 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
108 {
109         dprintk("nfs: %s: prematurely hit end of receive buffer. "
110                 "Remaining buffer length is %tu words.\n",
111                 func, xdr->end - xdr->p);
112 }
113
114 /*
115  * While encoding arguments, set up the reply buffer in advance to
116  * receive reply data directly into the page cache.
117  */
118 static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
119                                  unsigned int base, unsigned int len,
120                                  unsigned int bufsize)
121 {
122         struct rpc_auth *auth = req->rq_cred->cr_auth;
123         unsigned int replen;
124
125         replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
126         xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
127 }
128
129
130 /*
131  * Common NFS XDR functions as inlines
132  */
133 static inline __be32 *
134 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
135 {
136         if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
137                 memcpy(fh->data, p, fh->size);
138                 return p + XDR_QUADLEN(fh->size);
139         }
140         return NULL;
141 }
142
143 static inline __be32 *
144 xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
145 {
146         __be32 *p;
147         p = xdr_inline_decode(xdr, 4);
148         if (unlikely(!p))
149                 goto out_overflow;
150         fh->size = ntohl(*p++);
151
152         if (fh->size <= NFS3_FHSIZE) {
153                 p = xdr_inline_decode(xdr, fh->size);
154                 if (unlikely(!p))
155                         goto out_overflow;
156                 memcpy(fh->data, p, fh->size);
157                 return p + XDR_QUADLEN(fh->size);
158         }
159         return NULL;
160
161 out_overflow:
162         print_overflow_msg(__func__, xdr);
163         return ERR_PTR(-EIO);
164 }
165
166 /*
167  * Encode/decode time.
168  */
169 static inline __be32 *
170 xdr_encode_time3(__be32 *p, const struct timespec *timep)
171 {
172         *p++ = htonl(timep->tv_sec);
173         *p++ = htonl(timep->tv_nsec);
174         return p;
175 }
176
177 static inline __be32 *
178 xdr_decode_time3(__be32 *p, struct timespec *timep)
179 {
180         timep->tv_sec = ntohl(*p++);
181         timep->tv_nsec = ntohl(*p++);
182         return p;
183 }
184
185 static __be32 *
186 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
187 {
188         unsigned int    type, major, minor;
189         umode_t         fmode;
190
191         type = ntohl(*p++);
192         if (type > NF3FIFO)
193                 type = NF3NON;
194         fmode = nfs_type2fmt[type];
195         fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
196         fattr->nlink = ntohl(*p++);
197         fattr->uid = ntohl(*p++);
198         fattr->gid = ntohl(*p++);
199         p = xdr_decode_hyper(p, &fattr->size);
200         p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
201
202         /* Turn remote device info into Linux-specific dev_t */
203         major = ntohl(*p++);
204         minor = ntohl(*p++);
205         fattr->rdev = MKDEV(major, minor);
206         if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
207                 fattr->rdev = 0;
208
209         p = xdr_decode_hyper(p, &fattr->fsid.major);
210         fattr->fsid.minor = 0;
211         p = xdr_decode_hyper(p, &fattr->fileid);
212         p = xdr_decode_time3(p, &fattr->atime);
213         p = xdr_decode_time3(p, &fattr->mtime);
214         p = xdr_decode_time3(p, &fattr->ctime);
215
216         /* Update the mode bits */
217         fattr->valid |= NFS_ATTR_FATTR_V3;
218         return p;
219 }
220
221 static inline __be32 *
222 xdr_encode_sattr(__be32 *p, const struct iattr *attr)
223 {
224         if (attr->ia_valid & ATTR_MODE) {
225                 *p++ = xdr_one;
226                 *p++ = htonl(attr->ia_mode & S_IALLUGO);
227         } else {
228                 *p++ = xdr_zero;
229         }
230         if (attr->ia_valid & ATTR_UID) {
231                 *p++ = xdr_one;
232                 *p++ = htonl(attr->ia_uid);
233         } else {
234                 *p++ = xdr_zero;
235         }
236         if (attr->ia_valid & ATTR_GID) {
237                 *p++ = xdr_one;
238                 *p++ = htonl(attr->ia_gid);
239         } else {
240                 *p++ = xdr_zero;
241         }
242         if (attr->ia_valid & ATTR_SIZE) {
243                 *p++ = xdr_one;
244                 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
245         } else {
246                 *p++ = xdr_zero;
247         }
248         if (attr->ia_valid & ATTR_ATIME_SET) {
249                 *p++ = xdr_two;
250                 p = xdr_encode_time3(p, &attr->ia_atime);
251         } else if (attr->ia_valid & ATTR_ATIME) {
252                 *p++ = xdr_one;
253         } else {
254                 *p++ = xdr_zero;
255         }
256         if (attr->ia_valid & ATTR_MTIME_SET) {
257                 *p++ = xdr_two;
258                 p = xdr_encode_time3(p, &attr->ia_mtime);
259         } else if (attr->ia_valid & ATTR_MTIME) {
260                 *p++ = xdr_one;
261         } else {
262                 *p++ = xdr_zero;
263         }
264         return p;
265 }
266
267 static inline __be32 *
268 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
269 {
270         p = xdr_decode_hyper(p, &fattr->pre_size);
271         p = xdr_decode_time3(p, &fattr->pre_mtime);
272         p = xdr_decode_time3(p, &fattr->pre_ctime);
273         fattr->valid |= NFS_ATTR_FATTR_PRESIZE
274                 | NFS_ATTR_FATTR_PREMTIME
275                 | NFS_ATTR_FATTR_PRECTIME;
276         return p;
277 }
278
279 static inline __be32 *
280 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
281 {
282         if (*p++)
283                 p = xdr_decode_fattr(p, fattr);
284         return p;
285 }
286
287 static inline __be32 *
288 xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
289 {
290         __be32 *p;
291
292         p = xdr_inline_decode(xdr, 4);
293         if (unlikely(!p))
294                 goto out_overflow;
295         if (ntohl(*p++)) {
296                 p = xdr_inline_decode(xdr, 84);
297                 if (unlikely(!p))
298                         goto out_overflow;
299                 p = xdr_decode_fattr(p, fattr);
300         }
301         return p;
302 out_overflow:
303         print_overflow_msg(__func__, xdr);
304         return ERR_PTR(-EIO);
305 }
306
307 static inline __be32 *
308 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
309 {
310         if (*p++)
311                 return xdr_decode_wcc_attr(p, fattr);
312         return p;
313 }
314
315
316 static inline __be32 *
317 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
318 {
319         p = xdr_decode_pre_op_attr(p, fattr);
320         return xdr_decode_post_op_attr(p, fattr);
321 }
322
323
324 /*
325  * Encode/decode NFSv3 basic data types
326  *
327  * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
328  * "NFS Version 3 Protocol Specification".
329  *
330  * Not all basic data types have their own encoding and decoding
331  * functions.  For run-time efficiency, some data types are encoded
332  * or decoded inline.
333  */
334
335 static void encode_uint32(struct xdr_stream *xdr, u32 value)
336 {
337         __be32 *p = xdr_reserve_space(xdr, 4);
338         *p = cpu_to_be32(value);
339 }
340
341 /*
342  * filename3
343  *
344  *      typedef string filename3<>;
345  */
346 static void encode_filename3(struct xdr_stream *xdr,
347                              const char *name, u32 length)
348 {
349         __be32 *p;
350
351         BUG_ON(length > NFS3_MAXNAMLEN);
352         p = xdr_reserve_space(xdr, 4 + length);
353         xdr_encode_opaque(p, name, length);
354 }
355
356 /*
357  * nfspath3
358  *
359  *      typedef string nfspath3<>;
360  */
361 static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
362                             const u32 length)
363 {
364         BUG_ON(length > NFS3_MAXPATHLEN);
365         encode_uint32(xdr, length);
366         xdr_write_pages(xdr, pages, 0, length);
367 }
368
369 /*
370  * cookie3
371  *
372  *      typedef uint64 cookie3
373  */
374 static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
375 {
376         return xdr_encode_hyper(p, cookie);
377 }
378
379 /*
380  * cookieverf3
381  *
382  *      typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
383  */
384 static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
385 {
386         memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
387         return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
388 }
389
390 /*
391  * createverf3
392  *
393  *      typedef opaque createverf3[NFS3_CREATEVERFSIZE];
394  */
395 static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
396 {
397         __be32 *p;
398
399         p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
400         memcpy(p, verifier, NFS3_CREATEVERFSIZE);
401 }
402
403 /*
404  * ftype3
405  *
406  *      enum ftype3 {
407  *              NF3REG  = 1,
408  *              NF3DIR  = 2,
409  *              NF3BLK  = 3,
410  *              NF3CHR  = 4,
411  *              NF3LNK  = 5,
412  *              NF3SOCK = 6,
413  *              NF3FIFO = 7
414  *      };
415  */
416 static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
417 {
418         BUG_ON(type > NF3FIFO);
419         encode_uint32(xdr, type);
420 }
421
422 /*
423  * specdata3
424  *
425  *     struct specdata3 {
426  *             uint32  specdata1;
427  *             uint32  specdata2;
428  *     };
429  */
430 static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
431 {
432         __be32 *p;
433
434         p = xdr_reserve_space(xdr, 8);
435         *p++ = cpu_to_be32(MAJOR(rdev));
436         *p = cpu_to_be32(MINOR(rdev));
437 }
438
439 /*
440  * nfs_fh3
441  *
442  *      struct nfs_fh3 {
443  *              opaque       data<NFS3_FHSIZE>;
444  *      };
445  */
446 static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
447 {
448         __be32 *p;
449
450         BUG_ON(fh->size > NFS3_FHSIZE);
451         p = xdr_reserve_space(xdr, 4 + fh->size);
452         xdr_encode_opaque(p, fh->data, fh->size);
453 }
454
455 /*
456  * sattr3
457  *
458  *      enum time_how {
459  *              DONT_CHANGE             = 0,
460  *              SET_TO_SERVER_TIME      = 1,
461  *              SET_TO_CLIENT_TIME      = 2
462  *      };
463  *
464  *      union set_mode3 switch (bool set_it) {
465  *      case TRUE:
466  *              mode3   mode;
467  *      default:
468  *              void;
469  *      };
470  *
471  *      union set_uid3 switch (bool set_it) {
472  *      case TRUE:
473  *              uid3    uid;
474  *      default:
475  *              void;
476  *      };
477  *
478  *      union set_gid3 switch (bool set_it) {
479  *      case TRUE:
480  *              gid3    gid;
481  *      default:
482  *              void;
483  *      };
484  *
485  *      union set_size3 switch (bool set_it) {
486  *      case TRUE:
487  *              size3   size;
488  *      default:
489  *              void;
490  *      };
491  *
492  *      union set_atime switch (time_how set_it) {
493  *      case SET_TO_CLIENT_TIME:
494  *              nfstime3        atime;
495  *      default:
496  *              void;
497  *      };
498  *
499  *      union set_mtime switch (time_how set_it) {
500  *      case SET_TO_CLIENT_TIME:
501  *              nfstime3  mtime;
502  *      default:
503  *              void;
504  *      };
505  *
506  *      struct sattr3 {
507  *              set_mode3       mode;
508  *              set_uid3        uid;
509  *              set_gid3        gid;
510  *              set_size3       size;
511  *              set_atime       atime;
512  *              set_mtime       mtime;
513  *      };
514  */
515 static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
516 {
517         u32 nbytes;
518         __be32 *p;
519
520         /*
521          * In order to make only a single xdr_reserve_space() call,
522          * pre-compute the total number of bytes to be reserved.
523          * Six boolean values, one for each set_foo field, are always
524          * present in the encoded result, so start there.
525          */
526         nbytes = 6 * 4;
527         if (attr->ia_valid & ATTR_MODE)
528                 nbytes += 4;
529         if (attr->ia_valid & ATTR_UID)
530                 nbytes += 4;
531         if (attr->ia_valid & ATTR_GID)
532                 nbytes += 4;
533         if (attr->ia_valid & ATTR_SIZE)
534                 nbytes += 8;
535         if (attr->ia_valid & ATTR_ATIME_SET)
536                 nbytes += 8;
537         if (attr->ia_valid & ATTR_MTIME_SET)
538                 nbytes += 8;
539         p = xdr_reserve_space(xdr, nbytes);
540
541         xdr_encode_sattr(p, attr);
542 }
543
544 /*
545  * diropargs3
546  *
547  *      struct diropargs3 {
548  *              nfs_fh3         dir;
549  *              filename3       name;
550  *      };
551  */
552 static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
553                               const char *name, u32 length)
554 {
555         encode_nfs_fh3(xdr, fh);
556         encode_filename3(xdr, name, length);
557 }
558
559
560 /*
561  * NFSv3 XDR encode functions
562  *
563  * NFSv3 argument types are defined in section 3.3 of RFC 1813:
564  * "NFS Version 3 Protocol Specification".
565  */
566
567 /*
568  * 3.3.1  GETATTR3args
569  *
570  *      struct GETATTR3args {
571  *              nfs_fh3  object;
572  *      };
573  */
574 static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
575                                      const struct nfs_fh *fh)
576 {
577         struct xdr_stream xdr;
578
579         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
580         encode_nfs_fh3(&xdr, fh);
581         return 0;
582 }
583
584 /*
585  * 3.3.2  SETATTR3args
586  *
587  *      union sattrguard3 switch (bool check) {
588  *      case TRUE:
589  *              nfstime3  obj_ctime;
590  *      case FALSE:
591  *              void;
592  *      };
593  *
594  *      struct SETATTR3args {
595  *              nfs_fh3         object;
596  *              sattr3          new_attributes;
597  *              sattrguard3     guard;
598  *      };
599  */
600 static void encode_sattrguard3(struct xdr_stream *xdr,
601                                const struct nfs3_sattrargs *args)
602 {
603         __be32 *p;
604
605         if (args->guard) {
606                 p = xdr_reserve_space(xdr, 4 + 8);
607                 *p++ = xdr_one;
608                 xdr_encode_time3(p, &args->guardtime);
609         } else {
610                 p = xdr_reserve_space(xdr, 4);
611                 *p = xdr_zero;
612         }
613 }
614
615 static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
616                                      const struct nfs3_sattrargs *args)
617 {
618         struct xdr_stream xdr;
619
620         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
621         encode_nfs_fh3(&xdr, args->fh);
622         encode_sattr3(&xdr, args->sattr);
623         encode_sattrguard3(&xdr, args);
624         return 0;
625 }
626
627 /*
628  * 3.3.3  LOOKUP3args
629  *
630  *      struct LOOKUP3args {
631  *              diropargs3  what;
632  *      };
633  */
634 static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
635                                     const struct nfs3_diropargs *args)
636 {
637         struct xdr_stream xdr;
638
639         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
640         encode_diropargs3(&xdr, args->fh, args->name, args->len);
641         return 0;
642 }
643
644 /*
645  * 3.3.4  ACCESS3args
646  *
647  *      struct ACCESS3args {
648  *              nfs_fh3         object;
649  *              uint32          access;
650  *      };
651  */
652 static void encode_access3args(struct xdr_stream *xdr,
653                                const struct nfs3_accessargs *args)
654 {
655         encode_nfs_fh3(xdr, args->fh);
656         encode_uint32(xdr, args->access);
657 }
658
659 static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
660                                     const struct nfs3_accessargs *args)
661 {
662         struct xdr_stream xdr;
663
664         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
665         encode_access3args(&xdr, args);
666         return 0;
667 }
668
669 /*
670  * 3.3.5  READLINK3args
671  *
672  *      struct READLINK3args {
673  *              nfs_fh3 symlink;
674  *      };
675  */
676 static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
677                                       const struct nfs3_readlinkargs *args)
678 {
679         struct xdr_stream xdr;
680
681         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
682         encode_nfs_fh3(&xdr, args->fh);
683         prepare_reply_buffer(req, args->pages, args->pgbase,
684                                         args->pglen, NFS3_readlinkres_sz);
685         return 0;
686 }
687
688 /*
689  * 3.3.6  READ3args
690  *
691  *      struct READ3args {
692  *              nfs_fh3         file;
693  *              offset3         offset;
694  *              count3          count;
695  *      };
696  */
697 static void encode_read3args(struct xdr_stream *xdr,
698                              const struct nfs_readargs *args)
699 {
700         __be32 *p;
701
702         encode_nfs_fh3(xdr, args->fh);
703
704         p = xdr_reserve_space(xdr, 8 + 4);
705         p = xdr_encode_hyper(p, args->offset);
706         *p = cpu_to_be32(args->count);
707 }
708
709 static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
710                                   const struct nfs_readargs *args)
711 {
712         struct xdr_stream xdr;
713
714         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
715         encode_read3args(&xdr, args);
716         prepare_reply_buffer(req, args->pages, args->pgbase,
717                                         args->count, NFS3_readres_sz);
718         req->rq_rcv_buf.flags |= XDRBUF_READ;
719         return 0;
720 }
721
722 /*
723  * 3.3.7  WRITE3args
724  *
725  *      enum stable_how {
726  *              UNSTABLE  = 0,
727  *              DATA_SYNC = 1,
728  *              FILE_SYNC = 2
729  *      };
730  *
731  *      struct WRITE3args {
732  *              nfs_fh3         file;
733  *              offset3         offset;
734  *              count3          count;
735  *              stable_how      stable;
736  *              opaque          data<>;
737  *      };
738  */
739 static void encode_write3args(struct xdr_stream *xdr,
740                               const struct nfs_writeargs *args)
741 {
742         __be32 *p;
743
744         encode_nfs_fh3(xdr, args->fh);
745
746         p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
747         p = xdr_encode_hyper(p, args->offset);
748         *p++ = cpu_to_be32(args->count);
749
750         BUG_ON(args->stable > NFS_FILE_SYNC);
751         *p++ = cpu_to_be32(args->stable);
752
753         *p = cpu_to_be32(args->count);
754         xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
755 }
756
757 static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
758                                    const struct nfs_writeargs *args)
759 {
760         struct xdr_stream xdr;
761
762         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
763         encode_write3args(&xdr, args);
764         xdr.buf->flags |= XDRBUF_WRITE;
765         return 0;
766 }
767
768 /*
769  * 3.3.8  CREATE3args
770  *
771  *      enum createmode3 {
772  *              UNCHECKED = 0,
773  *              GUARDED   = 1,
774  *              EXCLUSIVE = 2
775  *      };
776  *
777  *      union createhow3 switch (createmode3 mode) {
778  *      case UNCHECKED:
779  *      case GUARDED:
780  *              sattr3       obj_attributes;
781  *      case EXCLUSIVE:
782  *              createverf3  verf;
783  *      };
784  *
785  *      struct CREATE3args {
786  *              diropargs3      where;
787  *              createhow3      how;
788  *      };
789  */
790 static void encode_createhow3(struct xdr_stream *xdr,
791                               const struct nfs3_createargs *args)
792 {
793         encode_uint32(xdr, args->createmode);
794         switch (args->createmode) {
795         case NFS3_CREATE_UNCHECKED:
796         case NFS3_CREATE_GUARDED:
797                 encode_sattr3(xdr, args->sattr);
798                 break;
799         case NFS3_CREATE_EXCLUSIVE:
800                 encode_createverf3(xdr, args->verifier);
801                 break;
802         default:
803                 BUG();
804         }
805 }
806
807 static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
808                                     const struct nfs3_createargs *args)
809 {
810         struct xdr_stream xdr;
811
812         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
813         encode_diropargs3(&xdr, args->fh, args->name, args->len);
814         encode_createhow3(&xdr, args);
815         return 0;
816 }
817
818 /*
819  * 3.3.9  MKDIR3args
820  *
821  *      struct MKDIR3args {
822  *              diropargs3      where;
823  *              sattr3          attributes;
824  *      };
825  */
826 static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
827                                    const struct nfs3_mkdirargs *args)
828 {
829         struct xdr_stream xdr;
830
831         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
832         encode_diropargs3(&xdr, args->fh, args->name, args->len);
833         encode_sattr3(&xdr, args->sattr);
834         return 0;
835 }
836
837 /*
838  * 3.3.10  SYMLINK3args
839  *
840  *      struct symlinkdata3 {
841  *              sattr3          symlink_attributes;
842  *              nfspath3        symlink_data;
843  *      };
844  *
845  *      struct SYMLINK3args {
846  *              diropargs3      where;
847  *              symlinkdata3    symlink;
848  *      };
849  */
850 static void encode_symlinkdata3(struct xdr_stream *xdr,
851                                 const struct nfs3_symlinkargs *args)
852 {
853         encode_sattr3(xdr, args->sattr);
854         encode_nfspath3(xdr, args->pages, args->pathlen);
855 }
856
857 static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
858                                      const struct nfs3_symlinkargs *args)
859 {
860         struct xdr_stream xdr;
861
862         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
863         encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
864         encode_symlinkdata3(&xdr, args);
865         return 0;
866 }
867
868 /*
869  * 3.3.11  MKNOD3args
870  *
871  *      struct devicedata3 {
872  *              sattr3          dev_attributes;
873  *              specdata3       spec;
874  *      };
875  *
876  *      union mknoddata3 switch (ftype3 type) {
877  *      case NF3CHR:
878  *      case NF3BLK:
879  *              devicedata3     device;
880  *      case NF3SOCK:
881  *      case NF3FIFO:
882  *              sattr3          pipe_attributes;
883  *      default:
884  *              void;
885  *      };
886  *
887  *      struct MKNOD3args {
888  *              diropargs3      where;
889  *              mknoddata3      what;
890  *      };
891  */
892 static void encode_devicedata3(struct xdr_stream *xdr,
893                                const struct nfs3_mknodargs *args)
894 {
895         encode_sattr3(xdr, args->sattr);
896         encode_specdata3(xdr, args->rdev);
897 }
898
899 static void encode_mknoddata3(struct xdr_stream *xdr,
900                               const struct nfs3_mknodargs *args)
901 {
902         encode_ftype3(xdr, args->type);
903         switch (args->type) {
904         case NF3CHR:
905         case NF3BLK:
906                 encode_devicedata3(xdr, args);
907                 break;
908         case NF3SOCK:
909         case NF3FIFO:
910                 encode_sattr3(xdr, args->sattr);
911                 break;
912         case NF3REG:
913         case NF3DIR:
914                 break;
915         default:
916                 BUG();
917         }
918 }
919
920 static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
921                                    const struct nfs3_mknodargs *args)
922 {
923         struct xdr_stream xdr;
924
925         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
926         encode_diropargs3(&xdr, args->fh, args->name, args->len);
927         encode_mknoddata3(&xdr, args);
928         return 0;
929 }
930
931 /*
932  * 3.3.12  REMOVE3args
933  *
934  *      struct REMOVE3args {
935  *              diropargs3  object;
936  *      };
937  */
938 static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
939                                     const struct nfs_removeargs *args)
940 {
941         struct xdr_stream xdr;
942
943         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
944         encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
945         return 0;
946 }
947
948 /*
949  * 3.3.14  RENAME3args
950  *
951  *      struct RENAME3args {
952  *              diropargs3      from;
953  *              diropargs3      to;
954  *      };
955  */
956 static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
957                                     const struct nfs_renameargs *args)
958 {
959         const struct qstr *old = args->old_name;
960         const struct qstr *new = args->new_name;
961         struct xdr_stream xdr;
962
963         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
964         encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
965         encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
966         return 0;
967 }
968
969 /*
970  * 3.3.15  LINK3args
971  *
972  *      struct LINK3args {
973  *              nfs_fh3         file;
974  *              diropargs3      link;
975  *      };
976  */
977 static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
978                                   const struct nfs3_linkargs *args)
979 {
980         struct xdr_stream xdr;
981
982         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
983         encode_nfs_fh3(&xdr, args->fromfh);
984         encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
985         return 0;
986 }
987
988 /*
989  * 3.3.16  READDIR3args
990  *
991  *      struct READDIR3args {
992  *              nfs_fh3         dir;
993  *              cookie3         cookie;
994  *              cookieverf3     cookieverf;
995  *              count3          count;
996  *      };
997  */
998 static void encode_readdir3args(struct xdr_stream *xdr,
999                                 const struct nfs3_readdirargs *args)
1000 {
1001         __be32 *p;
1002
1003         encode_nfs_fh3(xdr, args->fh);
1004
1005         p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1006         p = xdr_encode_cookie3(p, args->cookie);
1007         p = xdr_encode_cookieverf3(p, args->verf);
1008         *p = cpu_to_be32(args->count);
1009 }
1010
1011 static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1012                                      const struct nfs3_readdirargs *args)
1013 {
1014         struct xdr_stream xdr;
1015
1016         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1017         encode_readdir3args(&xdr, args);
1018         prepare_reply_buffer(req, args->pages, 0,
1019                                 args->count, NFS3_readdirres_sz);
1020         return 0;
1021 }
1022
1023 /*
1024  * 3.3.17  READDIRPLUS3args
1025  *
1026  *      struct READDIRPLUS3args {
1027  *              nfs_fh3         dir;
1028  *              cookie3         cookie;
1029  *              cookieverf3     cookieverf;
1030  *              count3          dircount;
1031  *              count3          maxcount;
1032  *      };
1033  */
1034 static void encode_readdirplus3args(struct xdr_stream *xdr,
1035                                     const struct nfs3_readdirargs *args)
1036 {
1037         __be32 *p;
1038
1039         encode_nfs_fh3(xdr, args->fh);
1040
1041         p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1042         p = xdr_encode_cookie3(p, args->cookie);
1043         p = xdr_encode_cookieverf3(p, args->verf);
1044
1045         /*
1046          * readdirplus: need dircount + buffer size.
1047          * We just make sure we make dircount big enough
1048          */
1049         *p++ = cpu_to_be32(args->count >> 3);
1050
1051         *p = cpu_to_be32(args->count);
1052 }
1053
1054 static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1055                                          const struct nfs3_readdirargs *args)
1056 {
1057         struct xdr_stream xdr;
1058
1059         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1060         encode_readdirplus3args(&xdr, args);
1061         prepare_reply_buffer(req, args->pages, 0,
1062                                 args->count, NFS3_readdirres_sz);
1063         return 0;
1064 }
1065
1066 /*
1067  * Decode the result of a readdir call.
1068  * We just check for syntactical correctness.
1069  */
1070 static int
1071 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1072 {
1073         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1074         struct kvec *iov = rcvbuf->head;
1075         struct page **page;
1076         size_t hdrlen;
1077         u32 recvd, pglen;
1078         int status;
1079
1080         status = ntohl(*p++);
1081         /* Decode post_op_attrs */
1082         p = xdr_decode_post_op_attr(p, res->dir_attr);
1083         if (status)
1084                 return nfs_stat_to_errno(status);
1085         /* Decode verifier cookie */
1086         if (res->verf) {
1087                 res->verf[0] = *p++;
1088                 res->verf[1] = *p++;
1089         } else {
1090                 p += 2;
1091         }
1092
1093         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1094         if (iov->iov_len < hdrlen) {
1095                 dprintk("NFS: READDIR reply header overflowed:"
1096                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1097                 return -errno_NFSERR_IO;
1098         } else if (iov->iov_len != hdrlen) {
1099                 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
1100                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1101         }
1102
1103         pglen = rcvbuf->page_len;
1104         recvd = rcvbuf->len - hdrlen;
1105         if (pglen > recvd)
1106                 pglen = recvd;
1107         page = rcvbuf->pages;
1108
1109         return pglen;
1110 }
1111
1112 __be32 *
1113 nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
1114 {
1115         __be32 *p;
1116         struct nfs_entry old = *entry;
1117
1118         p = xdr_inline_decode(xdr, 4);
1119         if (unlikely(!p))
1120                 goto out_overflow;
1121         if (!ntohl(*p++)) {
1122                 p = xdr_inline_decode(xdr, 4);
1123                 if (unlikely(!p))
1124                         goto out_overflow;
1125                 if (!ntohl(*p++))
1126                         return ERR_PTR(-EAGAIN);
1127                 entry->eof = 1;
1128                 return ERR_PTR(-EBADCOOKIE);
1129         }
1130
1131         p = xdr_inline_decode(xdr, 12);
1132         if (unlikely(!p))
1133                 goto out_overflow;
1134         p = xdr_decode_hyper(p, &entry->ino);
1135         entry->len  = ntohl(*p++);
1136
1137         p = xdr_inline_decode(xdr, entry->len + 8);
1138         if (unlikely(!p))
1139                 goto out_overflow;
1140         entry->name = (const char *) p;
1141         p += XDR_QUADLEN(entry->len);
1142         entry->prev_cookie = entry->cookie;
1143         p = xdr_decode_hyper(p, &entry->cookie);
1144
1145         entry->d_type = DT_UNKNOWN;
1146         if (plus) {
1147                 entry->fattr->valid = 0;
1148                 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
1149                 if (IS_ERR(p))
1150                         goto out_overflow_exit;
1151                 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1152                 /* In fact, a post_op_fh3: */
1153                 p = xdr_inline_decode(xdr, 4);
1154                 if (unlikely(!p))
1155                         goto out_overflow;
1156                 if (*p++) {
1157                         p = xdr_decode_fhandle_stream(xdr, entry->fh);
1158                         if (IS_ERR(p))
1159                                 goto out_overflow_exit;
1160                         /* Ugh -- server reply was truncated */
1161                         if (p == NULL) {
1162                                 dprintk("NFS: FH truncated\n");
1163                                 *entry = old;
1164                                 return ERR_PTR(-EAGAIN);
1165                         }
1166                 } else
1167                         memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
1168         }
1169
1170         p = xdr_inline_peek(xdr, 8);
1171         if (p != NULL)
1172                 entry->eof = !p[0] && p[1];
1173         else
1174                 entry->eof = 0;
1175
1176         return p;
1177
1178 out_overflow:
1179         print_overflow_msg(__func__, xdr);
1180 out_overflow_exit:
1181         return ERR_PTR(-EAGAIN);
1182 }
1183
1184 /*
1185  * 3.3.21  COMMIT3args
1186  *
1187  *      struct COMMIT3args {
1188  *              nfs_fh3         file;
1189  *              offset3         offset;
1190  *              count3          count;
1191  *      };
1192  */
1193 static void encode_commit3args(struct xdr_stream *xdr,
1194                                const struct nfs_writeargs *args)
1195 {
1196         __be32 *p;
1197
1198         encode_nfs_fh3(xdr, args->fh);
1199
1200         p = xdr_reserve_space(xdr, 8 + 4);
1201         p = xdr_encode_hyper(p, args->offset);
1202         *p = cpu_to_be32(args->count);
1203 }
1204
1205 static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1206                                     const struct nfs_writeargs *args)
1207 {
1208         struct xdr_stream xdr;
1209
1210         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1211         encode_commit3args(&xdr, args);
1212         return 0;
1213 }
1214
1215 #ifdef CONFIG_NFS_V3_ACL
1216
1217 static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1218                                     const struct nfs3_getaclargs *args)
1219 {
1220         struct xdr_stream xdr;
1221
1222         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1223         encode_nfs_fh3(&xdr, args->fh);
1224         encode_uint32(&xdr, args->mask);
1225         if (args->mask & (NFS_ACL | NFS_DFACL))
1226                 prepare_reply_buffer(req, args->pages, 0,
1227                                         NFSACL_MAXPAGES << PAGE_SHIFT,
1228                                         ACL3_getaclres_sz);
1229         return 0;
1230 }
1231
1232 static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1233                                     const struct nfs3_setaclargs *args)
1234 {
1235         struct xdr_stream xdr;
1236         unsigned int base;
1237         int error;
1238
1239         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1240         encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1241         encode_uint32(&xdr, args->mask);
1242         if (args->npages != 0)
1243                 xdr_write_pages(&xdr, args->pages, 0, args->len);
1244
1245         base = req->rq_slen;
1246         error = nfsacl_encode(xdr.buf, base, args->inode,
1247                             (args->mask & NFS_ACL) ?
1248                             args->acl_access : NULL, 1, 0);
1249         BUG_ON(error < 0);
1250         error = nfsacl_encode(xdr.buf, base + error, args->inode,
1251                             (args->mask & NFS_DFACL) ?
1252                             args->acl_default : NULL, 1,
1253                             NFS_ACL_DEFAULT);
1254         BUG_ON(error < 0);
1255         return 0;
1256 }
1257
1258 #endif  /* CONFIG_NFS_V3_ACL */
1259
1260 /*
1261  * NFS XDR decode functions
1262  */
1263
1264 /*
1265  * Decode attrstat reply.
1266  */
1267 static int
1268 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1269 {
1270         int     status;
1271
1272         if ((status = ntohl(*p++)))
1273                 return nfs_stat_to_errno(status);
1274         xdr_decode_fattr(p, fattr);
1275         return 0;
1276 }
1277
1278 /*
1279  * Decode status+wcc_data reply
1280  * SATTR, REMOVE, RMDIR
1281  */
1282 static int
1283 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1284 {
1285         int     status;
1286
1287         if ((status = ntohl(*p++)))
1288                 status = nfs_stat_to_errno(status);
1289         xdr_decode_wcc_data(p, fattr);
1290         return status;
1291 }
1292
1293 static int
1294 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1295 {
1296         return nfs3_xdr_wccstat(req, p, res->dir_attr);
1297 }
1298
1299 /*
1300  * Decode LOOKUP reply
1301  */
1302 static int
1303 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1304 {
1305         int     status;
1306
1307         if ((status = ntohl(*p++))) {
1308                 status = nfs_stat_to_errno(status);
1309         } else {
1310                 if (!(p = xdr_decode_fhandle(p, res->fh)))
1311                         return -errno_NFSERR_IO;
1312                 p = xdr_decode_post_op_attr(p, res->fattr);
1313         }
1314         xdr_decode_post_op_attr(p, res->dir_attr);
1315         return status;
1316 }
1317
1318 /*
1319  * Decode ACCESS reply
1320  */
1321 static int
1322 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1323 {
1324         int     status = ntohl(*p++);
1325
1326         p = xdr_decode_post_op_attr(p, res->fattr);
1327         if (status)
1328                 return nfs_stat_to_errno(status);
1329         res->access = ntohl(*p++);
1330         return 0;
1331 }
1332
1333 /*
1334  * Decode READLINK reply
1335  */
1336 static int
1337 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1338 {
1339         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1340         struct kvec *iov = rcvbuf->head;
1341         size_t hdrlen;
1342         u32 len, recvd;
1343         int     status;
1344
1345         status = ntohl(*p++);
1346         p = xdr_decode_post_op_attr(p, fattr);
1347
1348         if (status != 0)
1349                 return nfs_stat_to_errno(status);
1350
1351         /* Convert length of symlink */
1352         len = ntohl(*p++);
1353         if (len >= rcvbuf->page_len) {
1354                 dprintk("nfs: server returned giant symlink!\n");
1355                 return -ENAMETOOLONG;
1356         }
1357
1358         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1359         if (iov->iov_len < hdrlen) {
1360                 dprintk("NFS: READLINK reply header overflowed:"
1361                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1362                 return -errno_NFSERR_IO;
1363         } else if (iov->iov_len != hdrlen) {
1364                 dprintk("NFS: READLINK header is short. "
1365                         "iovec will be shifted.\n");
1366                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1367         }
1368         recvd = req->rq_rcv_buf.len - hdrlen;
1369         if (recvd < len) {
1370                 dprintk("NFS: server cheating in readlink reply: "
1371                                 "count %u > recvd %u\n", len, recvd);
1372                 return -EIO;
1373         }
1374
1375         xdr_terminate_string(rcvbuf, len);
1376         return 0;
1377 }
1378
1379 /*
1380  * Decode READ reply
1381  */
1382 static int
1383 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1384 {
1385         struct kvec *iov = req->rq_rcv_buf.head;
1386         size_t hdrlen;
1387         u32 count, ocount, recvd;
1388         int status;
1389
1390         status = ntohl(*p++);
1391         p = xdr_decode_post_op_attr(p, res->fattr);
1392
1393         if (status != 0)
1394                 return nfs_stat_to_errno(status);
1395
1396         /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1397          * in that it puts the count both in the res struct and in the
1398          * opaque data count. */
1399         count    = ntohl(*p++);
1400         res->eof = ntohl(*p++);
1401         ocount   = ntohl(*p++);
1402
1403         if (ocount != count) {
1404                 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1405                 return -errno_NFSERR_IO;
1406         }
1407
1408         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1409         if (iov->iov_len < hdrlen) {
1410                 dprintk("NFS: READ reply header overflowed:"
1411                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1412                 return -errno_NFSERR_IO;
1413         } else if (iov->iov_len != hdrlen) {
1414                 dprintk("NFS: READ header is short. iovec will be shifted.\n");
1415                 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
1416         }
1417
1418         recvd = req->rq_rcv_buf.len - hdrlen;
1419         if (count > recvd) {
1420                 dprintk("NFS: server cheating in read reply: "
1421                         "count %u > recvd %u\n", count, recvd);
1422                 count = recvd;
1423                 res->eof = 0;
1424         }
1425
1426         if (count < res->count)
1427                 res->count = count;
1428
1429         return count;
1430 }
1431
1432 /*
1433  * Decode WRITE response
1434  */
1435 static int
1436 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1437 {
1438         int     status;
1439
1440         status = ntohl(*p++);
1441         p = xdr_decode_wcc_data(p, res->fattr);
1442
1443         if (status != 0)
1444                 return nfs_stat_to_errno(status);
1445
1446         res->count = ntohl(*p++);
1447         res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
1448         res->verf->verifier[0] = *p++;
1449         res->verf->verifier[1] = *p++;
1450
1451         return res->count;
1452 }
1453
1454 /*
1455  * Decode a CREATE response
1456  */
1457 static int
1458 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1459 {
1460         int     status;
1461
1462         status = ntohl(*p++);
1463         if (status == 0) {
1464                 if (*p++) {
1465                         if (!(p = xdr_decode_fhandle(p, res->fh)))
1466                                 return -errno_NFSERR_IO;
1467                         p = xdr_decode_post_op_attr(p, res->fattr);
1468                 } else {
1469                         memset(res->fh, 0, sizeof(*res->fh));
1470                         /* Do decode post_op_attr but set it to NULL */
1471                         p = xdr_decode_post_op_attr(p, res->fattr);
1472                         res->fattr->valid = 0;
1473                 }
1474         } else {
1475                 status = nfs_stat_to_errno(status);
1476         }
1477         p = xdr_decode_wcc_data(p, res->dir_attr);
1478         return status;
1479 }
1480
1481 /*
1482  * Decode RENAME reply
1483  */
1484 static int
1485 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
1486 {
1487         int     status;
1488
1489         if ((status = ntohl(*p++)) != 0)
1490                 status = nfs_stat_to_errno(status);
1491         p = xdr_decode_wcc_data(p, res->old_fattr);
1492         p = xdr_decode_wcc_data(p, res->new_fattr);
1493         return status;
1494 }
1495
1496 /*
1497  * Decode LINK reply
1498  */
1499 static int
1500 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1501 {
1502         int     status;
1503
1504         if ((status = ntohl(*p++)) != 0)
1505                 status = nfs_stat_to_errno(status);
1506         p = xdr_decode_post_op_attr(p, res->fattr);
1507         p = xdr_decode_wcc_data(p, res->dir_attr);
1508         return status;
1509 }
1510
1511 /*
1512  * Decode FSSTAT reply
1513  */
1514 static int
1515 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1516 {
1517         int             status;
1518
1519         status = ntohl(*p++);
1520
1521         p = xdr_decode_post_op_attr(p, res->fattr);
1522         if (status != 0)
1523                 return nfs_stat_to_errno(status);
1524
1525         p = xdr_decode_hyper(p, &res->tbytes);
1526         p = xdr_decode_hyper(p, &res->fbytes);
1527         p = xdr_decode_hyper(p, &res->abytes);
1528         p = xdr_decode_hyper(p, &res->tfiles);
1529         p = xdr_decode_hyper(p, &res->ffiles);
1530         p = xdr_decode_hyper(p, &res->afiles);
1531
1532         /* ignore invarsec */
1533         return 0;
1534 }
1535
1536 /*
1537  * Decode FSINFO reply
1538  */
1539 static int
1540 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1541 {
1542         int             status;
1543
1544         status = ntohl(*p++);
1545
1546         p = xdr_decode_post_op_attr(p, res->fattr);
1547         if (status != 0)
1548                 return nfs_stat_to_errno(status);
1549
1550         res->rtmax  = ntohl(*p++);
1551         res->rtpref = ntohl(*p++);
1552         res->rtmult = ntohl(*p++);
1553         res->wtmax  = ntohl(*p++);
1554         res->wtpref = ntohl(*p++);
1555         res->wtmult = ntohl(*p++);
1556         res->dtpref = ntohl(*p++);
1557         p = xdr_decode_hyper(p, &res->maxfilesize);
1558         p = xdr_decode_time3(p, &res->time_delta);
1559
1560         /* ignore properties */
1561         res->lease_time = 0;
1562         return 0;
1563 }
1564
1565 /*
1566  * Decode PATHCONF reply
1567  */
1568 static int
1569 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1570 {
1571         int             status;
1572
1573         status = ntohl(*p++);
1574
1575         p = xdr_decode_post_op_attr(p, res->fattr);
1576         if (status != 0)
1577                 return nfs_stat_to_errno(status);
1578         res->max_link = ntohl(*p++);
1579         res->max_namelen = ntohl(*p++);
1580
1581         /* ignore remaining fields */
1582         return 0;
1583 }
1584
1585 /*
1586  * Decode COMMIT reply
1587  */
1588 static int
1589 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1590 {
1591         int             status;
1592
1593         status = ntohl(*p++);
1594         p = xdr_decode_wcc_data(p, res->fattr);
1595         if (status != 0)
1596                 return nfs_stat_to_errno(status);
1597
1598         res->verf->verifier[0] = *p++;
1599         res->verf->verifier[1] = *p++;
1600         return 0;
1601 }
1602
1603 #ifdef CONFIG_NFS_V3_ACL
1604 /*
1605  * Decode GETACL reply
1606  */
1607 static int
1608 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1609                    struct nfs3_getaclres *res)
1610 {
1611         struct xdr_buf *buf = &req->rq_rcv_buf;
1612         int status = ntohl(*p++);
1613         struct posix_acl **acl;
1614         unsigned int *aclcnt;
1615         int err, base;
1616
1617         if (status != 0)
1618                 return nfs_stat_to_errno(status);
1619         p = xdr_decode_post_op_attr(p, res->fattr);
1620         res->mask = ntohl(*p++);
1621         if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1622                 return -EINVAL;
1623         base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1624
1625         acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1626         aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1627         err = nfsacl_decode(buf, base, aclcnt, acl);
1628
1629         acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1630         aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1631         if (err > 0)
1632                 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1633         return (err > 0) ? 0 : err;
1634 }
1635
1636 /*
1637  * Decode setacl reply.
1638  */
1639 static int
1640 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1641 {
1642         int status = ntohl(*p++);
1643
1644         if (status)
1645                 return nfs_stat_to_errno(status);
1646         xdr_decode_post_op_attr(p, fattr);
1647         return 0;
1648 }
1649 #endif  /* CONFIG_NFS_V3_ACL */
1650
1651 #define PROC(proc, argtype, restype, timer)                             \
1652 [NFS3PROC_##proc] = {                                                   \
1653         .p_proc      = NFS3PROC_##proc,                                 \
1654         .p_encode    = (kxdrproc_t)nfs3_xdr_enc_##argtype##3args,       \
1655         .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                 \
1656         .p_arglen    = NFS3_##argtype##args_sz,                         \
1657         .p_replen    = NFS3_##restype##_sz,                             \
1658         .p_timer     = timer,                                           \
1659         .p_statidx   = NFS3PROC_##proc,                                 \
1660         .p_name      = #proc,                                           \
1661         }
1662
1663 struct rpc_procinfo     nfs3_procedures[] = {
1664         PROC(GETATTR,           getattr,        attrstat,       1),
1665         PROC(SETATTR,           setattr,        wccstat,        0),
1666         PROC(LOOKUP,            lookup,         lookupres,      2),
1667         PROC(ACCESS,            access,         accessres,      1),
1668         PROC(READLINK,          readlink,       readlinkres,    3),
1669         PROC(READ,              read,           readres,        3),
1670         PROC(WRITE,             write,          writeres,       4),
1671         PROC(CREATE,            create,         createres,      0),
1672         PROC(MKDIR,             mkdir,          createres,      0),
1673         PROC(SYMLINK,           symlink,        createres,      0),
1674         PROC(MKNOD,             mknod,          createres,      0),
1675         PROC(REMOVE,            remove,         removeres,      0),
1676         PROC(RMDIR,             lookup,         wccstat,        0),
1677         PROC(RENAME,            rename,         renameres,      0),
1678         PROC(LINK,              link,           linkres,        0),
1679         PROC(READDIR,           readdir,        readdirres,     3),
1680         PROC(READDIRPLUS,       readdirplus,    readdirres,     3),
1681         PROC(FSSTAT,            getattr,        fsstatres,      0),
1682         PROC(FSINFO,            getattr,        fsinfores,      0),
1683         PROC(PATHCONF,          getattr,        pathconfres,    0),
1684         PROC(COMMIT,            commit,         commitres,      5),
1685 };
1686
1687 struct rpc_version              nfs_version3 = {
1688         .number                 = 3,
1689         .nrprocs                = ARRAY_SIZE(nfs3_procedures),
1690         .procs                  = nfs3_procedures
1691 };
1692
1693 #ifdef CONFIG_NFS_V3_ACL
1694 static struct rpc_procinfo      nfs3_acl_procedures[] = {
1695         [ACLPROC3_GETACL] = {
1696                 .p_proc = ACLPROC3_GETACL,
1697                 .p_encode = (kxdrproc_t)nfs3_xdr_enc_getacl3args,
1698                 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1699                 .p_arglen = ACL3_getaclargs_sz,
1700                 .p_replen = ACL3_getaclres_sz,
1701                 .p_timer = 1,
1702                 .p_name = "GETACL",
1703         },
1704         [ACLPROC3_SETACL] = {
1705                 .p_proc = ACLPROC3_SETACL,
1706                 .p_encode = (kxdrproc_t)nfs3_xdr_enc_setacl3args,
1707                 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1708                 .p_arglen = ACL3_setaclargs_sz,
1709                 .p_replen = ACL3_setaclres_sz,
1710                 .p_timer = 0,
1711                 .p_name = "SETACL",
1712         },
1713 };
1714
1715 struct rpc_version              nfsacl_version3 = {
1716         .number                 = 3,
1717         .nrprocs                = sizeof(nfs3_acl_procedures)/
1718                                   sizeof(nfs3_acl_procedures[0]),
1719         .procs                  = nfs3_acl_procedures,
1720 };
1721 #endif  /* CONFIG_NFS_V3_ACL */