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