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