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