NFS: Introduce new-style XDR decoding functions for NFSv2
[pandora-kernel.git] / fs / nfs / nfs2xdr.c
1 /*
2  * linux/fs/nfs/nfs2xdr.c
3  *
4  * XDR functions to encode/decode NFS RPC arguments and results.
5  *
6  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
7  * Copyright (C) 1996 Olaf Kirch
8  * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
9  *              FIFO's need special handling in NFSv2
10  */
11
12 #include <linux/param.h>
13 #include <linux/time.h>
14 #include <linux/mm.h>
15 #include <linux/errno.h>
16 #include <linux/string.h>
17 #include <linux/in.h>
18 #include <linux/pagemap.h>
19 #include <linux/proc_fs.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs2.h>
23 #include <linux/nfs_fs.h>
24 #include "internal.h"
25
26 #define NFSDBG_FACILITY         NFSDBG_XDR
27
28 /* Mapping from NFS error code to "errno" error code. */
29 #define errno_NFSERR_IO         EIO
30
31 /*
32  * Declare the space requirements for NFS arguments and replies as
33  * number of 32bit-words
34  */
35 #define NFS_fhandle_sz          (8)
36 #define NFS_sattr_sz            (8)
37 #define NFS_filename_sz         (1+(NFS2_MAXNAMLEN>>2))
38 #define NFS_path_sz             (1+(NFS2_MAXPATHLEN>>2))
39 #define NFS_fattr_sz            (17)
40 #define NFS_info_sz             (5)
41 #define NFS_entry_sz            (NFS_filename_sz+3)
42
43 #define NFS_diropargs_sz        (NFS_fhandle_sz+NFS_filename_sz)
44 #define NFS_removeargs_sz       (NFS_fhandle_sz+NFS_filename_sz)
45 #define NFS_sattrargs_sz        (NFS_fhandle_sz+NFS_sattr_sz)
46 #define NFS_readlinkargs_sz     (NFS_fhandle_sz)
47 #define NFS_readargs_sz         (NFS_fhandle_sz+3)
48 #define NFS_writeargs_sz        (NFS_fhandle_sz+4)
49 #define NFS_createargs_sz       (NFS_diropargs_sz+NFS_sattr_sz)
50 #define NFS_renameargs_sz       (NFS_diropargs_sz+NFS_diropargs_sz)
51 #define NFS_linkargs_sz         (NFS_fhandle_sz+NFS_diropargs_sz)
52 #define NFS_symlinkargs_sz      (NFS_diropargs_sz+1+NFS_sattr_sz)
53 #define NFS_readdirargs_sz      (NFS_fhandle_sz+2)
54
55 #define NFS_attrstat_sz         (1+NFS_fattr_sz)
56 #define NFS_diropres_sz         (1+NFS_fhandle_sz+NFS_fattr_sz)
57 #define NFS_readlinkres_sz      (2)
58 #define NFS_readres_sz          (1+NFS_fattr_sz+1)
59 #define NFS_writeres_sz         (NFS_attrstat_sz)
60 #define NFS_stat_sz             (1)
61 #define NFS_readdirres_sz       (1)
62 #define NFS_statfsres_sz        (1+NFS_info_sz)
63
64
65 /*
66  * While encoding arguments, set up the reply buffer in advance to
67  * receive reply data directly into the page cache.
68  */
69 static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
70                                  unsigned int base, unsigned int len,
71                                  unsigned int bufsize)
72 {
73         struct rpc_auth *auth = req->rq_cred->cr_auth;
74         unsigned int replen;
75
76         replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
77         xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
78 }
79
80 /*
81  * Handle decode buffer overflows out-of-line.
82  */
83 static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
84 {
85         dprintk("NFS: %s prematurely hit the end of our receive buffer. "
86                 "Remaining buffer length is %tu words.\n",
87                 func, xdr->end - xdr->p);
88 }
89
90
91 /*
92  * Common NFS XDR functions as inlines
93  */
94 static inline __be32 *
95 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
96 {
97         /* NFSv2 handles have a fixed length */
98         fhandle->size = NFS2_FHSIZE;
99         memcpy(fhandle->data, p, NFS2_FHSIZE);
100         return p + XDR_QUADLEN(NFS2_FHSIZE);
101 }
102
103 static inline __be32*
104 xdr_decode_time(__be32 *p, struct timespec *timep)
105 {
106         timep->tv_sec = ntohl(*p++);
107         /* Convert microseconds into nanoseconds */
108         timep->tv_nsec = ntohl(*p++) * 1000;
109         return p;
110 }
111
112 static __be32 *
113 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
114 {
115         u32 rdev, type;
116         type = ntohl(*p++);
117         fattr->mode = ntohl(*p++);
118         fattr->nlink = ntohl(*p++);
119         fattr->uid = ntohl(*p++);
120         fattr->gid = ntohl(*p++);
121         fattr->size = ntohl(*p++);
122         fattr->du.nfs2.blocksize = ntohl(*p++);
123         rdev = ntohl(*p++);
124         fattr->du.nfs2.blocks = ntohl(*p++);
125         fattr->fsid.major = ntohl(*p++);
126         fattr->fsid.minor = 0;
127         fattr->fileid = ntohl(*p++);
128         p = xdr_decode_time(p, &fattr->atime);
129         p = xdr_decode_time(p, &fattr->mtime);
130         p = xdr_decode_time(p, &fattr->ctime);
131         fattr->valid |= NFS_ATTR_FATTR_V2;
132         fattr->rdev = new_decode_dev(rdev);
133         if (type == NFCHR && rdev == NFS2_FIFO_DEV) {
134                 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
135                 fattr->rdev = 0;
136         }
137         return p;
138 }
139
140 /*
141  * Encode/decode NFSv2 basic data types
142  *
143  * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
144  * "NFS: Network File System Protocol Specification".
145  *
146  * Not all basic data types have their own encoding and decoding
147  * functions.  For run-time efficiency, some data types are encoded
148  * or decoded inline.
149  */
150
151 /*
152  *      typedef opaque  nfsdata<>;
153  */
154 static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
155 {
156         u32 recvd, count;
157         size_t hdrlen;
158         __be32 *p;
159
160         p = xdr_inline_decode(xdr, 4);
161         if (unlikely(p == NULL))
162                 goto out_overflow;
163         count = be32_to_cpup(p);
164         hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
165         recvd = xdr->buf->len - hdrlen;
166         if (unlikely(count > recvd))
167                 goto out_cheating;
168 out:
169         xdr_read_pages(xdr, count);
170         result->eof = 0;        /* NFSv2 does not pass EOF flag on the wire. */
171         result->count = count;
172         return count;
173 out_cheating:
174         dprintk("NFS: server cheating in read result: "
175                 "count %u > recvd %u\n", count, recvd);
176         count = recvd;
177         goto out;
178 out_overflow:
179         print_overflow_msg(__func__, xdr);
180         return -EIO;
181 }
182
183 /*
184  *      enum stat {
185  *              NFS_OK = 0,
186  *              NFSERR_PERM = 1,
187  *              NFSERR_NOENT = 2,
188  *              NFSERR_IO = 5,
189  *              NFSERR_NXIO = 6,
190  *              NFSERR_ACCES = 13,
191  *              NFSERR_EXIST = 17,
192  *              NFSERR_NODEV = 19,
193  *              NFSERR_NOTDIR = 20,
194  *              NFSERR_ISDIR = 21,
195  *              NFSERR_FBIG = 27,
196  *              NFSERR_NOSPC = 28,
197  *              NFSERR_ROFS = 30,
198  *              NFSERR_NAMETOOLONG = 63,
199  *              NFSERR_NOTEMPTY = 66,
200  *              NFSERR_DQUOT = 69,
201  *              NFSERR_STALE = 70,
202  *              NFSERR_WFLUSH = 99
203  *      };
204  */
205 static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
206 {
207         __be32 *p;
208
209         p = xdr_inline_decode(xdr, 4);
210         if (unlikely(p == NULL))
211                 goto out_overflow;
212         *status = be32_to_cpup(p);
213         return 0;
214 out_overflow:
215         print_overflow_msg(__func__, xdr);
216         return -EIO;
217 }
218
219 /*
220  * 2.3.3.  fhandle
221  *
222  *      typedef opaque fhandle[FHSIZE];
223  */
224 static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
225 {
226         __be32 *p;
227
228         BUG_ON(fh->size != NFS2_FHSIZE);
229         p = xdr_reserve_space(xdr, NFS2_FHSIZE);
230         memcpy(p, fh->data, NFS2_FHSIZE);
231 }
232
233 static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
234 {
235         __be32 *p;
236
237         p = xdr_inline_decode(xdr, NFS2_FHSIZE);
238         if (unlikely(p == NULL))
239                 goto out_overflow;
240         fh->size = NFS2_FHSIZE;
241         memcpy(fh->data, p, NFS2_FHSIZE);
242         return 0;
243 out_overflow:
244         print_overflow_msg(__func__, xdr);
245         return -EIO;
246 }
247
248 /*
249  * 2.3.4.  timeval
250  *
251  *      struct timeval {
252  *              unsigned int seconds;
253  *              unsigned int useconds;
254  *      };
255  */
256 static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep)
257 {
258         *p++ = cpu_to_be32(timep->tv_sec);
259         if (timep->tv_nsec != 0)
260                 *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
261         else
262                 *p++ = cpu_to_be32(0);
263         return p;
264 }
265
266 /*
267  * Passing the invalid value useconds=1000000 is a Sun convention for
268  * "set to current server time".  It's needed to make permissions checks
269  * for the "touch" program across v2 mounts to Solaris and Irix servers
270  * work correctly.  See description of sattr in section 6.1 of "NFS
271  * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
272  */
273 static __be32 *xdr_encode_current_server_time(__be32 *p,
274                                               const struct timespec *timep)
275 {
276         *p++ = cpu_to_be32(timep->tv_sec);
277         *p++ = cpu_to_be32(1000000);
278         return p;
279 }
280
281 /*
282  * 2.3.5.  fattr
283  *
284  *      struct fattr {
285  *              ftype           type;
286  *              unsigned int    mode;
287  *              unsigned int    nlink;
288  *              unsigned int    uid;
289  *              unsigned int    gid;
290  *              unsigned int    size;
291  *              unsigned int    blocksize;
292  *              unsigned int    rdev;
293  *              unsigned int    blocks;
294  *              unsigned int    fsid;
295  *              unsigned int    fileid;
296  *              timeval         atime;
297  *              timeval         mtime;
298  *              timeval         ctime;
299  *      };
300  *
301  */
302 static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
303 {
304         __be32 *p;
305
306         p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
307         if (unlikely(p == NULL))
308                 goto out_overflow;
309         xdr_decode_fattr(p, fattr);
310         return 0;
311 out_overflow:
312         print_overflow_msg(__func__, xdr);
313         return -EIO;
314 }
315
316 /*
317  * 2.3.6.  sattr
318  *
319  *      struct sattr {
320  *              unsigned int    mode;
321  *              unsigned int    uid;
322  *              unsigned int    gid;
323  *              unsigned int    size;
324  *              timeval         atime;
325  *              timeval         mtime;
326  *      };
327  */
328
329 #define NFS2_SATTR_NOT_SET      (0xffffffff)
330
331 static __be32 *xdr_time_not_set(__be32 *p)
332 {
333         *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
334         *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
335         return p;
336 }
337
338 static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
339 {
340         __be32 *p;
341
342         p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
343
344         if (attr->ia_valid & ATTR_MODE)
345                 *p++ = cpu_to_be32(attr->ia_mode);
346         else
347                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
348         if (attr->ia_valid & ATTR_UID)
349                 *p++ = cpu_to_be32(attr->ia_uid);
350         else
351                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
352         if (attr->ia_valid & ATTR_GID)
353                 *p++ = cpu_to_be32(attr->ia_gid);
354         else
355                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
356         if (attr->ia_valid & ATTR_SIZE)
357                 *p++ = cpu_to_be32((u32)attr->ia_size);
358         else
359                 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
360
361         if (attr->ia_valid & ATTR_ATIME_SET)
362                 p = xdr_encode_time(p, &attr->ia_atime);
363         else if (attr->ia_valid & ATTR_ATIME)
364                 p = xdr_encode_current_server_time(p, &attr->ia_atime);
365         else
366                 p = xdr_time_not_set(p);
367         if (attr->ia_valid & ATTR_MTIME_SET)
368                 xdr_encode_time(p, &attr->ia_mtime);
369         else if (attr->ia_valid & ATTR_MTIME)
370                 xdr_encode_current_server_time(p, &attr->ia_mtime);
371         else
372                 xdr_time_not_set(p);
373 }
374
375 /*
376  * 2.3.7.  filename
377  *
378  *      typedef string filename<MAXNAMLEN>;
379  */
380 static void encode_filename(struct xdr_stream *xdr,
381                             const char *name, u32 length)
382 {
383         __be32 *p;
384
385         BUG_ON(length > NFS2_MAXNAMLEN);
386         p = xdr_reserve_space(xdr, 4 + length);
387         xdr_encode_opaque(p, name, length);
388 }
389
390 static int decode_filename_inline(struct xdr_stream *xdr,
391                                   const char **name, u32 *length)
392 {
393         __be32 *p;
394         u32 count;
395
396         p = xdr_inline_decode(xdr, 4);
397         if (unlikely(p == NULL))
398                 goto out_overflow;
399         count = be32_to_cpup(p);
400         if (count > NFS3_MAXNAMLEN)
401                 goto out_nametoolong;
402         p = xdr_inline_decode(xdr, count);
403         if (unlikely(p == NULL))
404                 goto out_overflow;
405         *name = (const char *)p;
406         *length = count;
407         return 0;
408 out_nametoolong:
409         dprintk("NFS: returned filename too long: %u\n", count);
410         return -ENAMETOOLONG;
411 out_overflow:
412         print_overflow_msg(__func__, xdr);
413         return -EIO;
414 }
415
416 /*
417  * 2.3.8.  path
418  *
419  *      typedef string path<MAXPATHLEN>;
420  */
421 static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
422 {
423         __be32 *p;
424
425         BUG_ON(length > NFS2_MAXPATHLEN);
426         p = xdr_reserve_space(xdr, 4);
427         *p = cpu_to_be32(length);
428         xdr_write_pages(xdr, pages, 0, length);
429 }
430
431 static int decode_path(struct xdr_stream *xdr)
432 {
433         u32 length, recvd;
434         size_t hdrlen;
435         __be32 *p;
436
437         p = xdr_inline_decode(xdr, 4);
438         if (unlikely(p == NULL))
439                 goto out_overflow;
440         length = be32_to_cpup(p);
441         if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
442                 goto out_size;
443         hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
444         recvd = xdr->buf->len - hdrlen;
445         if (unlikely(length > recvd))
446                 goto out_cheating;
447
448         xdr_read_pages(xdr, length);
449         xdr_terminate_string(xdr->buf, length);
450         return 0;
451 out_size:
452         dprintk("NFS: returned pathname too long: %u\n", length);
453         return -ENAMETOOLONG;
454 out_cheating:
455         dprintk("NFS: server cheating in pathname result: "
456                 "length %u > received %u\n", length, recvd);
457         return -EIO;
458 out_overflow:
459         print_overflow_msg(__func__, xdr);
460         return -EIO;
461 }
462
463 /*
464  * 2.3.9.  attrstat
465  *
466  *      union attrstat switch (stat status) {
467  *      case NFS_OK:
468  *              fattr attributes;
469  *      default:
470  *              void;
471  *      };
472  */
473 static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result)
474 {
475         enum nfs_stat status;
476         int error;
477
478         error = decode_stat(xdr, &status);
479         if (unlikely(error))
480                 goto out;
481         if (status != NFS_OK)
482                 goto out_default;
483         error = decode_fattr(xdr, result);
484 out:
485         return error;
486 out_default:
487         return nfs_stat_to_errno(status);
488 }
489
490 /*
491  * 2.3.10.  diropargs
492  *
493  *      struct diropargs {
494  *              fhandle  dir;
495  *              filename name;
496  *      };
497  */
498 static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
499                              const char *name, u32 length)
500 {
501         encode_fhandle(xdr, fh);
502         encode_filename(xdr, name, length);
503 }
504
505 /*
506  * 2.3.11.  diropres
507  *
508  *      union diropres switch (stat status) {
509  *      case NFS_OK:
510  *              struct {
511  *                      fhandle file;
512  *                      fattr   attributes;
513  *              } diropok;
514  *      default:
515  *              void;
516  *      };
517  */
518 static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
519 {
520         int error;
521
522         error = decode_fhandle(xdr, result->fh);
523         if (unlikely(error))
524                 goto out;
525         error = decode_fattr(xdr, result->fattr);
526 out:
527         return error;
528 }
529
530 static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
531 {
532         enum nfs_stat status;
533         int error;
534
535         error = decode_stat(xdr, &status);
536         if (unlikely(error))
537                 goto out;
538         if (status != NFS_OK)
539                 goto out_default;
540         error = decode_diropok(xdr, result);
541 out:
542         return error;
543 out_default:
544         return nfs_stat_to_errno(status);
545 }
546
547
548 /*
549  * NFSv2 XDR encode functions
550  *
551  * NFSv2 argument types are defined in section 2.2 of RFC 1094:
552  * "NFS: Network File System Protocol Specification".
553  */
554
555 static int nfs2_xdr_enc_fhandle(struct rpc_rqst *req, __be32 *p,
556                                 const struct nfs_fh *fh)
557 {
558         struct xdr_stream xdr;
559
560         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
561         encode_fhandle(&xdr, fh);
562         return 0;
563 }
564
565 /*
566  * 2.2.3.  sattrargs
567  *
568  *      struct sattrargs {
569  *              fhandle file;
570  *              sattr attributes;
571  *      };
572  */
573 static int nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, __be32 *p,
574                                   const struct nfs_sattrargs *args)
575 {
576         struct xdr_stream xdr;
577
578         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
579         encode_fhandle(&xdr, args->fh);
580         encode_sattr(&xdr, args->sattr);
581         return 0;
582 }
583
584 static int nfs2_xdr_enc_diropargs(struct rpc_rqst *req, __be32 *p,
585                                   const struct nfs_diropargs *args)
586 {
587         struct xdr_stream xdr;
588
589         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
590         encode_diropargs(&xdr, args->fh, args->name, args->len);
591         return 0;
592 }
593
594 static int nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, __be32 *p,
595                                      const struct nfs_readlinkargs *args)
596 {
597         struct xdr_stream xdr;
598
599         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
600         encode_fhandle(&xdr, args->fh);
601         prepare_reply_buffer(req, args->pages, args->pgbase,
602                                         args->pglen, NFS_readlinkres_sz);
603         return 0;
604 }
605
606 /*
607  * 2.2.7.  readargs
608  *
609  *      struct readargs {
610  *              fhandle file;
611  *              unsigned offset;
612  *              unsigned count;
613  *              unsigned totalcount;
614  *      };
615  */
616 static void encode_readargs(struct xdr_stream *xdr,
617                             const struct nfs_readargs *args)
618 {
619         u32 offset = args->offset;
620         u32 count = args->count;
621         __be32 *p;
622
623         encode_fhandle(xdr, args->fh);
624
625         p = xdr_reserve_space(xdr, 4 + 4 + 4);
626         *p++ = cpu_to_be32(offset);
627         *p++ = cpu_to_be32(count);
628         *p = cpu_to_be32(count);
629 }
630
631 static int nfs2_xdr_enc_readargs(struct rpc_rqst *req, __be32 *p,
632                                  const struct nfs_readargs *args)
633 {
634         struct xdr_stream xdr;
635
636         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
637         encode_readargs(&xdr, args);
638         prepare_reply_buffer(req, args->pages, args->pgbase,
639                                         args->count, NFS_readres_sz);
640         req->rq_rcv_buf.flags |= XDRBUF_READ;
641         return 0;
642 }
643
644 /*
645  * Decode READ reply
646  */
647 static int
648 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
649 {
650         struct kvec *iov = req->rq_rcv_buf.head;
651         size_t hdrlen;
652         u32 count, recvd;
653         int status;
654
655         if ((status = ntohl(*p++)))
656                 return nfs_stat_to_errno(status);
657         p = xdr_decode_fattr(p, res->fattr);
658
659         count = ntohl(*p++);
660         res->eof = 0;
661         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
662         if (iov->iov_len < hdrlen) {
663                 dprintk("NFS: READ reply header overflowed:"
664                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
665                 return -errno_NFSERR_IO;
666         } else if (iov->iov_len != hdrlen) {
667                 dprintk("NFS: READ header is short. iovec will be shifted.\n");
668                 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
669         }
670
671         recvd = req->rq_rcv_buf.len - hdrlen;
672         if (count > recvd) {
673                 dprintk("NFS: server cheating in read reply: "
674                         "count %u > recvd %u\n", count, recvd);
675                 count = recvd;
676         }
677
678         dprintk("RPC:      readres OK count %u\n", count);
679         if (count < res->count)
680                 res->count = count;
681
682         return count;
683 }
684
685
686 /*
687  * 2.2.9.  writeargs
688  *
689  *      struct writeargs {
690  *              fhandle file;
691  *              unsigned beginoffset;
692  *              unsigned offset;
693  *              unsigned totalcount;
694  *              nfsdata data;
695  *      };
696  */
697 static void encode_writeargs(struct xdr_stream *xdr,
698                              const struct nfs_writeargs *args)
699 {
700         u32 offset = args->offset;
701         u32 count = args->count;
702         __be32 *p;
703
704         encode_fhandle(xdr, args->fh);
705
706         p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
707         *p++ = cpu_to_be32(offset);
708         *p++ = cpu_to_be32(offset);
709         *p++ = cpu_to_be32(count);
710
711         /* nfsdata */
712         *p = cpu_to_be32(count);
713         xdr_write_pages(xdr, args->pages, args->pgbase, count);
714 }
715
716 static int nfs2_xdr_enc_writeargs(struct rpc_rqst *req, __be32 *p,
717                                   const struct nfs_writeargs *args)
718 {
719         struct xdr_stream xdr;
720
721         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
722         encode_writeargs(&xdr, args);
723         xdr.buf->flags |= XDRBUF_WRITE;
724         return 0;
725 }
726
727 /*
728  * 2.2.10.  createargs
729  *
730  *      struct createargs {
731  *              diropargs where;
732  *              sattr attributes;
733  *      };
734  */
735 static int nfs2_xdr_enc_createargs(struct rpc_rqst *req, __be32 *p,
736                                    const struct nfs_createargs *args)
737 {
738         struct xdr_stream xdr;
739
740         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
741         encode_diropargs(&xdr, args->fh, args->name, args->len);
742         encode_sattr(&xdr, args->sattr);
743         return 0;
744 }
745
746 static int nfs2_xdr_enc_removeargs(struct rpc_rqst *req, __be32 *p,
747                                    const struct nfs_removeargs *args)
748 {
749         struct xdr_stream xdr;
750
751         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
752         encode_diropargs(&xdr, args->fh, args->name.name, args->name.len);
753         return 0;
754 }
755
756 /*
757  * 2.2.12.  renameargs
758  *
759  *      struct renameargs {
760  *              diropargs from;
761  *              diropargs to;
762  *      };
763  */
764 static int nfs2_xdr_enc_renameargs(struct rpc_rqst *req, __be32 *p,
765                                    const struct nfs_renameargs *args)
766 {
767         const struct qstr *old = args->old_name;
768         const struct qstr *new = args->new_name;
769         struct xdr_stream xdr;
770
771         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
772         encode_diropargs(&xdr, args->old_dir, old->name, old->len);
773         encode_diropargs(&xdr, args->new_dir, new->name, new->len);
774         return 0;
775 }
776
777 /*
778  * 2.2.13.  linkargs
779  *
780  *      struct linkargs {
781  *              fhandle from;
782  *              diropargs to;
783  *      };
784  */
785 static int nfs2_xdr_enc_linkargs(struct rpc_rqst *req, __be32 *p,
786                                  const struct nfs_linkargs *args)
787 {
788         struct xdr_stream xdr;
789
790         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
791         encode_fhandle(&xdr, args->fromfh);
792         encode_diropargs(&xdr, args->tofh, args->toname, args->tolen);
793         return 0;
794 }
795
796 /*
797  * 2.2.14.  symlinkargs
798  *
799  *      struct symlinkargs {
800  *              diropargs from;
801  *              path to;
802  *              sattr attributes;
803  *      };
804  */
805 static int nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, __be32 *p,
806                                     const struct nfs_symlinkargs *args)
807 {
808         struct xdr_stream xdr;
809
810         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
811         encode_diropargs(&xdr, args->fromfh, args->fromname, args->fromlen);
812         encode_path(&xdr, args->pages, args->pathlen);
813         encode_sattr(&xdr, args->sattr);
814         return 0;
815 }
816
817 /*
818  * 2.2.17.  readdirargs
819  *
820  *      struct readdirargs {
821  *              fhandle dir;
822  *              nfscookie cookie;
823  *              unsigned count;
824  *      };
825  */
826 static void encode_readdirargs(struct xdr_stream *xdr,
827                                const struct nfs_readdirargs *args)
828 {
829         __be32 *p;
830
831         encode_fhandle(xdr, args->fh);
832
833         p = xdr_reserve_space(xdr, 4 + 4);
834         *p++ = cpu_to_be32(args->cookie);
835         *p = cpu_to_be32(args->count);
836 }
837
838 static int nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, __be32 *p,
839                                     const struct nfs_readdirargs *args)
840 {
841         struct xdr_stream xdr;
842
843         xdr_init_encode(&xdr, &req->rq_snd_buf, p);
844         encode_readdirargs(&xdr, args);
845         prepare_reply_buffer(req, args->pages, 0,
846                                         args->count, NFS_readdirres_sz);
847         return 0;
848 }
849
850 /*
851  * Decode the result of a readdir call.
852  * We're not really decoding anymore, we just leave the buffer untouched
853  * and only check that it is syntactically correct.
854  * The real decoding happens in nfs_decode_entry below, called directly
855  * from nfs_readdir for each entry.
856  */
857 static int
858 nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
859 {
860         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
861         struct kvec *iov = rcvbuf->head;
862         struct page **page;
863         size_t hdrlen;
864         unsigned int pglen, recvd;
865         int status;
866
867         if ((status = ntohl(*p++)))
868                 return nfs_stat_to_errno(status);
869
870         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
871         if (iov->iov_len < hdrlen) {
872                 dprintk("NFS: READDIR reply header overflowed:"
873                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
874                 return -errno_NFSERR_IO;
875         } else if (iov->iov_len != hdrlen) {
876                 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
877                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
878         }
879
880         pglen = rcvbuf->page_len;
881         recvd = rcvbuf->len - hdrlen;
882         if (pglen > recvd)
883                 pglen = recvd;
884         page = rcvbuf->pages;
885         return pglen;
886 }
887
888 __be32 *
889 nfs_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
890 {
891         __be32 *p;
892         p = xdr_inline_decode(xdr, 4);
893         if (unlikely(!p))
894                 goto out_overflow;
895         if (!ntohl(*p++)) {
896                 p = xdr_inline_decode(xdr, 4);
897                 if (unlikely(!p))
898                         goto out_overflow;
899                 if (!ntohl(*p++))
900                         return ERR_PTR(-EAGAIN);
901                 entry->eof = 1;
902                 return ERR_PTR(-EBADCOOKIE);
903         }
904
905         p = xdr_inline_decode(xdr, 8);
906         if (unlikely(!p))
907                 goto out_overflow;
908
909         entry->ino        = ntohl(*p++);
910         entry->len        = ntohl(*p++);
911
912         p = xdr_inline_decode(xdr, entry->len + 4);
913         if (unlikely(!p))
914                 goto out_overflow;
915         entry->name       = (const char *) p;
916         p                += XDR_QUADLEN(entry->len);
917         entry->prev_cookie        = entry->cookie;
918         entry->cookie     = ntohl(*p++);
919
920         entry->d_type = DT_UNKNOWN;
921
922         p = xdr_inline_peek(xdr, 8);
923         if (p != NULL)
924                 entry->eof = !p[0] && p[1];
925         else
926                 entry->eof = 0;
927
928         return p;
929
930 out_overflow:
931         print_overflow_msg(__func__, xdr);
932         return ERR_PTR(-EAGAIN);
933 }
934
935 /*
936  * NFS XDR decode functions
937  */
938 /*
939  * Decode simple status reply
940  */
941 static int
942 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
943 {
944         int     status;
945
946         if ((status = ntohl(*p++)) != 0)
947                 status = nfs_stat_to_errno(status);
948         return status;
949 }
950
951 static int nfs2_xdr_dec_stat(struct rpc_rqst *req, __be32 *p,
952                              void *__unused)
953 {
954         struct xdr_stream xdr;
955         enum nfs_stat status;
956         int error;
957
958         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
959         error = decode_stat(&xdr, &status);
960         if (unlikely(error))
961                 goto out;
962         if (status != NFS_OK)
963                 goto out_default;
964 out:
965         return error;
966 out_default:
967         return nfs_stat_to_errno(status);
968 }
969
970 /*
971  * Decode attrstat reply
972  * GETATTR, SETATTR, WRITE
973  */
974 static int
975 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
976 {
977         int     status;
978
979         if ((status = ntohl(*p++)))
980                 return nfs_stat_to_errno(status);
981         xdr_decode_fattr(p, fattr);
982         return 0;
983 }
984
985 static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, __be32 *p,
986                                  struct nfs_fattr *result)
987 {
988         struct xdr_stream xdr;
989
990         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
991         return decode_attrstat(&xdr, result);
992 }
993
994 /*
995  * Decode diropres reply
996  * LOOKUP, CREATE, MKDIR
997  */
998 static int
999 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
1000 {
1001         int     status;
1002
1003         if ((status = ntohl(*p++)))
1004                 return nfs_stat_to_errno(status);
1005         p = xdr_decode_fhandle(p, res->fh);
1006         xdr_decode_fattr(p, res->fattr);
1007         return 0;
1008 }
1009
1010 static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, __be32 *p,
1011                                  struct nfs_diropok *result)
1012 {
1013         struct xdr_stream xdr;
1014
1015         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1016         return decode_diropres(&xdr, result);
1017 }
1018
1019 /*
1020  * Decode READLINK reply
1021  */
1022 static int
1023 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
1024 {
1025         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1026         struct kvec *iov = rcvbuf->head;
1027         size_t hdrlen;
1028         u32 len, recvd;
1029         int     status;
1030
1031         if ((status = ntohl(*p++)))
1032                 return nfs_stat_to_errno(status);
1033         /* Convert length of symlink */
1034         len = ntohl(*p++);
1035         if (len >= rcvbuf->page_len) {
1036                 dprintk("nfs: server returned giant symlink!\n");
1037                 return -ENAMETOOLONG;
1038         }
1039         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1040         if (iov->iov_len < hdrlen) {
1041                 dprintk("NFS: READLINK reply header overflowed:"
1042                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1043                 return -errno_NFSERR_IO;
1044         } else if (iov->iov_len != hdrlen) {
1045                 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
1046                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1047         }
1048         recvd = req->rq_rcv_buf.len - hdrlen;
1049         if (recvd < len) {
1050                 dprintk("NFS: server cheating in readlink reply: "
1051                                 "count %u > recvd %u\n", len, recvd);
1052                 return -EIO;
1053         }
1054
1055         xdr_terminate_string(rcvbuf, len);
1056         return 0;
1057 }
1058
1059 /*
1060  * 2.2.6.  readlinkres
1061  *
1062  *      union readlinkres switch (stat status) {
1063  *      case NFS_OK:
1064  *              path data;
1065  *      default:
1066  *              void;
1067  *      };
1068  */
1069 static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req, __be32 *p,
1070                                     void *__unused)
1071 {
1072         struct xdr_stream xdr;
1073         enum nfs_stat status;
1074         int error;
1075
1076         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1077         error = decode_stat(&xdr, &status);
1078         if (unlikely(error))
1079                 goto out;
1080         if (status != NFS_OK)
1081                 goto out_default;
1082         error = decode_path(&xdr);
1083 out:
1084         return error;
1085 out_default:
1086         return nfs_stat_to_errno(status);
1087 }
1088
1089 /*
1090  * 2.2.7.  readres
1091  *
1092  *      union readres switch (stat status) {
1093  *      case NFS_OK:
1094  *              fattr attributes;
1095  *              nfsdata data;
1096  *      default:
1097  *              void;
1098  *      };
1099  */
1100 static int nfs2_xdr_dec_readres(struct rpc_rqst *req, __be32 *p,
1101                                 struct nfs_readres *result)
1102 {
1103         struct xdr_stream xdr;
1104         enum nfs_stat status;
1105         int error;
1106
1107         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1108         error = decode_stat(&xdr, &status);
1109         if (unlikely(error))
1110                 goto out;
1111         if (status != NFS_OK)
1112                 goto out_default;
1113         error = decode_fattr(&xdr, result->fattr);
1114         if (unlikely(error))
1115                 goto out;
1116         error = decode_nfsdata(&xdr, result);
1117 out:
1118         return error;
1119 out_default:
1120         return nfs_stat_to_errno(status);
1121 }
1122
1123 /*
1124  * Decode WRITE reply
1125  */
1126 static int
1127 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1128 {
1129         res->verf->committed = NFS_FILE_SYNC;
1130         return nfs_xdr_attrstat(req, p, res->fattr);
1131 }
1132
1133 static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, __be32 *p,
1134                                  struct nfs_writeres *result)
1135 {
1136         struct xdr_stream xdr;
1137
1138         /* All NFSv2 writes are "file sync" writes */
1139         result->verf->committed = NFS_FILE_SYNC;
1140
1141         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1142         return decode_attrstat(&xdr, result->fattr);
1143 }
1144
1145 /**
1146  * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
1147  *                      the local page cache.
1148  * @xdr: XDR stream where entry resides
1149  * @entry: buffer to fill in with entry data
1150  * @server: nfs_server data for this directory
1151  * @plus: boolean indicating whether this should be a readdirplus entry
1152  *
1153  * Returns the position of the next item in the buffer, or an ERR_PTR.
1154  *
1155  * This function is not invoked during READDIR reply decoding, but
1156  * rather whenever an application invokes the getdents(2) system call
1157  * on a directory already in our cache.
1158  *
1159  * 2.2.17.  entry
1160  *
1161  *      struct entry {
1162  *              unsigned        fileid;
1163  *              filename        name;
1164  *              nfscookie       cookie;
1165  *              entry           *nextentry;
1166  *      };
1167  */
1168 __be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
1169                            struct nfs_server *server, int plus)
1170 {
1171         __be32 *p;
1172         int error;
1173
1174         p = xdr_inline_decode(xdr, 4);
1175         if (unlikely(p == NULL))
1176                 goto out_overflow;
1177         if (*p++ == xdr_zero) {
1178                 p = xdr_inline_decode(xdr, 4);
1179                 if (unlikely(p == NULL))
1180                         goto out_overflow;
1181                 if (*p++ == xdr_zero)
1182                         return ERR_PTR(-EAGAIN);
1183                 entry->eof = 1;
1184                 return ERR_PTR(-EBADCOOKIE);
1185         }
1186
1187         p = xdr_inline_decode(xdr, 4);
1188         if (unlikely(p == NULL))
1189                 goto out_overflow;
1190         entry->ino = be32_to_cpup(p);
1191
1192         error = decode_filename_inline(xdr, &entry->name, &entry->len);
1193         if (unlikely(error))
1194                 return ERR_PTR(error);
1195
1196         /*
1197          * The type (size and byte order) of nfscookie isn't defined in
1198          * RFC 1094.  This implementation assumes that it's an XDR uint32.
1199          */
1200         entry->prev_cookie = entry->cookie;
1201         p = xdr_inline_decode(xdr, 4);
1202         if (unlikely(p == NULL))
1203                 goto out_overflow;
1204         entry->cookie = be32_to_cpup(p);
1205
1206         entry->d_type = DT_UNKNOWN;
1207
1208         /* Peek at the next entry to see if we're at EOD */
1209         p = xdr_inline_peek(xdr, 4 + 4);
1210         entry->eof = 0;
1211         if (p != NULL)
1212                 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
1213         return p;
1214
1215 out_overflow:
1216         print_overflow_msg(__func__, xdr);
1217         return ERR_PTR(-EAGAIN);
1218 }
1219
1220 /*
1221  * 2.2.17.  readdirres
1222  *
1223  *      union readdirres switch (stat status) {
1224  *      case NFS_OK:
1225  *              struct {
1226  *                      entry *entries;
1227  *                      bool eof;
1228  *              } readdirok;
1229  *      default:
1230  *              void;
1231  *      };
1232  *
1233  * Read the directory contents into the page cache, but don't
1234  * touch them.  The actual decoding is done by nfs2_decode_dirent()
1235  * during subsequent nfs_readdir() calls.
1236  */
1237 static int decode_readdirok(struct xdr_stream *xdr)
1238 {
1239         u32 recvd, pglen;
1240         size_t hdrlen;
1241
1242         pglen = xdr->buf->page_len;
1243         hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1244         recvd = xdr->buf->len - hdrlen;
1245         if (unlikely(pglen > recvd))
1246                 goto out_cheating;
1247 out:
1248         xdr_read_pages(xdr, pglen);
1249         return pglen;
1250 out_cheating:
1251         dprintk("NFS: server cheating in readdir result: "
1252                 "pglen %u > recvd %u\n", pglen, recvd);
1253         pglen = recvd;
1254         goto out;
1255 }
1256
1257 static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, __be32 *p,
1258                                    void *__unused)
1259 {
1260         struct xdr_stream xdr;
1261         enum nfs_stat status;
1262         int error;
1263
1264         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1265         error = decode_stat(&xdr, &status);
1266         if (unlikely(error))
1267                 goto out;
1268         if (status != NFS_OK)
1269                 goto out_default;
1270         error = decode_readdirok(&xdr);
1271 out:
1272         return error;
1273 out_default:
1274         return nfs_stat_to_errno(status);
1275 }
1276
1277 /*
1278  * Decode STATFS reply
1279  */
1280 static int
1281 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
1282 {
1283         int     status;
1284
1285         if ((status = ntohl(*p++)))
1286                 return nfs_stat_to_errno(status);
1287
1288         res->tsize  = ntohl(*p++);
1289         res->bsize  = ntohl(*p++);
1290         res->blocks = ntohl(*p++);
1291         res->bfree  = ntohl(*p++);
1292         res->bavail = ntohl(*p++);
1293         return 0;
1294 }
1295
1296 /*
1297  * 2.2.18.  statfsres
1298  *
1299  *      union statfsres (stat status) {
1300  *      case NFS_OK:
1301  *              struct {
1302  *                      unsigned tsize;
1303  *                      unsigned bsize;
1304  *                      unsigned blocks;
1305  *                      unsigned bfree;
1306  *                      unsigned bavail;
1307  *              } info;
1308  *      default:
1309  *              void;
1310  *      };
1311  */
1312 static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1313 {
1314         __be32 *p;
1315
1316         p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1317         if (unlikely(p == NULL))
1318                 goto out_overflow;
1319         result->tsize  = be32_to_cpup(p++);
1320         result->bsize  = be32_to_cpup(p++);
1321         result->blocks = be32_to_cpup(p++);
1322         result->bfree  = be32_to_cpup(p++);
1323         result->bavail = be32_to_cpup(p);
1324         return 0;
1325 out_overflow:
1326         print_overflow_msg(__func__, xdr);
1327         return -EIO;
1328 }
1329
1330 static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, __be32 *p,
1331                                   struct nfs2_fsstat *result)
1332 {
1333         struct xdr_stream xdr;
1334         enum nfs_stat status;
1335         int error;
1336
1337         xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1338         error = decode_stat(&xdr, &status);
1339         if (unlikely(error))
1340                 goto out;
1341         if (status != NFS_OK)
1342                 goto out_default;
1343         error = decode_info(&xdr, result);
1344 out:
1345         return error;
1346 out_default:
1347         return nfs_stat_to_errno(status);
1348 }
1349
1350
1351 /*
1352  * We need to translate between nfs status return values and
1353  * the local errno values which may not be the same.
1354  */
1355 static const struct {
1356         int stat;
1357         int errno;
1358 } nfs_errtbl[] = {
1359         { NFS_OK,               0               },
1360         { NFSERR_PERM,          -EPERM          },
1361         { NFSERR_NOENT,         -ENOENT         },
1362         { NFSERR_IO,            -errno_NFSERR_IO},
1363         { NFSERR_NXIO,          -ENXIO          },
1364 /*      { NFSERR_EAGAIN,        -EAGAIN         }, */
1365         { NFSERR_ACCES,         -EACCES         },
1366         { NFSERR_EXIST,         -EEXIST         },
1367         { NFSERR_XDEV,          -EXDEV          },
1368         { NFSERR_NODEV,         -ENODEV         },
1369         { NFSERR_NOTDIR,        -ENOTDIR        },
1370         { NFSERR_ISDIR,         -EISDIR         },
1371         { NFSERR_INVAL,         -EINVAL         },
1372         { NFSERR_FBIG,          -EFBIG          },
1373         { NFSERR_NOSPC,         -ENOSPC         },
1374         { NFSERR_ROFS,          -EROFS          },
1375         { NFSERR_MLINK,         -EMLINK         },
1376         { NFSERR_NAMETOOLONG,   -ENAMETOOLONG   },
1377         { NFSERR_NOTEMPTY,      -ENOTEMPTY      },
1378         { NFSERR_DQUOT,         -EDQUOT         },
1379         { NFSERR_STALE,         -ESTALE         },
1380         { NFSERR_REMOTE,        -EREMOTE        },
1381 #ifdef EWFLUSH
1382         { NFSERR_WFLUSH,        -EWFLUSH        },
1383 #endif
1384         { NFSERR_BADHANDLE,     -EBADHANDLE     },
1385         { NFSERR_NOT_SYNC,      -ENOTSYNC       },
1386         { NFSERR_BAD_COOKIE,    -EBADCOOKIE     },
1387         { NFSERR_NOTSUPP,       -ENOTSUPP       },
1388         { NFSERR_TOOSMALL,      -ETOOSMALL      },
1389         { NFSERR_SERVERFAULT,   -EREMOTEIO      },
1390         { NFSERR_BADTYPE,       -EBADTYPE       },
1391         { NFSERR_JUKEBOX,       -EJUKEBOX       },
1392         { -1,                   -EIO            }
1393 };
1394
1395 /**
1396  * nfs_stat_to_errno - convert an NFS status code to a local errno
1397  * @status: NFS status code to convert
1398  *
1399  * Returns a local errno value, or -EIO if the NFS status code is
1400  * not recognized.  This function is used jointly by NFSv2 and NFSv3.
1401  */
1402 int nfs_stat_to_errno(enum nfs_stat status)
1403 {
1404         int i;
1405
1406         for (i = 0; nfs_errtbl[i].stat != -1; i++) {
1407                 if (nfs_errtbl[i].stat == (int)status)
1408                         return nfs_errtbl[i].errno;
1409         }
1410         dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1411         return nfs_errtbl[i].errno;
1412 }
1413
1414 #define PROC(proc, argtype, restype, timer)                             \
1415 [NFSPROC_##proc] = {                                                    \
1416         .p_proc     =  NFSPROC_##proc,                                  \
1417         .p_encode   =  (kxdrproc_t)nfs2_xdr_enc_##argtype,              \
1418         .p_decode   =  (kxdrproc_t)nfs2_xdr_dec_##restype,              \
1419         .p_arglen   =  NFS_##argtype##_sz,                              \
1420         .p_replen   =  NFS_##restype##_sz,                              \
1421         .p_timer    =  timer,                                           \
1422         .p_statidx  =  NFSPROC_##proc,                                  \
1423         .p_name     =  #proc,                                           \
1424         }
1425 struct rpc_procinfo     nfs_procedures[] = {
1426     PROC(GETATTR,       fhandle,        attrstat, 1),
1427     PROC(SETATTR,       sattrargs,      attrstat, 0),
1428     PROC(LOOKUP,        diropargs,      diropres, 2),
1429     PROC(READLINK,      readlinkargs,   readlinkres, 3),
1430     PROC(READ,          readargs,       readres, 3),
1431     PROC(WRITE,         writeargs,      writeres, 4),
1432     PROC(CREATE,        createargs,     diropres, 0),
1433     PROC(REMOVE,        removeargs,     stat, 0),
1434     PROC(RENAME,        renameargs,     stat, 0),
1435     PROC(LINK,          linkargs,       stat, 0),
1436     PROC(SYMLINK,       symlinkargs,    stat, 0),
1437     PROC(MKDIR,         createargs,     diropres, 0),
1438     PROC(RMDIR,         diropargs,      stat, 0),
1439     PROC(READDIR,       readdirargs,    readdirres, 3),
1440     PROC(STATFS,        fhandle,        statfsres, 0),
1441 };
1442
1443 struct rpc_version              nfs_version2 = {
1444         .number                 = 2,
1445         .nrprocs                = ARRAY_SIZE(nfs_procedures),
1446         .procs                  = nfs_procedures
1447 };