NFS: Use unsigned intermediates for manipulating header lengths (NFSv3 XDR)
[linux-2.6.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/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         req->rq_rcv_buf.flags |= XDRBUF_READ;
350         return 0;
351 }
352
353 /*
354  * Write arguments. Splice the buffer to be written into the iovec.
355  */
356 static int
357 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
358 {
359         struct xdr_buf *sndbuf = &req->rq_snd_buf;
360         u32 count = args->count;
361
362         p = xdr_encode_fhandle(p, args->fh);
363         p = xdr_encode_hyper(p, args->offset);
364         *p++ = htonl(count);
365         *p++ = htonl(args->stable);
366         *p++ = htonl(count);
367         sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
368
369         /* Copy the page array */
370         xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
371         sndbuf->flags |= XDRBUF_WRITE;
372         return 0;
373 }
374
375 /*
376  * Encode CREATE arguments
377  */
378 static int
379 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
380 {
381         p = xdr_encode_fhandle(p, args->fh);
382         p = xdr_encode_array(p, args->name, args->len);
383
384         *p++ = htonl(args->createmode);
385         if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
386                 *p++ = args->verifier[0];
387                 *p++ = args->verifier[1];
388         } else
389                 p = xdr_encode_sattr(p, args->sattr);
390
391         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
392         return 0;
393 }
394
395 /*
396  * Encode MKDIR arguments
397  */
398 static int
399 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
400 {
401         p = xdr_encode_fhandle(p, args->fh);
402         p = xdr_encode_array(p, args->name, args->len);
403         p = xdr_encode_sattr(p, args->sattr);
404         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
405         return 0;
406 }
407
408 /*
409  * Encode SYMLINK arguments
410  */
411 static int
412 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
413 {
414         p = xdr_encode_fhandle(p, args->fromfh);
415         p = xdr_encode_array(p, args->fromname, args->fromlen);
416         p = xdr_encode_sattr(p, args->sattr);
417         *p++ = htonl(args->pathlen);
418         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
419
420         /* Copy the page */
421         xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
422         return 0;
423 }
424
425 /*
426  * Encode MKNOD arguments
427  */
428 static int
429 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
430 {
431         p = xdr_encode_fhandle(p, args->fh);
432         p = xdr_encode_array(p, args->name, args->len);
433         *p++ = htonl(args->type);
434         p = xdr_encode_sattr(p, args->sattr);
435         if (args->type == NF3CHR || args->type == NF3BLK) {
436                 *p++ = htonl(MAJOR(args->rdev));
437                 *p++ = htonl(MINOR(args->rdev));
438         }
439
440         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
441         return 0;
442 }
443
444 /*
445  * Encode RENAME arguments
446  */
447 static int
448 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
449 {
450         p = xdr_encode_fhandle(p, args->fromfh);
451         p = xdr_encode_array(p, args->fromname, args->fromlen);
452         p = xdr_encode_fhandle(p, args->tofh);
453         p = xdr_encode_array(p, args->toname, args->tolen);
454         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
455         return 0;
456 }
457
458 /*
459  * Encode LINK arguments
460  */
461 static int
462 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
463 {
464         p = xdr_encode_fhandle(p, args->fromfh);
465         p = xdr_encode_fhandle(p, args->tofh);
466         p = xdr_encode_array(p, args->toname, args->tolen);
467         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
468         return 0;
469 }
470
471 /*
472  * Encode arguments to readdir call
473  */
474 static int
475 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
476 {
477         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
478         unsigned int replen;
479         u32 count = args->count;
480
481         p = xdr_encode_fhandle(p, args->fh);
482         p = xdr_encode_hyper(p, args->cookie);
483         *p++ = args->verf[0];
484         *p++ = args->verf[1];
485         if (args->plus) {
486                 /* readdirplus: need dircount + buffer size.
487                  * We just make sure we make dircount big enough */
488                 *p++ = htonl(count >> 3);
489         }
490         *p++ = htonl(count);
491         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
492
493         /* Inline the page array */
494         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
495         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
496         return 0;
497 }
498
499 /*
500  * Decode the result of a readdir call.
501  * We just check for syntactical correctness.
502  */
503 static int
504 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
505 {
506         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
507         struct kvec *iov = rcvbuf->head;
508         struct page **page;
509         size_t hdrlen;
510         u32 len, recvd, pglen;
511         int status, nr;
512         __be32 *entry, *end, *kaddr;
513
514         status = ntohl(*p++);
515         /* Decode post_op_attrs */
516         p = xdr_decode_post_op_attr(p, res->dir_attr);
517         if (status)
518                 return -nfs_stat_to_errno(status);
519         /* Decode verifier cookie */
520         if (res->verf) {
521                 res->verf[0] = *p++;
522                 res->verf[1] = *p++;
523         } else {
524                 p += 2;
525         }
526
527         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
528         if (iov->iov_len < hdrlen) {
529                 dprintk("NFS: READDIR reply header overflowed:"
530                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
531                 return -errno_NFSERR_IO;
532         } else if (iov->iov_len != hdrlen) {
533                 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
534                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
535         }
536
537         pglen = rcvbuf->page_len;
538         recvd = rcvbuf->len - hdrlen;
539         if (pglen > recvd)
540                 pglen = recvd;
541         page = rcvbuf->pages;
542         kaddr = p = kmap_atomic(*page, KM_USER0);
543         end = (__be32 *)((char *)p + pglen);
544         entry = p;
545         for (nr = 0; *p++; nr++) {
546                 if (p + 3 > end)
547                         goto short_pkt;
548                 p += 2;                         /* inode # */
549                 len = ntohl(*p++);              /* string length */
550                 p += XDR_QUADLEN(len) + 2;      /* name + cookie */
551                 if (len > NFS3_MAXNAMLEN) {
552                         dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
553                                                 len);
554                         goto err_unmap;
555                 }
556
557                 if (res->plus) {
558                         /* post_op_attr */
559                         if (p + 2 > end)
560                                 goto short_pkt;
561                         if (*p++) {
562                                 p += 21;
563                                 if (p + 1 > end)
564                                         goto short_pkt;
565                         }
566                         /* post_op_fh3 */
567                         if (*p++) {
568                                 if (p + 1 > end)
569                                         goto short_pkt;
570                                 len = ntohl(*p++);
571                                 if (len > NFS3_FHSIZE) {
572                                         dprintk("NFS: giant filehandle in "
573                                                 "readdir (len 0x%x)!\n", len);
574                                         goto err_unmap;
575                                 }
576                                 p += XDR_QUADLEN(len);
577                         }
578                 }
579
580                 if (p + 2 > end)
581                         goto short_pkt;
582                 entry = p;
583         }
584         if (!nr && (entry[0] != 0 || entry[1] == 0))
585                 goto short_pkt;
586  out:
587         kunmap_atomic(kaddr, KM_USER0);
588         return nr;
589  short_pkt:
590         entry[0] = entry[1] = 0;
591         /* truncate listing ? */
592         if (!nr) {
593                 dprintk("NFS: readdir reply truncated!\n");
594                 entry[1] = 1;
595         }
596         goto out;
597 err_unmap:
598         nr = -errno_NFSERR_IO;
599         goto out;
600 }
601
602 __be32 *
603 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
604 {
605         struct nfs_entry old = *entry;
606
607         if (!*p++) {
608                 if (!*p)
609                         return ERR_PTR(-EAGAIN);
610                 entry->eof = 1;
611                 return ERR_PTR(-EBADCOOKIE);
612         }
613
614         p = xdr_decode_hyper(p, &entry->ino);
615         entry->len  = ntohl(*p++);
616         entry->name = (const char *) p;
617         p += XDR_QUADLEN(entry->len);
618         entry->prev_cookie = entry->cookie;
619         p = xdr_decode_hyper(p, &entry->cookie);
620
621         if (plus) {
622                 entry->fattr->valid = 0;
623                 p = xdr_decode_post_op_attr(p, entry->fattr);
624                 /* In fact, a post_op_fh3: */
625                 if (*p++) {
626                         p = xdr_decode_fhandle(p, entry->fh);
627                         /* Ugh -- server reply was truncated */
628                         if (p == NULL) {
629                                 dprintk("NFS: FH truncated\n");
630                                 *entry = old;
631                                 return ERR_PTR(-EAGAIN);
632                         }
633                 } else
634                         memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
635         }
636
637         entry->eof = !p[0] && p[1];
638         return p;
639 }
640
641 /*
642  * Encode COMMIT arguments
643  */
644 static int
645 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
646 {
647         p = xdr_encode_fhandle(p, args->fh);
648         p = xdr_encode_hyper(p, args->offset);
649         *p++ = htonl(args->count);
650         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
651         return 0;
652 }
653
654 #ifdef CONFIG_NFS_V3_ACL
655 /*
656  * Encode GETACL arguments
657  */
658 static int
659 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
660                     struct nfs3_getaclargs *args)
661 {
662         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
663         unsigned int replen;
664
665         p = xdr_encode_fhandle(p, args->fh);
666         *p++ = htonl(args->mask);
667         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
668
669         if (args->mask & (NFS_ACL | NFS_DFACL)) {
670                 /* Inline the page array */
671                 replen = (RPC_REPHDRSIZE + auth->au_rslack +
672                           ACL3_getaclres_sz) << 2;
673                 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
674                                  NFSACL_MAXPAGES << PAGE_SHIFT);
675         }
676         return 0;
677 }
678
679 /*
680  * Encode SETACL arguments
681  */
682 static int
683 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
684                    struct nfs3_setaclargs *args)
685 {
686         struct xdr_buf *buf = &req->rq_snd_buf;
687         unsigned int base, len_in_head, len = nfsacl_size(
688                 (args->mask & NFS_ACL)   ? args->acl_access  : NULL,
689                 (args->mask & NFS_DFACL) ? args->acl_default : NULL);
690         int count, err;
691
692         p = xdr_encode_fhandle(p, NFS_FH(args->inode));
693         *p++ = htonl(args->mask);
694         base = (char *)p - (char *)buf->head->iov_base;
695         /* put as much of the acls into head as possible. */
696         len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
697         len -= len_in_head;
698         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
699
700         for (count = 0; (count << PAGE_SHIFT) < len; count++) {
701                 args->pages[count] = alloc_page(GFP_KERNEL);
702                 if (!args->pages[count]) {
703                         while (count)
704                                 __free_page(args->pages[--count]);
705                         return -ENOMEM;
706                 }
707         }
708         xdr_encode_pages(buf, args->pages, 0, len);
709
710         err = nfsacl_encode(buf, base, args->inode,
711                             (args->mask & NFS_ACL) ?
712                             args->acl_access : NULL, 1, 0);
713         if (err > 0)
714                 err = nfsacl_encode(buf, base + err, args->inode,
715                                     (args->mask & NFS_DFACL) ?
716                                     args->acl_default : NULL, 1,
717                                     NFS_ACL_DEFAULT);
718         return (err > 0) ? 0 : err;
719 }
720 #endif  /* CONFIG_NFS_V3_ACL */
721
722 /*
723  * NFS XDR decode functions
724  */
725
726 /*
727  * Decode attrstat reply.
728  */
729 static int
730 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
731 {
732         int     status;
733
734         if ((status = ntohl(*p++)))
735                 return -nfs_stat_to_errno(status);
736         xdr_decode_fattr(p, fattr);
737         return 0;
738 }
739
740 /*
741  * Decode status+wcc_data reply
742  * SATTR, REMOVE, RMDIR
743  */
744 static int
745 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
746 {
747         int     status;
748
749         if ((status = ntohl(*p++)))
750                 status = -nfs_stat_to_errno(status);
751         xdr_decode_wcc_data(p, fattr);
752         return status;
753 }
754
755 static int
756 nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
757 {
758         return nfs3_xdr_wccstat(req, p, &res->dir_attr);
759 }
760
761 /*
762  * Decode LOOKUP reply
763  */
764 static int
765 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
766 {
767         int     status;
768
769         if ((status = ntohl(*p++))) {
770                 status = -nfs_stat_to_errno(status);
771         } else {
772                 if (!(p = xdr_decode_fhandle(p, res->fh)))
773                         return -errno_NFSERR_IO;
774                 p = xdr_decode_post_op_attr(p, res->fattr);
775         }
776         xdr_decode_post_op_attr(p, res->dir_attr);
777         return status;
778 }
779
780 /*
781  * Decode ACCESS reply
782  */
783 static int
784 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
785 {
786         int     status = ntohl(*p++);
787
788         p = xdr_decode_post_op_attr(p, res->fattr);
789         if (status)
790                 return -nfs_stat_to_errno(status);
791         res->access = ntohl(*p++);
792         return 0;
793 }
794
795 static int
796 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
797 {
798         struct rpc_auth *auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
799         unsigned int replen;
800
801         p = xdr_encode_fhandle(p, args->fh);
802         req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
803
804         /* Inline the page array */
805         replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
806         xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
807         return 0;
808 }
809
810 /*
811  * Decode READLINK reply
812  */
813 static int
814 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
815 {
816         struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
817         struct kvec *iov = rcvbuf->head;
818         size_t hdrlen;
819         u32 len, recvd;
820         char    *kaddr;
821         int     status;
822
823         status = ntohl(*p++);
824         p = xdr_decode_post_op_attr(p, fattr);
825
826         if (status != 0)
827                 return -nfs_stat_to_errno(status);
828
829         /* Convert length of symlink */
830         len = ntohl(*p++);
831         if (len >= rcvbuf->page_len) {
832                 dprintk("nfs: server returned giant symlink!\n");
833                 return -ENAMETOOLONG;
834         }
835
836         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
837         if (iov->iov_len < hdrlen) {
838                 dprintk("NFS: READLINK reply header overflowed:"
839                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
840                 return -errno_NFSERR_IO;
841         } else if (iov->iov_len != hdrlen) {
842                 dprintk("NFS: READLINK header is short. "
843                         "iovec will be shifted.\n");
844                 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
845         }
846         recvd = req->rq_rcv_buf.len - hdrlen;
847         if (recvd < len) {
848                 dprintk("NFS: server cheating in readlink reply: "
849                                 "count %u > recvd %u\n", len, recvd);
850                 return -EIO;
851         }
852
853         /* NULL terminate the string we got */
854         kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
855         kaddr[len+rcvbuf->page_base] = '\0';
856         kunmap_atomic(kaddr, KM_USER0);
857         return 0;
858 }
859
860 /*
861  * Decode READ reply
862  */
863 static int
864 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
865 {
866         struct kvec *iov = req->rq_rcv_buf.head;
867         size_t hdrlen;
868         u32 count, ocount, recvd;
869         int status;
870
871         status = ntohl(*p++);
872         p = xdr_decode_post_op_attr(p, res->fattr);
873
874         if (status != 0)
875                 return -nfs_stat_to_errno(status);
876
877         /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
878          * in that it puts the count both in the res struct and in the
879          * opaque data count. */
880         count    = ntohl(*p++);
881         res->eof = ntohl(*p++);
882         ocount   = ntohl(*p++);
883
884         if (ocount != count) {
885                 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
886                 return -errno_NFSERR_IO;
887         }
888
889         hdrlen = (u8 *) p - (u8 *) iov->iov_base;
890         if (iov->iov_len < hdrlen) {
891                 dprintk("NFS: READ reply header overflowed:"
892                                 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
893                 return -errno_NFSERR_IO;
894         } else if (iov->iov_len != hdrlen) {
895                 dprintk("NFS: READ header is short. iovec will be shifted.\n");
896                 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
897         }
898
899         recvd = req->rq_rcv_buf.len - hdrlen;
900         if (count > recvd) {
901                 dprintk("NFS: server cheating in read reply: "
902                         "count %u > recvd %u\n", count, recvd);
903                 count = recvd;
904                 res->eof = 0;
905         }
906
907         if (count < res->count)
908                 res->count = count;
909
910         return count;
911 }
912
913 /*
914  * Decode WRITE response
915  */
916 static int
917 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
918 {
919         int     status;
920
921         status = ntohl(*p++);
922         p = xdr_decode_wcc_data(p, res->fattr);
923
924         if (status != 0)
925                 return -nfs_stat_to_errno(status);
926
927         res->count = ntohl(*p++);
928         res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
929         res->verf->verifier[0] = *p++;
930         res->verf->verifier[1] = *p++;
931
932         return res->count;
933 }
934
935 /*
936  * Decode a CREATE response
937  */
938 static int
939 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
940 {
941         int     status;
942
943         status = ntohl(*p++);
944         if (status == 0) {
945                 if (*p++) {
946                         if (!(p = xdr_decode_fhandle(p, res->fh)))
947                                 return -errno_NFSERR_IO;
948                         p = xdr_decode_post_op_attr(p, res->fattr);
949                 } else {
950                         memset(res->fh, 0, sizeof(*res->fh));
951                         /* Do decode post_op_attr but set it to NULL */
952                         p = xdr_decode_post_op_attr(p, res->fattr);
953                         res->fattr->valid = 0;
954                 }
955         } else {
956                 status = -nfs_stat_to_errno(status);
957         }
958         p = xdr_decode_wcc_data(p, res->dir_attr);
959         return status;
960 }
961
962 /*
963  * Decode RENAME reply
964  */
965 static int
966 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
967 {
968         int     status;
969
970         if ((status = ntohl(*p++)) != 0)
971                 status = -nfs_stat_to_errno(status);
972         p = xdr_decode_wcc_data(p, res->fromattr);
973         p = xdr_decode_wcc_data(p, res->toattr);
974         return status;
975 }
976
977 /*
978  * Decode LINK reply
979  */
980 static int
981 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
982 {
983         int     status;
984
985         if ((status = ntohl(*p++)) != 0)
986                 status = -nfs_stat_to_errno(status);
987         p = xdr_decode_post_op_attr(p, res->fattr);
988         p = xdr_decode_wcc_data(p, res->dir_attr);
989         return status;
990 }
991
992 /*
993  * Decode FSSTAT reply
994  */
995 static int
996 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
997 {
998         int             status;
999
1000         status = ntohl(*p++);
1001
1002         p = xdr_decode_post_op_attr(p, res->fattr);
1003         if (status != 0)
1004                 return -nfs_stat_to_errno(status);
1005
1006         p = xdr_decode_hyper(p, &res->tbytes);
1007         p = xdr_decode_hyper(p, &res->fbytes);
1008         p = xdr_decode_hyper(p, &res->abytes);
1009         p = xdr_decode_hyper(p, &res->tfiles);
1010         p = xdr_decode_hyper(p, &res->ffiles);
1011         p = xdr_decode_hyper(p, &res->afiles);
1012
1013         /* ignore invarsec */
1014         return 0;
1015 }
1016
1017 /*
1018  * Decode FSINFO reply
1019  */
1020 static int
1021 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1022 {
1023         int             status;
1024
1025         status = ntohl(*p++);
1026
1027         p = xdr_decode_post_op_attr(p, res->fattr);
1028         if (status != 0)
1029                 return -nfs_stat_to_errno(status);
1030
1031         res->rtmax  = ntohl(*p++);
1032         res->rtpref = ntohl(*p++);
1033         res->rtmult = ntohl(*p++);
1034         res->wtmax  = ntohl(*p++);
1035         res->wtpref = ntohl(*p++);
1036         res->wtmult = ntohl(*p++);
1037         res->dtpref = ntohl(*p++);
1038         p = xdr_decode_hyper(p, &res->maxfilesize);
1039
1040         /* ignore time_delta and properties */
1041         res->lease_time = 0;
1042         return 0;
1043 }
1044
1045 /*
1046  * Decode PATHCONF reply
1047  */
1048 static int
1049 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1050 {
1051         int             status;
1052
1053         status = ntohl(*p++);
1054
1055         p = xdr_decode_post_op_attr(p, res->fattr);
1056         if (status != 0)
1057                 return -nfs_stat_to_errno(status);
1058         res->max_link = ntohl(*p++);
1059         res->max_namelen = ntohl(*p++);
1060
1061         /* ignore remaining fields */
1062         return 0;
1063 }
1064
1065 /*
1066  * Decode COMMIT reply
1067  */
1068 static int
1069 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1070 {
1071         int             status;
1072
1073         status = ntohl(*p++);
1074         p = xdr_decode_wcc_data(p, res->fattr);
1075         if (status != 0)
1076                 return -nfs_stat_to_errno(status);
1077
1078         res->verf->verifier[0] = *p++;
1079         res->verf->verifier[1] = *p++;
1080         return 0;
1081 }
1082
1083 #ifdef CONFIG_NFS_V3_ACL
1084 /*
1085  * Decode GETACL reply
1086  */
1087 static int
1088 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1089                    struct nfs3_getaclres *res)
1090 {
1091         struct xdr_buf *buf = &req->rq_rcv_buf;
1092         int status = ntohl(*p++);
1093         struct posix_acl **acl;
1094         unsigned int *aclcnt;
1095         int err, base;
1096
1097         if (status != 0)
1098                 return -nfs_stat_to_errno(status);
1099         p = xdr_decode_post_op_attr(p, res->fattr);
1100         res->mask = ntohl(*p++);
1101         if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1102                 return -EINVAL;
1103         base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1104
1105         acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1106         aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1107         err = nfsacl_decode(buf, base, aclcnt, acl);
1108
1109         acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1110         aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1111         if (err > 0)
1112                 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1113         return (err > 0) ? 0 : err;
1114 }
1115
1116 /*
1117  * Decode setacl reply.
1118  */
1119 static int
1120 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1121 {
1122         int status = ntohl(*p++);
1123
1124         if (status)
1125                 return -nfs_stat_to_errno(status);
1126         xdr_decode_post_op_attr(p, fattr);
1127         return 0;
1128 }
1129 #endif  /* CONFIG_NFS_V3_ACL */
1130
1131 #define PROC(proc, argtype, restype, timer)                             \
1132 [NFS3PROC_##proc] = {                                                   \
1133         .p_proc      = NFS3PROC_##proc,                                 \
1134         .p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,                 \
1135         .p_decode    = (kxdrproc_t) nfs3_xdr_##restype,                 \
1136         .p_arglen    = NFS3_##argtype##_sz,                             \
1137         .p_replen    = NFS3_##restype##_sz,                             \
1138         .p_timer     = timer,                                           \
1139         .p_statidx   = NFS3PROC_##proc,                                 \
1140         .p_name      = #proc,                                           \
1141         }
1142
1143 struct rpc_procinfo     nfs3_procedures[] = {
1144   PROC(GETATTR,         fhandle,        attrstat, 1),
1145   PROC(SETATTR,         sattrargs,      wccstat, 0),
1146   PROC(LOOKUP,          diropargs,      lookupres, 2),
1147   PROC(ACCESS,          accessargs,     accessres, 1),
1148   PROC(READLINK,        readlinkargs,   readlinkres, 3),
1149   PROC(READ,            readargs,       readres, 3),
1150   PROC(WRITE,           writeargs,      writeres, 4),
1151   PROC(CREATE,          createargs,     createres, 0),
1152   PROC(MKDIR,           mkdirargs,      createres, 0),
1153   PROC(SYMLINK,         symlinkargs,    createres, 0),
1154   PROC(MKNOD,           mknodargs,      createres, 0),
1155   PROC(REMOVE,          removeargs,     removeres, 0),
1156   PROC(RMDIR,           diropargs,      wccstat, 0),
1157   PROC(RENAME,          renameargs,     renameres, 0),
1158   PROC(LINK,            linkargs,       linkres, 0),
1159   PROC(READDIR,         readdirargs,    readdirres, 3),
1160   PROC(READDIRPLUS,     readdirargs,    readdirres, 3),
1161   PROC(FSSTAT,          fhandle,        fsstatres, 0),
1162   PROC(FSINFO,          fhandle,        fsinfores, 0),
1163   PROC(PATHCONF,        fhandle,        pathconfres, 0),
1164   PROC(COMMIT,          commitargs,     commitres, 5),
1165 };
1166
1167 struct rpc_version              nfs_version3 = {
1168         .number                 = 3,
1169         .nrprocs                = ARRAY_SIZE(nfs3_procedures),
1170         .procs                  = nfs3_procedures
1171 };
1172
1173 #ifdef CONFIG_NFS_V3_ACL
1174 static struct rpc_procinfo      nfs3_acl_procedures[] = {
1175         [ACLPROC3_GETACL] = {
1176                 .p_proc = ACLPROC3_GETACL,
1177                 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1178                 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1179                 .p_arglen = ACL3_getaclargs_sz,
1180                 .p_replen = ACL3_getaclres_sz,
1181                 .p_timer = 1,
1182                 .p_name = "GETACL",
1183         },
1184         [ACLPROC3_SETACL] = {
1185                 .p_proc = ACLPROC3_SETACL,
1186                 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1187                 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1188                 .p_arglen = ACL3_setaclargs_sz,
1189                 .p_replen = ACL3_setaclres_sz,
1190                 .p_timer = 0,
1191                 .p_name = "SETACL",
1192         },
1193 };
1194
1195 struct rpc_version              nfsacl_version3 = {
1196         .number                 = 3,
1197         .nrprocs                = sizeof(nfs3_acl_procedures)/
1198                                   sizeof(nfs3_acl_procedures[0]),
1199         .procs                  = nfs3_acl_procedures,
1200 };
1201 #endif  /* CONFIG_NFS_V3_ACL */