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