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