chipsfb: use correct pm state
[linux-2.6] / 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/slab.h>
13 #include <linux/utsname.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/in.h>
17 #include <linux/pagemap.h>
18 #include <linux/proc_fs.h>
19 #include <linux/kdev_t.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs3.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/nfsacl.h>
25 #include "internal.h"
26
27 #define NFSDBG_FACILITY         NFSDBG_XDR
28
29 /* Mapping from NFS error code to "errno" error code. */
30 #define errno_NFSERR_IO         EIO
31
32 /*
33  * Declare the space requirements for NFS arguments and replies as
34  * number of 32bit-words
35  */
36 #define NFS3_fhandle_sz         (1+16)
37 #define NFS3_fh_sz              (NFS3_fhandle_sz)       /* shorthand */
38 #define NFS3_sattr_sz           (15)
39 #define NFS3_filename_sz        (1+(NFS3_MAXNAMLEN>>2))
40 #define NFS3_path_sz            (1+(NFS3_MAXPATHLEN>>2))
41 #define NFS3_fattr_sz           (21)
42 #define NFS3_wcc_attr_sz                (6)
43 #define NFS3_pre_op_attr_sz     (1+NFS3_wcc_attr_sz)
44 #define NFS3_post_op_attr_sz    (1+NFS3_fattr_sz)
45 #define NFS3_wcc_data_sz                (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
46 #define NFS3_fsstat_sz          
47 #define NFS3_fsinfo_sz          
48 #define NFS3_pathconf_sz                
49 #define NFS3_entry_sz           (NFS3_filename_sz+3)
50
51 #define NFS3_sattrargs_sz       (NFS3_fh_sz+NFS3_sattr_sz+3)
52 #define NFS3_diropargs_sz       (NFS3_fh_sz+NFS3_filename_sz)
53 #define NFS3_removeargs_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_renameargs_sz      (NFS3_diropargs_sz+NFS3_diropargs_sz)
63 #define NFS3_linkargs_sz                (NFS3_fh_sz+NFS3_diropargs_sz)
64 #define NFS3_readdirargs_sz     (NFS3_fh_sz+2)
65 #define NFS3_commitargs_sz      (NFS3_fh_sz+3)
66
67 #define NFS3_attrstat_sz        (1+NFS3_fattr_sz)
68 #define NFS3_wccstat_sz         (1+NFS3_wcc_data_sz)
69 #define NFS3_removeres_sz       (NFS3_wccstat_sz)
70 #define NFS3_lookupres_sz       (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
71 #define NFS3_accessres_sz       (1+NFS3_post_op_attr_sz+1)
72 #define NFS3_readlinkres_sz     (1+NFS3_post_op_attr_sz+1)
73 #define NFS3_readres_sz         (1+NFS3_post_op_attr_sz+3)
74 #define NFS3_writeres_sz        (1+NFS3_wcc_data_sz+4)
75 #define NFS3_createres_sz       (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76 #define NFS3_renameres_sz       (1+(2 * NFS3_wcc_data_sz))
77 #define NFS3_linkres_sz         (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78 #define NFS3_readdirres_sz      (1+NFS3_post_op_attr_sz+2)
79 #define NFS3_fsstatres_sz       (1+NFS3_post_op_attr_sz+13)
80 #define NFS3_fsinfores_sz       (1+NFS3_post_op_attr_sz+12)
81 #define NFS3_pathconfres_sz     (1+NFS3_post_op_attr_sz+6)
82 #define NFS3_commitres_sz       (1+NFS3_wcc_data_sz+2)
83
84 #define ACL3_getaclargs_sz      (NFS3_fh_sz+1)
85 #define ACL3_setaclargs_sz      (NFS3_fh_sz+1+2*(2+5*3))
86 #define ACL3_getaclres_sz       (1+NFS3_post_op_attr_sz+1+2*(2+5*3))
87 #define ACL3_setaclres_sz       (1+NFS3_post_op_attr_sz)
88
89 /*
90  * Map file type to S_IFMT bits
91  */
92 static struct {
93         unsigned int    mode;
94         unsigned int    nfs2type;
95 } nfs_type2fmt[] = {
96       { 0,              NFNON   },
97       { S_IFREG,        NFREG   },
98       { S_IFDIR,        NFDIR   },
99       { S_IFBLK,        NFBLK   },
100       { S_IFCHR,        NFCHR   },
101       { S_IFLNK,        NFLNK   },
102       { S_IFSOCK,       NFSOCK  },
103       { S_IFIFO,        NFFIFO  },
104       { 0,              NFBAD   }
105 };
106
107 /*
108  * Common NFS XDR functions as inlines
109  */
110 static inline __be32 *
111 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
112 {
113         return xdr_encode_array(p, fh->data, fh->size);
114 }
115
116 static inline __be32 *
117 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
118 {
119         if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
120                 memcpy(fh->data, p, fh->size);
121                 return p + XDR_QUADLEN(fh->size);
122         }
123         return NULL;
124 }
125
126 /*
127  * Encode/decode time.
128  */
129 static inline __be32 *
130 xdr_encode_time3(__be32 *p, struct timespec *timep)
131 {
132         *p++ = htonl(timep->tv_sec);
133         *p++ = htonl(timep->tv_nsec);
134         return p;
135 }
136
137 static inline __be32 *
138 xdr_decode_time3(__be32 *p, struct timespec *timep)
139 {
140         timep->tv_sec = ntohl(*p++);
141         timep->tv_nsec = ntohl(*p++);
142         return p;
143 }
144
145 static __be32 *
146 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
147 {
148         unsigned int    type, major, minor;
149         int             fmode;
150
151         type = ntohl(*p++);
152         if (type >= NF3BAD)
153                 type = NF3BAD;
154         fmode = nfs_type2fmt[type].mode;
155         fattr->type = nfs_type2fmt[type].nfs2type;
156         fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
157         fattr->nlink = ntohl(*p++);
158         fattr->uid = ntohl(*p++);
159         fattr->gid = ntohl(*p++);
160         p = xdr_decode_hyper(p, &fattr->size);
161         p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
162
163         /* Turn remote device info into Linux-specific dev_t */
164         major = ntohl(*p++);
165         minor = ntohl(*p++);
166         fattr->rdev = MKDEV(major, minor);
167         if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
168                 fattr->rdev = 0;
169
170         p = xdr_decode_hyper(p, &fattr->fsid.major);
171         fattr->fsid.minor = 0;
172         p = xdr_decode_hyper(p, &fattr->fileid);
173         p = xdr_decode_time3(p, &fattr->atime);
174         p = xdr_decode_time3(p, &fattr->mtime);
175         p = xdr_decode_time3(p, &fattr->ctime);
176
177         /* Update the mode bits */
178         fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
179         return p;
180 }
181
182 static inline __be32 *
183 xdr_encode_sattr(__be32 *p, struct iattr *attr)
184 {
185         if (attr->ia_valid & ATTR_MODE) {
186                 *p++ = xdr_one;
187                 *p++ = htonl(attr->ia_mode & S_IALLUGO);
188         } else {
189                 *p++ = xdr_zero;
190         }
191         if (attr->ia_valid & ATTR_UID) {
192                 *p++ = xdr_one;
193                 *p++ = htonl(attr->ia_uid);
194         } else {
195                 *p++ = xdr_zero;
196         }
197         if (attr->ia_valid & ATTR_GID) {
198                 *p++ = xdr_one;
199                 *p++ = htonl(attr->ia_gid);
200         } else {
201                 *p++ = xdr_zero;
202         }
203         if (attr->ia_valid & ATTR_SIZE) {
204                 *p++ = xdr_one;
205                 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
206         } else {
207                 *p++ = xdr_zero;
208         }
209         if (attr->ia_valid & ATTR_ATIME_SET) {
210                 *p++ = xdr_two;
211                 p = xdr_encode_time3(p, &attr->ia_atime);
212         } else if (attr->ia_valid & ATTR_ATIME) {
213                 *p++ = xdr_one;
214         } else {
215                 *p++ = xdr_zero;
216         }
217         if (attr->ia_valid & ATTR_MTIME_SET) {
218                 *p++ = xdr_two;
219                 p = xdr_encode_time3(p, &attr->ia_mtime);
220         } else if (attr->ia_valid & ATTR_MTIME) {
221                 *p++ = xdr_one;
222         } else {
223                 *p++ = xdr_zero;
224         }
225         return p;
226 }
227
228 static inline __be32 *
229 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
230 {
231         p = xdr_decode_hyper(p, &fattr->pre_size);
232         p = xdr_decode_time3(p, &fattr->pre_mtime);
233         p = xdr_decode_time3(p, &fattr->pre_ctime);
234         fattr->valid |= NFS_ATTR_WCC;
235         return p;
236 }
237
238 static inline __be32 *
239 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
240 {
241         if (*p++)
242                 p = xdr_decode_fattr(p, fattr);
243         return p;
244 }
245
246 static inline __be32 *
247 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
248 {
249         if (*p++)
250                 return xdr_decode_wcc_attr(p, fattr);
251         return p;
252 }
253
254
255 static inline __be32 *
256 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
257 {
258         p = xdr_decode_pre_op_attr(p, fattr);
259         return xdr_decode_post_op_attr(p, fattr);
260 }
261
262 /*
263  * NFS encode functions
264  */
265
266 /*
267  * Encode file handle argument
268  */
269 static int
270 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
271 {
272         p = xdr_encode_fhandle(p, fh);
273         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
274         return 0;
275 }
276
277 /*
278  * Encode SETATTR arguments
279  */
280 static int
281 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
282 {
283         p = xdr_encode_fhandle(p, args->fh);
284         p = xdr_encode_sattr(p, args->sattr);
285         *p++ = htonl(args->guard);
286         if (args->guard)
287                 p = xdr_encode_time3(p, &args->guardtime);
288         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
289         return 0;
290 }
291
292 /*
293  * Encode directory ops argument
294  */
295 static int
296 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
297 {
298         p = xdr_encode_fhandle(p, args->fh);
299         p = xdr_encode_array(p, args->name, args->len);
300         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
301         return 0;
302 }
303
304 /*
305  * Encode REMOVE argument
306  */
307 static int
308 nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
309 {
310         p = xdr_encode_fhandle(p, args->fh);
311         p = xdr_encode_array(p, args->name.name, args->name.len);
312         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
313         return 0;
314 }
315
316 /*
317  * Encode access() argument
318  */
319 static int
320 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
321 {
322         p = xdr_encode_fhandle(p, args->fh);
323         *p++ = htonl(args->access);
324         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
325         return 0;
326 }
327
328 /*
329  * Arguments to a READ call. Since we read data directly into the page
330  * cache, we also set up the reply iovec here so that iov[1] points
331  * exactly to the page we want to fetch.
332  */
333 static int
334 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
335 {
336         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
337         unsigned int replen;
338         u32 count = args->count;
339
340         p = xdr_encode_fhandle(p, args->fh);
341         p = xdr_encode_hyper(p, args->offset);
342         *p++ = htonl(count);
343         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
344
345         /* Inline the page array */
346         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
347         xdr_inline_pages(&req->rq_rcv_buf, replen,
348                          args->pages, args->pgbase, count);
349         return 0;
350 }
351
352 /*
353  * Write arguments. Splice the buffer to be written into the iovec.
354  */
355 static int
356 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
357 {
358         struct xdr_buf *sndbuf = &req->rq_snd_buf;
359         u32 count = args->count;
360
361         p = xdr_encode_fhandle(p, args->fh);
362         p = xdr_encode_hyper(p, args->offset);
363         *p++ = htonl(count);
364         *p++ = htonl(args->stable);
365         *p++ = htonl(count);
366         sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
367
368         /* Copy the page array */
369         xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
370         return 0;
371 }
372
373 /*
374  * Encode CREATE arguments
375  */
376 static int
377 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
378 {
379         p = xdr_encode_fhandle(p, args->fh);
380         p = xdr_encode_array(p, args->name, args->len);
381
382         *p++ = htonl(args->createmode);
383         if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
384                 *p++ = args->verifier[0];
385                 *p++ = args->verifier[1];
386         } else
387                 p = xdr_encode_sattr(p, args->sattr);
388
389         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
390         return 0;
391 }
392
393 /*
394  * Encode MKDIR arguments
395  */
396 static int
397 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
398 {
399         p = xdr_encode_fhandle(p, args->fh);
400         p = xdr_encode_array(p, args->name, args->len);
401         p = xdr_encode_sattr(p, args->sattr);
402         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
403         return 0;
404 }
405
406 /*
407  * Encode SYMLINK arguments
408  */
409 static int
410 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
411 {
412         p = xdr_encode_fhandle(p, args->fromfh);
413         p = xdr_encode_array(p, args->fromname, args->fromlen);
414         p = xdr_encode_sattr(p, args->sattr);
415         *p++ = htonl(args->pathlen);
416         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
417
418         /* Copy the page */
419         xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
420         return 0;
421 }
422
423 /*
424  * Encode MKNOD arguments
425  */
426 static int
427 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
428 {
429         p = xdr_encode_fhandle(p, args->fh);
430         p = xdr_encode_array(p, args->name, args->len);
431         *p++ = htonl(args->type);
432         p = xdr_encode_sattr(p, args->sattr);
433         if (args->type == NF3CHR || args->type == NF3BLK) {
434                 *p++ = htonl(MAJOR(args->rdev));
435                 *p++ = htonl(MINOR(args->rdev));
436         }
437
438         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
439         return 0;
440 }
441
442 /*
443  * Encode RENAME arguments
444  */
445 static int
446 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
447 {
448         p = xdr_encode_fhandle(p, args->fromfh);
449         p = xdr_encode_array(p, args->fromname, args->fromlen);
450         p = xdr_encode_fhandle(p, args->tofh);
451         p = xdr_encode_array(p, args->toname, args->tolen);
452         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
453         return 0;
454 }
455
456 /*
457  * Encode LINK arguments
458  */
459 static int
460 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
461 {
462         p = xdr_encode_fhandle(p, args->fromfh);
463         p = xdr_encode_fhandle(p, args->tofh);
464         p = xdr_encode_array(p, args->toname, args->tolen);
465         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
466         return 0;
467 }
468
469 /*
470  * Encode arguments to readdir call
471  */
472 static int
473 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
474 {
475         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
476         unsigned int replen;
477         u32 count = args->count;
478
479         p = xdr_encode_fhandle(p, args->fh);
480         p = xdr_encode_hyper(p, args->cookie);
481         *p++ = args->verf[0];
482         *p++ = args->verf[1];
483         if (args->plus) {
484                 /* readdirplus: need dircount + buffer size.
485                  * We just make sure we make dircount big enough */
486                 *p++ = htonl(count >> 3);
487         }
488         *p++ = htonl(count);
489         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
490
491         /* Inline the page array */
492         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
493         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
494         return 0;
495 }
496
497 /*
498  * Decode the result of a readdir call.
499  * We just check for syntactical correctness.
500  */
501 static int
502 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
503 {
504         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
505         struct kvec *iov = rcvbuf->head;
506         struct page **page;
507         int hdrlen, recvd;
508         int status, nr;
509         unsigned int len, pglen;
510         __be32 *entry, *end, *kaddr;
511
512         status = ntohl(*p++);
513         /* Decode post_op_attrs */
514         p = xdr_decode_post_op_attr(p, res->dir_attr);
515         if (status)
516                 return -nfs_stat_to_errno(status);
517         /* Decode verifier cookie */
518         if (res->verf) {
519                 res->verf[0] = *p++;
520                 res->verf[1] = *p++;
521         } else {
522                 p += 2;
523         }
524
525         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
526         if (iov->iov_len < hdrlen) {
527                 printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
528                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
529                 return -errno_NFSERR_IO;
530         } else if (iov->iov_len != hdrlen) {
531                 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
532                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
533         }
534
535         pglen = rcvbuf->page_len;
536         recvd = rcvbuf->len - hdrlen;
537         if (pglen > recvd)
538                 pglen = recvd;
539         page = rcvbuf->pages;
540         kaddr = p = kmap_atomic(*page, KM_USER0);
541         end = (__be32 *)((char *)p + pglen);
542         entry = p;
543         for (nr = 0; *p++; nr++) {
544                 if (p + 3 > end)
545                         goto short_pkt;
546                 p += 2;                         /* inode # */
547                 len = ntohl(*p++);              /* string length */
548                 p += XDR_QUADLEN(len) + 2;      /* name + cookie */
549                 if (len > NFS3_MAXNAMLEN) {
550                         printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
551                                                 len);
552                         goto err_unmap;
553                 }
554
555                 if (res->plus) {
556                         /* post_op_attr */
557                         if (p + 2 > end)
558                                 goto short_pkt;
559                         if (*p++) {
560                                 p += 21;
561                                 if (p + 1 > end)
562                                         goto short_pkt;
563                         }
564                         /* post_op_fh3 */
565                         if (*p++) {
566                                 if (p + 1 > end)
567                                         goto short_pkt;
568                                 len = ntohl(*p++);
569                                 if (len > NFS3_FHSIZE) {
570                                         printk(KERN_WARNING "NFS: giant filehandle in "
571                                                 "readdir (len %x)!\n", len);
572                                         goto err_unmap;
573                                 }
574                                 p += XDR_QUADLEN(len);
575                         }
576                 }
577
578                 if (p + 2 > end)
579                         goto short_pkt;
580                 entry = p;
581         }
582         if (!nr && (entry[0] != 0 || entry[1] == 0))
583                 goto short_pkt;
584  out:
585         kunmap_atomic(kaddr, KM_USER0);
586         return nr;
587  short_pkt:
588         entry[0] = entry[1] = 0;
589         /* truncate listing ? */
590         if (!nr) {
591                 printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
592                 entry[1] = 1;
593         }
594         goto out;
595 err_unmap:
596         nr = -errno_NFSERR_IO;
597         goto out;
598 }
599
600 __be32 *
601 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
602 {
603         struct nfs_entry old = *entry;
604
605         if (!*p++) {
606                 if (!*p)
607                         return ERR_PTR(-EAGAIN);
608                 entry->eof = 1;
609                 return ERR_PTR(-EBADCOOKIE);
610         }
611
612         p = xdr_decode_hyper(p, &entry->ino);
613         entry->len  = ntohl(*p++);
614         entry->name = (const char *) p;
615         p += XDR_QUADLEN(entry->len);
616         entry->prev_cookie = entry->cookie;
617         p = xdr_decode_hyper(p, &entry->cookie);
618
619         if (plus) {
620                 entry->fattr->valid = 0;
621                 p = xdr_decode_post_op_attr(p, entry->fattr);
622                 /* In fact, a post_op_fh3: */
623                 if (*p++) {
624                         p = xdr_decode_fhandle(p, entry->fh);
625                         /* Ugh -- server reply was truncated */
626                         if (p == NULL) {
627                                 dprintk("NFS: FH truncated\n");
628                                 *entry = old;
629                                 return ERR_PTR(-EAGAIN);
630                         }
631                 } else
632                         memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
633         }
634
635         entry->eof = !p[0] && p[1];
636         return p;
637 }
638
639 /*
640  * Encode COMMIT arguments
641  */
642 static int
643 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
644 {
645         p = xdr_encode_fhandle(p, args->fh);
646         p = xdr_encode_hyper(p, args->offset);
647         *p++ = htonl(args->count);
648         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
649         return 0;
650 }
651
652 #ifdef CONFIG_NFS_V3_ACL
653 /*
654  * Encode GETACL arguments
655  */
656 static int
657 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
658                     struct nfs3_getaclargs *args)
659 {
660         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
661         unsigned int replen;
662
663         p = xdr_encode_fhandle(p, args->fh);
664         *p++ = htonl(args->mask);
665         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
666
667         if (args->mask & (NFS_ACL | NFS_DFACL)) {
668                 /* Inline the page array */
669                 replen = (RPC_REPHDRSIZE + auth->au_rslack +
670                           ACL3_getaclres_sz) << 2;
671                 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
672                                  NFSACL_MAXPAGES << PAGE_SHIFT);
673         }
674         return 0;
675 }
676
677 /*
678  * Encode SETACL arguments
679  */
680 static int
681 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
682                    struct nfs3_setaclargs *args)
683 {
684         struct xdr_buf *buf = &req->rq_snd_buf;
685         unsigned int base, len_in_head, len = nfsacl_size(
686                 (args->mask & NFS_ACL)   ? args->acl_access  : NULL,
687                 (args->mask & NFS_DFACL) ? args->acl_default : NULL);
688         int count, err;
689
690         p = xdr_encode_fhandle(p, NFS_FH(args->inode));
691         *p++ = htonl(args->mask);
692         base = (char *)p - (char *)buf->head->iov_base;
693         /* put as much of the acls into head as possible. */
694         len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
695         len -= len_in_head;
696         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
697
698         for (count = 0; (count << PAGE_SHIFT) < len; count++) {
699                 args->pages[count] = alloc_page(GFP_KERNEL);
700                 if (!args->pages[count]) {
701                         while (count)
702                                 __free_page(args->pages[--count]);
703                         return -ENOMEM;
704                 }
705         }
706         xdr_encode_pages(buf, args->pages, 0, len);
707
708         err = nfsacl_encode(buf, base, args->inode,
709                             (args->mask & NFS_ACL) ?
710                             args->acl_access : NULL, 1, 0);
711         if (err > 0)
712                 err = nfsacl_encode(buf, base + err, args->inode,
713                                     (args->mask & NFS_DFACL) ?
714                                     args->acl_default : NULL, 1,
715                                     NFS_ACL_DEFAULT);
716         return (err > 0) ? 0 : err;
717 }
718 #endif  /* CONFIG_NFS_V3_ACL */
719
720 /*
721  * NFS XDR decode functions
722  */
723
724 /*
725  * Decode attrstat reply.
726  */
727 static int
728 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
729 {
730         int     status;
731
732         if ((status = ntohl(*p++)))
733                 return -nfs_stat_to_errno(status);
734         xdr_decode_fattr(p, fattr);
735         return 0;
736 }
737
738 /*
739  * Decode status+wcc_data reply
740  * SATTR, REMOVE, RMDIR
741  */
742 static int
743 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
744 {
745         int     status;
746
747         if ((status = ntohl(*p++)))
748                 status = -nfs_stat_to_errno(status);
749         xdr_decode_wcc_data(p, fattr);
750         return status;
751 }
752
753 static int
754 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
755 {
756         return nfs3_xdr_wccstat(req, p, &res->dir_attr);
757 }
758
759 /*
760  * Decode LOOKUP reply
761  */
762 static int
763 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
764 {
765         int     status;
766
767         if ((status = ntohl(*p++))) {
768                 status = -nfs_stat_to_errno(status);
769         } else {
770                 if (!(p = xdr_decode_fhandle(p, res->fh)))
771                         return -errno_NFSERR_IO;
772                 p = xdr_decode_post_op_attr(p, res->fattr);
773         }
774         xdr_decode_post_op_attr(p, res->dir_attr);
775         return status;
776 }
777
778 /*
779  * Decode ACCESS reply
780  */
781 static int
782 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
783 {
784         int     status = ntohl(*p++);
785
786         p = xdr_decode_post_op_attr(p, res->fattr);
787         if (status)
788                 return -nfs_stat_to_errno(status);
789         res->access = ntohl(*p++);
790         return 0;
791 }
792
793 static int
794 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
795 {
796         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
797         unsigned int replen;
798
799         p = xdr_encode_fhandle(p, args->fh);
800         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
801
802         /* Inline the page array */
803         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
804         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
805         return 0;
806 }
807
808 /*
809  * Decode READLINK reply
810  */
811 static int
812 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
813 {
814         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
815         struct kvec *iov = rcvbuf->head;
816         int hdrlen, len, recvd;
817         char    *kaddr;
818         int     status;
819
820         status = ntohl(*p++);
821         p = xdr_decode_post_op_attr(p, fattr);
822
823         if (status != 0)
824                 return -nfs_stat_to_errno(status);
825
826         /* Convert length of symlink */
827         len = ntohl(*p++);
828         if (len >= rcvbuf->page_len || len <= 0) {
829                 dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
830                 return -ENAMETOOLONG;
831         }
832
833         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
834         if (iov->iov_len < hdrlen) {
835                 printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
836                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
837                 return -errno_NFSERR_IO;
838         } else if (iov->iov_len != hdrlen) {
839                 dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
840                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
841         }
842         recvd = req->rq_rcv_buf.len - hdrlen;
843         if (recvd < len) {
844                 printk(KERN_WARNING "NFS: server cheating in readlink reply: "
845                                 "count %u > recvd %u\n", len, recvd);
846                 return -EIO;
847         }
848
849         /* NULL terminate the string we got */
850         kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
851         kaddr[len+rcvbuf->page_base] = '\0';
852         kunmap_atomic(kaddr, KM_USER0);
853         return 0;
854 }
855
856 /*
857  * Decode READ reply
858  */
859 static int
860 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
861 {
862         struct kvec *iov = req->rq_rcv_buf.head;
863         int     status, count, ocount, recvd, hdrlen;
864
865         status = ntohl(*p++);
866         p = xdr_decode_post_op_attr(p, res->fattr);
867
868         if (status != 0)
869                 return -nfs_stat_to_errno(status);
870
871         /* Decode reply could and EOF flag. NFSv3 is somewhat redundant
872          * in that it puts the count both in the res struct and in the
873          * opaque data count. */
874         count    = ntohl(*p++);
875         res->eof = ntohl(*p++);
876         ocount   = ntohl(*p++);
877
878         if (ocount != count) {
879                 printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
880                 return -errno_NFSERR_IO;
881         }
882
883         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
884         if (iov->iov_len < hdrlen) {
885                 printk(KERN_WARNING "NFS: READ reply header overflowed:"
886                                 "length %d > %Zu\n", hdrlen, iov->iov_len);
887                 return -errno_NFSERR_IO;
888         } else if (iov->iov_len != hdrlen) {
889                 dprintk("NFS: READ header is short. iovec will be shifted.\n");
890                 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
891         }
892
893         recvd = req->rq_rcv_buf.len - hdrlen;
894         if (count > recvd) {
895                 printk(KERN_WARNING "NFS: server cheating in read reply: "
896                         "count %d > recvd %d\n", count, recvd);
897                 count = recvd;
898                 res->eof = 0;
899         }
900
901         if (count < res->count)
902                 res->count = count;
903
904         return count;
905 }
906
907 /*
908  * Decode WRITE response
909  */
910 static int
911 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
912 {
913         int     status;
914
915         status = ntohl(*p++);
916         p = xdr_decode_wcc_data(p, res->fattr);
917
918         if (status != 0)
919                 return -nfs_stat_to_errno(status);
920
921         res->count = ntohl(*p++);
922         res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
923         res->verf->verifier[0] = *p++;
924         res->verf->verifier[1] = *p++;
925
926         return res->count;
927 }
928
929 /*
930  * Decode a CREATE response
931  */
932 static int
933 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
934 {
935         int     status;
936
937         status = ntohl(*p++);
938         if (status == 0) {
939                 if (*p++) {
940                         if (!(p = xdr_decode_fhandle(p, res->fh)))
941                                 return -errno_NFSERR_IO;
942                         p = xdr_decode_post_op_attr(p, res->fattr);
943                 } else {
944                         memset(res->fh, 0, sizeof(*res->fh));
945                         /* Do decode post_op_attr but set it to NULL */
946                         p = xdr_decode_post_op_attr(p, res->fattr);
947                         res->fattr->valid = 0;
948                 }
949         } else {
950                 status = -nfs_stat_to_errno(status);
951         }
952         p = xdr_decode_wcc_data(p, res->dir_attr);
953         return status;
954 }
955
956 /*
957  * Decode RENAME reply
958  */
959 static int
960 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
961 {
962         int     status;
963
964         if ((status = ntohl(*p++)) != 0)
965                 status = -nfs_stat_to_errno(status);
966         p = xdr_decode_wcc_data(p, res->fromattr);
967         p = xdr_decode_wcc_data(p, res->toattr);
968         return status;
969 }
970
971 /*
972  * Decode LINK reply
973  */
974 static int
975 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
976 {
977         int     status;
978
979         if ((status = ntohl(*p++)) != 0)
980                 status = -nfs_stat_to_errno(status);
981         p = xdr_decode_post_op_attr(p, res->fattr);
982         p = xdr_decode_wcc_data(p, res->dir_attr);
983         return status;
984 }
985
986 /*
987  * Decode FSSTAT reply
988  */
989 static int
990 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
991 {
992         int             status;
993
994         status = ntohl(*p++);
995
996         p = xdr_decode_post_op_attr(p, res->fattr);
997         if (status != 0)
998                 return -nfs_stat_to_errno(status);
999
1000         p = xdr_decode_hyper(p, &res->tbytes);
1001         p = xdr_decode_hyper(p, &res->fbytes);
1002         p = xdr_decode_hyper(p, &res->abytes);
1003         p = xdr_decode_hyper(p, &res->tfiles);
1004         p = xdr_decode_hyper(p, &res->ffiles);
1005         p = xdr_decode_hyper(p, &res->afiles);
1006
1007         /* ignore invarsec */
1008         return 0;
1009 }
1010
1011 /*
1012  * Decode FSINFO reply
1013  */
1014 static int
1015 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1016 {
1017         int             status;
1018
1019         status = ntohl(*p++);
1020
1021         p = xdr_decode_post_op_attr(p, res->fattr);
1022         if (status != 0)
1023                 return -nfs_stat_to_errno(status);
1024
1025         res->rtmax  = ntohl(*p++);
1026         res->rtpref = ntohl(*p++);
1027         res->rtmult = ntohl(*p++);
1028         res->wtmax  = ntohl(*p++);
1029         res->wtpref = ntohl(*p++);
1030         res->wtmult = ntohl(*p++);
1031         res->dtpref = ntohl(*p++);
1032         p = xdr_decode_hyper(p, &res->maxfilesize);
1033
1034         /* ignore time_delta and properties */
1035         res->lease_time = 0;
1036         return 0;
1037 }
1038
1039 /*
1040  * Decode PATHCONF reply
1041  */
1042 static int
1043 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1044 {
1045         int             status;
1046
1047         status = ntohl(*p++);
1048
1049         p = xdr_decode_post_op_attr(p, res->fattr);
1050         if (status != 0)
1051                 return -nfs_stat_to_errno(status);
1052         res->max_link = ntohl(*p++);
1053         res->max_namelen = ntohl(*p++);
1054
1055         /* ignore remaining fields */
1056         return 0;
1057 }
1058
1059 /*
1060  * Decode COMMIT reply
1061  */
1062 static int
1063 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1064 {
1065         int             status;
1066
1067         status = ntohl(*p++);
1068         p = xdr_decode_wcc_data(p, res->fattr);
1069         if (status != 0)
1070                 return -nfs_stat_to_errno(status);
1071
1072         res->verf->verifier[0] = *p++;
1073         res->verf->verifier[1] = *p++;
1074         return 0;
1075 }
1076
1077 #ifdef CONFIG_NFS_V3_ACL
1078 /*
1079  * Decode GETACL reply
1080  */
1081 static int
1082 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1083                    struct nfs3_getaclres *res)
1084 {
1085         struct xdr_buf *buf = &req->rq_rcv_buf;
1086         int status = ntohl(*p++);
1087         struct posix_acl **acl;
1088         unsigned int *aclcnt;
1089         int err, base;
1090
1091         if (status != 0)
1092                 return -nfs_stat_to_errno(status);
1093         p = xdr_decode_post_op_attr(p, res->fattr);
1094         res->mask = ntohl(*p++);
1095         if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1096                 return -EINVAL;
1097         base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1098
1099         acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1100         aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1101         err = nfsacl_decode(buf, base, aclcnt, acl);
1102
1103         acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1104         aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1105         if (err > 0)
1106                 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1107         return (err > 0) ? 0 : err;
1108 }
1109
1110 /*
1111  * Decode setacl reply.
1112  */
1113 static int
1114 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1115 {
1116         int status = ntohl(*p++);
1117
1118         if (status)
1119                 return -nfs_stat_to_errno(status);
1120         xdr_decode_post_op_attr(p, fattr);
1121         return 0;
1122 }
1123 #endif  /* CONFIG_NFS_V3_ACL */
1124
1125 #define PROC(proc, argtype, restype, timer)                             \
1126 [NFS3PROC_##proc] = {                                                   \
1127         .p_proc      = NFS3PROC_##proc,                                 \
1128         .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,                 \
1129         .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                 \
1130         .p_arglen    = NFS3_##argtype##_sz,                             \
1131         .p_replen    = NFS3_##restype##_sz,                             \
1132         .p_timer     = timer,                                           \
1133         .p_statidx   = NFS3PROC_##proc,                                 \
1134         .p_name      = #proc,                                           \
1135         }
1136
1137 struct rpc_procinfo     nfs3_procedures[] = {
1138   PROC(GETATTR,         fhandle,        attrstat, 1),
1139   PROC(SETATTR,         sattrargs,      wccstat, 0),
1140   PROC(LOOKUP,          diropargs,      lookupres, 2),
1141   PROC(ACCESS,          accessargs,     accessres, 1),
1142   PROC(READLINK,        readlinkargs,   readlinkres, 3),
1143   PROC(READ,            readargs,       readres, 3),
1144   PROC(WRITE,           writeargs,      writeres, 4),
1145   PROC(CREATE,          createargs,     createres, 0),
1146   PROC(MKDIR,           mkdirargs,      createres, 0),
1147   PROC(SYMLINK,         symlinkargs,    createres, 0),
1148   PROC(MKNOD,           mknodargs,      createres, 0),
1149   PROC(REMOVE,          removeargs,     removeres, 0),
1150   PROC(RMDIR,           diropargs,      wccstat, 0),
1151   PROC(RENAME,          renameargs,     renameres, 0),
1152   PROC(LINK,            linkargs,       linkres, 0),
1153   PROC(READDIR,         readdirargs,    readdirres, 3),
1154   PROC(READDIRPLUS,     readdirargs,    readdirres, 3),
1155   PROC(FSSTAT,          fhandle,        fsstatres, 0),
1156   PROC(FSINFO,          fhandle,        fsinfores, 0),
1157   PROC(PATHCONF,        fhandle,        pathconfres, 0),
1158   PROC(COMMIT,          commitargs,     commitres, 5),
1159 };
1160
1161 struct rpc_version              nfs_version3 = {
1162         .number                 = 3,
1163         .nrprocs                = ARRAY_SIZE(nfs3_procedures),
1164         .procs                  = nfs3_procedures
1165 };
1166
1167 #ifdef CONFIG_NFS_V3_ACL
1168 static struct rpc_procinfo      nfs3_acl_procedures[] = {
1169         [ACLPROC3_GETACL] = {
1170                 .p_proc = ACLPROC3_GETACL,
1171                 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1172                 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1173                 .p_arglen = ACL3_getaclargs_sz,
1174                 .p_replen = ACL3_getaclres_sz,
1175                 .p_timer = 1,
1176                 .p_name = "GETACL",
1177         },
1178         [ACLPROC3_SETACL] = {
1179                 .p_proc = ACLPROC3_SETACL,
1180                 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1181                 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1182                 .p_arglen = ACL3_setaclargs_sz,
1183                 .p_replen = ACL3_setaclres_sz,
1184                 .p_timer = 0,
1185                 .p_name = "SETACL",
1186         },
1187 };
1188
1189 struct rpc_version              nfsacl_version3 = {
1190         .number                 = 3,
1191         .nrprocs                = sizeof(nfs3_acl_procedures)/
1192                                   sizeof(nfs3_acl_procedures[0]),
1193         .procs                  = nfs3_acl_procedures,
1194 };
1195 #endif  /* CONFIG_NFS_V3_ACL */