nfsd: fix compose_entry_fh() failure exits
[pandora-kernel.git] / fs / nfsd / nfs3xdr.c
1 /*
2  * XDR support for nfsd/protocol version 3.
3  *
4  * Copyright (C) 1995, 1996, 1997 Olaf Kirch <okir@monad.swb.de>
5  *
6  * 2003-08-09 Jamie Lokier: Use htonl() for nanoseconds, not htons()!
7  */
8
9 #include <linux/namei.h>
10 #include "xdr3.h"
11 #include "auth.h"
12
13 #define NFSDDBG_FACILITY                NFSDDBG_XDR
14
15
16 /*
17  * Mapping of S_IF* types to NFS file types
18  */
19 static u32      nfs3_ftypes[] = {
20         NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
21         NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
22         NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
23         NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
24 };
25
26 /*
27  * XDR functions for basic NFS types
28  */
29 static __be32 *
30 encode_time3(__be32 *p, struct timespec *time)
31 {
32         *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
33         return p;
34 }
35
36 static __be32 *
37 decode_time3(__be32 *p, struct timespec *time)
38 {
39         time->tv_sec = ntohl(*p++);
40         time->tv_nsec = ntohl(*p++);
41         return p;
42 }
43
44 static __be32 *
45 decode_fh(__be32 *p, struct svc_fh *fhp)
46 {
47         unsigned int size;
48         fh_init(fhp, NFS3_FHSIZE);
49         size = ntohl(*p++);
50         if (size > NFS3_FHSIZE)
51                 return NULL;
52
53         memcpy(&fhp->fh_handle.fh_base, p, size);
54         fhp->fh_handle.fh_size = size;
55         return p + XDR_QUADLEN(size);
56 }
57
58 /* Helper function for NFSv3 ACL code */
59 __be32 *nfs3svc_decode_fh(__be32 *p, struct svc_fh *fhp)
60 {
61         return decode_fh(p, fhp);
62 }
63
64 static __be32 *
65 encode_fh(__be32 *p, struct svc_fh *fhp)
66 {
67         unsigned int size = fhp->fh_handle.fh_size;
68         *p++ = htonl(size);
69         if (size) p[XDR_QUADLEN(size)-1]=0;
70         memcpy(p, &fhp->fh_handle.fh_base, size);
71         return p + XDR_QUADLEN(size);
72 }
73
74 /*
75  * Decode a file name and make sure that the path contains
76  * no slashes or null bytes.
77  */
78 static __be32 *
79 decode_filename(__be32 *p, char **namp, unsigned int *lenp)
80 {
81         char            *name;
82         unsigned int    i;
83
84         if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
85                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
86                         if (*name == '\0' || *name == '/')
87                                 return NULL;
88                 }
89         }
90
91         return p;
92 }
93
94 static __be32 *
95 decode_sattr3(__be32 *p, struct iattr *iap)
96 {
97         u32     tmp;
98
99         iap->ia_valid = 0;
100
101         if (*p++) {
102                 iap->ia_valid |= ATTR_MODE;
103                 iap->ia_mode = ntohl(*p++);
104         }
105         if (*p++) {
106                 iap->ia_valid |= ATTR_UID;
107                 iap->ia_uid = ntohl(*p++);
108         }
109         if (*p++) {
110                 iap->ia_valid |= ATTR_GID;
111                 iap->ia_gid = ntohl(*p++);
112         }
113         if (*p++) {
114                 u64     newsize;
115
116                 iap->ia_valid |= ATTR_SIZE;
117                 p = xdr_decode_hyper(p, &newsize);
118                 if (newsize <= NFS_OFFSET_MAX)
119                         iap->ia_size = newsize;
120                 else
121                         iap->ia_size = NFS_OFFSET_MAX;
122         }
123         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
124                 iap->ia_valid |= ATTR_ATIME;
125         } else if (tmp == 2) {          /* set to client time */
126                 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
127                 iap->ia_atime.tv_sec = ntohl(*p++);
128                 iap->ia_atime.tv_nsec = ntohl(*p++);
129         }
130         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
131                 iap->ia_valid |= ATTR_MTIME;
132         } else if (tmp == 2) {          /* set to client time */
133                 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
134                 iap->ia_mtime.tv_sec = ntohl(*p++);
135                 iap->ia_mtime.tv_nsec = ntohl(*p++);
136         }
137         return p;
138 }
139
140 static __be32 *encode_fsid(__be32 *p, struct svc_fh *fhp)
141 {
142         u64 f;
143         switch(fsid_source(fhp)) {
144         default:
145         case FSIDSOURCE_DEV:
146                 p = xdr_encode_hyper(p, (u64)huge_encode_dev
147                                      (fhp->fh_dentry->d_inode->i_sb->s_dev));
148                 break;
149         case FSIDSOURCE_FSID:
150                 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
151                 break;
152         case FSIDSOURCE_UUID:
153                 f = ((u64*)fhp->fh_export->ex_uuid)[0];
154                 f ^= ((u64*)fhp->fh_export->ex_uuid)[1];
155                 p = xdr_encode_hyper(p, f);
156                 break;
157         }
158         return p;
159 }
160
161 static __be32 *
162 encode_fattr3(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp,
163               struct kstat *stat)
164 {
165         *p++ = htonl(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
166         *p++ = htonl((u32) stat->mode);
167         *p++ = htonl((u32) stat->nlink);
168         *p++ = htonl((u32) nfsd_ruid(rqstp, stat->uid));
169         *p++ = htonl((u32) nfsd_rgid(rqstp, stat->gid));
170         if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN) {
171                 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
172         } else {
173                 p = xdr_encode_hyper(p, (u64) stat->size);
174         }
175         p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
176         *p++ = htonl((u32) MAJOR(stat->rdev));
177         *p++ = htonl((u32) MINOR(stat->rdev));
178         p = encode_fsid(p, fhp);
179         p = xdr_encode_hyper(p, stat->ino);
180         p = encode_time3(p, &stat->atime);
181         p = encode_time3(p, &stat->mtime);
182         p = encode_time3(p, &stat->ctime);
183
184         return p;
185 }
186
187 static __be32 *
188 encode_saved_post_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
189 {
190         /* Attributes to follow */
191         *p++ = xdr_one;
192         return encode_fattr3(rqstp, p, fhp, &fhp->fh_post_attr);
193 }
194
195 /*
196  * Encode post-operation attributes.
197  * The inode may be NULL if the call failed because of a stale file
198  * handle. In this case, no attributes are returned.
199  */
200 static __be32 *
201 encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
202 {
203         struct dentry *dentry = fhp->fh_dentry;
204         if (dentry && dentry->d_inode) {
205                 int err;
206                 struct kstat stat;
207
208                 err = vfs_getattr(fhp->fh_export->ex_path.mnt, dentry, &stat);
209                 if (!err) {
210                         *p++ = xdr_one;         /* attributes follow */
211                         lease_get_mtime(dentry->d_inode, &stat.mtime);
212                         return encode_fattr3(rqstp, p, fhp, &stat);
213                 }
214         }
215         *p++ = xdr_zero;
216         return p;
217 }
218
219 /* Helper for NFSv3 ACLs */
220 __be32 *
221 nfs3svc_encode_post_op_attr(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
222 {
223         return encode_post_op_attr(rqstp, p, fhp);
224 }
225
226 /*
227  * Enocde weak cache consistency data
228  */
229 static __be32 *
230 encode_wcc_data(struct svc_rqst *rqstp, __be32 *p, struct svc_fh *fhp)
231 {
232         struct dentry   *dentry = fhp->fh_dentry;
233
234         if (dentry && dentry->d_inode && fhp->fh_post_saved) {
235                 if (fhp->fh_pre_saved) {
236                         *p++ = xdr_one;
237                         p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
238                         p = encode_time3(p, &fhp->fh_pre_mtime);
239                         p = encode_time3(p, &fhp->fh_pre_ctime);
240                 } else {
241                         *p++ = xdr_zero;
242                 }
243                 return encode_saved_post_attr(rqstp, p, fhp);
244         }
245         /* no pre- or post-attrs */
246         *p++ = xdr_zero;
247         return encode_post_op_attr(rqstp, p, fhp);
248 }
249
250 /*
251  * Fill in the post_op attr for the wcc data
252  */
253 void fill_post_wcc(struct svc_fh *fhp)
254 {
255         int err;
256
257         if (fhp->fh_post_saved)
258                 printk("nfsd: inode locked twice during operation.\n");
259
260         err = vfs_getattr(fhp->fh_export->ex_path.mnt, fhp->fh_dentry,
261                         &fhp->fh_post_attr);
262         fhp->fh_post_change = fhp->fh_dentry->d_inode->i_version;
263         if (err) {
264                 fhp->fh_post_saved = 0;
265                 /* Grab the ctime anyway - set_change_info might use it */
266                 fhp->fh_post_attr.ctime = fhp->fh_dentry->d_inode->i_ctime;
267         } else
268                 fhp->fh_post_saved = 1;
269 }
270
271 /*
272  * XDR decode functions
273  */
274 int
275 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, __be32 *p, struct nfsd_fhandle *args)
276 {
277         if (!(p = decode_fh(p, &args->fh)))
278                 return 0;
279         return xdr_argsize_check(rqstp, p);
280 }
281
282 int
283 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, __be32 *p,
284                                         struct nfsd3_sattrargs *args)
285 {
286         if (!(p = decode_fh(p, &args->fh)))
287                 return 0;
288         p = decode_sattr3(p, &args->attrs);
289
290         if ((args->check_guard = ntohl(*p++)) != 0) { 
291                 struct timespec time; 
292                 p = decode_time3(p, &time);
293                 args->guardtime = time.tv_sec;
294         }
295
296         return xdr_argsize_check(rqstp, p);
297 }
298
299 int
300 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, __be32 *p,
301                                         struct nfsd3_diropargs *args)
302 {
303         if (!(p = decode_fh(p, &args->fh))
304          || !(p = decode_filename(p, &args->name, &args->len)))
305                 return 0;
306
307         return xdr_argsize_check(rqstp, p);
308 }
309
310 int
311 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, __be32 *p,
312                                         struct nfsd3_accessargs *args)
313 {
314         if (!(p = decode_fh(p, &args->fh)))
315                 return 0;
316         args->access = ntohl(*p++);
317
318         return xdr_argsize_check(rqstp, p);
319 }
320
321 int
322 nfs3svc_decode_readargs(struct svc_rqst *rqstp, __be32 *p,
323                                         struct nfsd3_readargs *args)
324 {
325         unsigned int len;
326         int v,pn;
327         u32 max_blocksize = svc_max_payload(rqstp);
328
329         if (!(p = decode_fh(p, &args->fh)))
330                 return 0;
331         p = xdr_decode_hyper(p, &args->offset);
332
333         len = args->count = ntohl(*p++);
334
335         if (len > max_blocksize)
336                 len = max_blocksize;
337
338         /* set up the kvec */
339         v=0;
340         while (len > 0) {
341                 pn = rqstp->rq_resused++;
342                 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
343                 rqstp->rq_vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
344                 len -= rqstp->rq_vec[v].iov_len;
345                 v++;
346         }
347         args->vlen = v;
348         return xdr_argsize_check(rqstp, p);
349 }
350
351 int
352 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, __be32 *p,
353                                         struct nfsd3_writeargs *args)
354 {
355         unsigned int len, v, hdr, dlen;
356         u32 max_blocksize = svc_max_payload(rqstp);
357
358         if (!(p = decode_fh(p, &args->fh)))
359                 return 0;
360         p = xdr_decode_hyper(p, &args->offset);
361
362         args->count = ntohl(*p++);
363         args->stable = ntohl(*p++);
364         len = args->len = ntohl(*p++);
365         /*
366          * The count must equal the amount of data passed.
367          */
368         if (args->count != args->len)
369                 return 0;
370
371         /*
372          * Check to make sure that we got the right number of
373          * bytes.
374          */
375         hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
376         dlen = rqstp->rq_arg.head[0].iov_len + rqstp->rq_arg.page_len
377                 - hdr;
378         /*
379          * Round the length of the data which was specified up to
380          * the next multiple of XDR units and then compare that
381          * against the length which was actually received.
382          * Note that when RPCSEC/GSS (for example) is used, the
383          * data buffer can be padded so dlen might be larger
384          * than required.  It must never be smaller.
385          */
386         if (dlen < XDR_QUADLEN(len)*4)
387                 return 0;
388
389         if (args->count > max_blocksize) {
390                 args->count = max_blocksize;
391                 len = args->len = max_blocksize;
392         }
393         rqstp->rq_vec[0].iov_base = (void*)p;
394         rqstp->rq_vec[0].iov_len = rqstp->rq_arg.head[0].iov_len - hdr;
395         v = 0;
396         while (len > rqstp->rq_vec[v].iov_len) {
397                 len -= rqstp->rq_vec[v].iov_len;
398                 v++;
399                 rqstp->rq_vec[v].iov_base = page_address(rqstp->rq_pages[v]);
400                 rqstp->rq_vec[v].iov_len = PAGE_SIZE;
401         }
402         rqstp->rq_vec[v].iov_len = len;
403         args->vlen = v + 1;
404         return 1;
405 }
406
407 int
408 nfs3svc_decode_createargs(struct svc_rqst *rqstp, __be32 *p,
409                                         struct nfsd3_createargs *args)
410 {
411         if (!(p = decode_fh(p, &args->fh))
412          || !(p = decode_filename(p, &args->name, &args->len)))
413                 return 0;
414
415         switch (args->createmode = ntohl(*p++)) {
416         case NFS3_CREATE_UNCHECKED:
417         case NFS3_CREATE_GUARDED:
418                 p = decode_sattr3(p, &args->attrs);
419                 break;
420         case NFS3_CREATE_EXCLUSIVE:
421                 args->verf = p;
422                 p += 2;
423                 break;
424         default:
425                 return 0;
426         }
427
428         return xdr_argsize_check(rqstp, p);
429 }
430 int
431 nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, __be32 *p,
432                                         struct nfsd3_createargs *args)
433 {
434         if (!(p = decode_fh(p, &args->fh)) ||
435             !(p = decode_filename(p, &args->name, &args->len)))
436                 return 0;
437         p = decode_sattr3(p, &args->attrs);
438
439         return xdr_argsize_check(rqstp, p);
440 }
441
442 int
443 nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, __be32 *p,
444                                         struct nfsd3_symlinkargs *args)
445 {
446         unsigned int len, avail;
447         char *old, *new;
448         struct kvec *vec;
449
450         if (!(p = decode_fh(p, &args->ffh)) ||
451             !(p = decode_filename(p, &args->fname, &args->flen))
452                 )
453                 return 0;
454         p = decode_sattr3(p, &args->attrs);
455
456         /* now decode the pathname, which might be larger than the first page.
457          * As we have to check for nul's anyway, we copy it into a new page
458          * This page appears in the rq_res.pages list, but as pages_len is always
459          * 0, it won't get in the way
460          */
461         len = ntohl(*p++);
462         if (len == 0 || len > NFS3_MAXPATHLEN || len >= PAGE_SIZE)
463                 return 0;
464         args->tname = new =
465                 page_address(rqstp->rq_respages[rqstp->rq_resused++]);
466         args->tlen = len;
467         /* first copy and check from the first page */
468         old = (char*)p;
469         vec = &rqstp->rq_arg.head[0];
470         avail = vec->iov_len - (old - (char*)vec->iov_base);
471         while (len && avail && *old) {
472                 *new++ = *old++;
473                 len--;
474                 avail--;
475         }
476         /* now copy next page if there is one */
477         if (len && !avail && rqstp->rq_arg.page_len) {
478                 avail = rqstp->rq_arg.page_len;
479                 if (avail > PAGE_SIZE)
480                         avail = PAGE_SIZE;
481                 old = page_address(rqstp->rq_arg.pages[0]);
482         }
483         while (len && avail && *old) {
484                 *new++ = *old++;
485                 len--;
486                 avail--;
487         }
488         *new = '\0';
489         if (len)
490                 return 0;
491
492         return 1;
493 }
494
495 int
496 nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, __be32 *p,
497                                         struct nfsd3_mknodargs *args)
498 {
499         if (!(p = decode_fh(p, &args->fh))
500          || !(p = decode_filename(p, &args->name, &args->len)))
501                 return 0;
502
503         args->ftype = ntohl(*p++);
504
505         if (args->ftype == NF3BLK  || args->ftype == NF3CHR
506          || args->ftype == NF3SOCK || args->ftype == NF3FIFO)
507                 p = decode_sattr3(p, &args->attrs);
508
509         if (args->ftype == NF3BLK || args->ftype == NF3CHR) {
510                 args->major = ntohl(*p++);
511                 args->minor = ntohl(*p++);
512         }
513
514         return xdr_argsize_check(rqstp, p);
515 }
516
517 int
518 nfs3svc_decode_renameargs(struct svc_rqst *rqstp, __be32 *p,
519                                         struct nfsd3_renameargs *args)
520 {
521         if (!(p = decode_fh(p, &args->ffh))
522          || !(p = decode_filename(p, &args->fname, &args->flen))
523          || !(p = decode_fh(p, &args->tfh))
524          || !(p = decode_filename(p, &args->tname, &args->tlen)))
525                 return 0;
526
527         return xdr_argsize_check(rqstp, p);
528 }
529
530 int
531 nfs3svc_decode_readlinkargs(struct svc_rqst *rqstp, __be32 *p,
532                                         struct nfsd3_readlinkargs *args)
533 {
534         if (!(p = decode_fh(p, &args->fh)))
535                 return 0;
536         args->buffer =
537                 page_address(rqstp->rq_respages[rqstp->rq_resused++]);
538
539         return xdr_argsize_check(rqstp, p);
540 }
541
542 int
543 nfs3svc_decode_linkargs(struct svc_rqst *rqstp, __be32 *p,
544                                         struct nfsd3_linkargs *args)
545 {
546         if (!(p = decode_fh(p, &args->ffh))
547          || !(p = decode_fh(p, &args->tfh))
548          || !(p = decode_filename(p, &args->tname, &args->tlen)))
549                 return 0;
550
551         return xdr_argsize_check(rqstp, p);
552 }
553
554 int
555 nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, __be32 *p,
556                                         struct nfsd3_readdirargs *args)
557 {
558         if (!(p = decode_fh(p, &args->fh)))
559                 return 0;
560         p = xdr_decode_hyper(p, &args->cookie);
561         args->verf   = p; p += 2;
562         args->dircount = ~0;
563         args->count  = ntohl(*p++);
564
565         if (args->count > PAGE_SIZE)
566                 args->count = PAGE_SIZE;
567
568         args->buffer =
569                 page_address(rqstp->rq_respages[rqstp->rq_resused++]);
570
571         return xdr_argsize_check(rqstp, p);
572 }
573
574 int
575 nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, __be32 *p,
576                                         struct nfsd3_readdirargs *args)
577 {
578         int len, pn;
579         u32 max_blocksize = svc_max_payload(rqstp);
580
581         if (!(p = decode_fh(p, &args->fh)))
582                 return 0;
583         p = xdr_decode_hyper(p, &args->cookie);
584         args->verf     = p; p += 2;
585         args->dircount = ntohl(*p++);
586         args->count    = ntohl(*p++);
587
588         len = (args->count > max_blocksize) ? max_blocksize :
589                                                   args->count;
590         args->count = len;
591
592         while (len > 0) {
593                 pn = rqstp->rq_resused++;
594                 if (!args->buffer)
595                         args->buffer = page_address(rqstp->rq_respages[pn]);
596                 len -= PAGE_SIZE;
597         }
598
599         return xdr_argsize_check(rqstp, p);
600 }
601
602 int
603 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, __be32 *p,
604                                         struct nfsd3_commitargs *args)
605 {
606         if (!(p = decode_fh(p, &args->fh)))
607                 return 0;
608         p = xdr_decode_hyper(p, &args->offset);
609         args->count = ntohl(*p++);
610
611         return xdr_argsize_check(rqstp, p);
612 }
613
614 /*
615  * XDR encode functions
616  */
617 /*
618  * There must be an encoding function for void results so svc_process
619  * will work properly.
620  */
621 int
622 nfs3svc_encode_voidres(struct svc_rqst *rqstp, __be32 *p, void *dummy)
623 {
624         return xdr_ressize_check(rqstp, p);
625 }
626
627 /* GETATTR */
628 int
629 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, __be32 *p,
630                                         struct nfsd3_attrstat *resp)
631 {
632         if (resp->status == 0) {
633                 lease_get_mtime(resp->fh.fh_dentry->d_inode,
634                                 &resp->stat.mtime);
635                 p = encode_fattr3(rqstp, p, &resp->fh, &resp->stat);
636         }
637         return xdr_ressize_check(rqstp, p);
638 }
639
640 /* SETATTR, REMOVE, RMDIR */
641 int
642 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, __be32 *p,
643                                         struct nfsd3_attrstat *resp)
644 {
645         p = encode_wcc_data(rqstp, p, &resp->fh);
646         return xdr_ressize_check(rqstp, p);
647 }
648
649 /* LOOKUP */
650 int
651 nfs3svc_encode_diropres(struct svc_rqst *rqstp, __be32 *p,
652                                         struct nfsd3_diropres *resp)
653 {
654         if (resp->status == 0) {
655                 p = encode_fh(p, &resp->fh);
656                 p = encode_post_op_attr(rqstp, p, &resp->fh);
657         }
658         p = encode_post_op_attr(rqstp, p, &resp->dirfh);
659         return xdr_ressize_check(rqstp, p);
660 }
661
662 /* ACCESS */
663 int
664 nfs3svc_encode_accessres(struct svc_rqst *rqstp, __be32 *p,
665                                         struct nfsd3_accessres *resp)
666 {
667         p = encode_post_op_attr(rqstp, p, &resp->fh);
668         if (resp->status == 0)
669                 *p++ = htonl(resp->access);
670         return xdr_ressize_check(rqstp, p);
671 }
672
673 /* READLINK */
674 int
675 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, __be32 *p,
676                                         struct nfsd3_readlinkres *resp)
677 {
678         p = encode_post_op_attr(rqstp, p, &resp->fh);
679         if (resp->status == 0) {
680                 *p++ = htonl(resp->len);
681                 xdr_ressize_check(rqstp, p);
682                 rqstp->rq_res.page_len = resp->len;
683                 if (resp->len & 3) {
684                         /* need to pad the tail */
685                         rqstp->rq_res.tail[0].iov_base = p;
686                         *p = 0;
687                         rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
688                 }
689                 return 1;
690         } else
691                 return xdr_ressize_check(rqstp, p);
692 }
693
694 /* READ */
695 int
696 nfs3svc_encode_readres(struct svc_rqst *rqstp, __be32 *p,
697                                         struct nfsd3_readres *resp)
698 {
699         p = encode_post_op_attr(rqstp, p, &resp->fh);
700         if (resp->status == 0) {
701                 *p++ = htonl(resp->count);
702                 *p++ = htonl(resp->eof);
703                 *p++ = htonl(resp->count);      /* xdr opaque count */
704                 xdr_ressize_check(rqstp, p);
705                 /* now update rqstp->rq_res to reflect data as well */
706                 rqstp->rq_res.page_len = resp->count;
707                 if (resp->count & 3) {
708                         /* need to pad the tail */
709                         rqstp->rq_res.tail[0].iov_base = p;
710                         *p = 0;
711                         rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
712                 }
713                 return 1;
714         } else
715                 return xdr_ressize_check(rqstp, p);
716 }
717
718 /* WRITE */
719 int
720 nfs3svc_encode_writeres(struct svc_rqst *rqstp, __be32 *p,
721                                         struct nfsd3_writeres *resp)
722 {
723         p = encode_wcc_data(rqstp, p, &resp->fh);
724         if (resp->status == 0) {
725                 *p++ = htonl(resp->count);
726                 *p++ = htonl(resp->committed);
727                 *p++ = htonl(nfssvc_boot.tv_sec);
728                 *p++ = htonl(nfssvc_boot.tv_usec);
729         }
730         return xdr_ressize_check(rqstp, p);
731 }
732
733 /* CREATE, MKDIR, SYMLINK, MKNOD */
734 int
735 nfs3svc_encode_createres(struct svc_rqst *rqstp, __be32 *p,
736                                         struct nfsd3_diropres *resp)
737 {
738         if (resp->status == 0) {
739                 *p++ = xdr_one;
740                 p = encode_fh(p, &resp->fh);
741                 p = encode_post_op_attr(rqstp, p, &resp->fh);
742         }
743         p = encode_wcc_data(rqstp, p, &resp->dirfh);
744         return xdr_ressize_check(rqstp, p);
745 }
746
747 /* RENAME */
748 int
749 nfs3svc_encode_renameres(struct svc_rqst *rqstp, __be32 *p,
750                                         struct nfsd3_renameres *resp)
751 {
752         p = encode_wcc_data(rqstp, p, &resp->ffh);
753         p = encode_wcc_data(rqstp, p, &resp->tfh);
754         return xdr_ressize_check(rqstp, p);
755 }
756
757 /* LINK */
758 int
759 nfs3svc_encode_linkres(struct svc_rqst *rqstp, __be32 *p,
760                                         struct nfsd3_linkres *resp)
761 {
762         p = encode_post_op_attr(rqstp, p, &resp->fh);
763         p = encode_wcc_data(rqstp, p, &resp->tfh);
764         return xdr_ressize_check(rqstp, p);
765 }
766
767 /* READDIR */
768 int
769 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, __be32 *p,
770                                         struct nfsd3_readdirres *resp)
771 {
772         p = encode_post_op_attr(rqstp, p, &resp->fh);
773
774         if (resp->status == 0) {
775                 /* stupid readdir cookie */
776                 memcpy(p, resp->verf, 8); p += 2;
777                 xdr_ressize_check(rqstp, p);
778                 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
779                         return 1; /*No room for trailer */
780                 rqstp->rq_res.page_len = (resp->count) << 2;
781
782                 /* add the 'tail' to the end of the 'head' page - page 0. */
783                 rqstp->rq_res.tail[0].iov_base = p;
784                 *p++ = 0;               /* no more entries */
785                 *p++ = htonl(resp->common.err == nfserr_eof);
786                 rqstp->rq_res.tail[0].iov_len = 2<<2;
787                 return 1;
788         } else
789                 return xdr_ressize_check(rqstp, p);
790 }
791
792 static __be32 *
793 encode_entry_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name,
794              int namlen, u64 ino)
795 {
796         *p++ = xdr_one;                          /* mark entry present */
797         p    = xdr_encode_hyper(p, ino);         /* file id */
798         p    = xdr_encode_array(p, name, namlen);/* name length & name */
799
800         cd->offset = p;                         /* remember pointer */
801         p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */
802
803         return p;
804 }
805
806 static __be32
807 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
808                 const char *name, int namlen)
809 {
810         struct svc_export       *exp;
811         struct dentry           *dparent, *dchild;
812         __be32 rv = nfserr_noent;
813
814         dparent = cd->fh.fh_dentry;
815         exp  = cd->fh.fh_export;
816
817         if (isdotent(name, namlen)) {
818                 if (namlen == 2) {
819                         dchild = dget_parent(dparent);
820                         /* filesystem root - cannot return filehandle for ".." */
821                         if (dchild == dparent)
822                                 goto out;
823                 } else
824                         dchild = dget(dparent);
825         } else
826                 dchild = lookup_one_len(name, dparent, namlen);
827         if (IS_ERR(dchild))
828                 return rv;
829         if (d_mountpoint(dchild))
830                 goto out;
831         if (!dchild->d_inode)
832                 goto out;
833         rv = fh_compose(fhp, exp, dchild, &cd->fh);
834 out:
835         dput(dchild);
836         return rv;
837 }
838
839 static __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
840 {
841         struct svc_fh   fh;
842         __be32 err;
843
844         fh_init(&fh, NFS3_FHSIZE);
845         err = compose_entry_fh(cd, &fh, name, namlen);
846         if (err) {
847                 *p++ = 0;
848                 *p++ = 0;
849                 goto out;
850         }
851         p = encode_post_op_attr(cd->rqstp, p, &fh);
852         *p++ = xdr_one;                 /* yes, a file handle follows */
853         p = encode_fh(p, &fh);
854 out:
855         fh_put(&fh);
856         return p;
857 }
858
859 /*
860  * Encode a directory entry. This one works for both normal readdir
861  * and readdirplus.
862  * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
863  * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
864  * 
865  * The readdirplus baggage is 1+21 words for post_op_attr, plus the
866  * file handle.
867  */
868
869 #define NFS3_ENTRY_BAGGAGE      (2 + 1 + 2 + 1)
870 #define NFS3_ENTRYPLUS_BAGGAGE  (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
871 static int
872 encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
873              loff_t offset, u64 ino, unsigned int d_type, int plus)
874 {
875         struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
876                                                         common);
877         __be32          *p = cd->buffer;
878         caddr_t         curr_page_addr = NULL;
879         int             pn;             /* current page number */
880         int             slen;           /* string (name) length */
881         int             elen;           /* estimated entry length in words */
882         int             num_entry_words = 0;    /* actual number of words */
883
884         if (cd->offset) {
885                 u64 offset64 = offset;
886
887                 if (unlikely(cd->offset1)) {
888                         /* we ended up with offset on a page boundary */
889                         *cd->offset = htonl(offset64 >> 32);
890                         *cd->offset1 = htonl(offset64 & 0xffffffff);
891                         cd->offset1 = NULL;
892                 } else {
893                         xdr_encode_hyper(cd->offset, offset64);
894                 }
895         }
896
897         /*
898         dprintk("encode_entry(%.*s @%ld%s)\n",
899                 namlen, name, (long) offset, plus? " plus" : "");
900          */
901
902         /* truncate filename if too long */
903         if (namlen > NFS3_MAXNAMLEN)
904                 namlen = NFS3_MAXNAMLEN;
905
906         slen = XDR_QUADLEN(namlen);
907         elen = slen + NFS3_ENTRY_BAGGAGE
908                 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
909
910         if (cd->buflen < elen) {
911                 cd->common.err = nfserr_toosmall;
912                 return -EINVAL;
913         }
914
915         /* determine which page in rq_respages[] we are currently filling */
916         for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
917                 curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
918
919                 if (((caddr_t)cd->buffer >= curr_page_addr) &&
920                     ((caddr_t)cd->buffer <  curr_page_addr + PAGE_SIZE))
921                         break;
922         }
923
924         if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
925                 /* encode entry in current page */
926
927                 p = encode_entry_baggage(cd, p, name, namlen, ino);
928
929                 if (plus)
930                         p = encode_entryplus_baggage(cd, p, name, namlen);
931                 num_entry_words = p - cd->buffer;
932         } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
933                 /* temporarily encode entry into next page, then move back to
934                  * current and next page in rq_respages[] */
935                 __be32 *p1, *tmp;
936                 int len1, len2;
937
938                 /* grab next page for temporary storage of entry */
939                 p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
940
941                 p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
942
943                 if (plus)
944                         p1 = encode_entryplus_baggage(cd, p1, name, namlen);
945
946                 /* determine entry word length and lengths to go in pages */
947                 num_entry_words = p1 - tmp;
948                 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
949                 if ((num_entry_words << 2) < len1) {
950                         /* the actual number of words in the entry is less
951                          * than elen and can still fit in the current page
952                          */
953                         memmove(p, tmp, num_entry_words << 2);
954                         p += num_entry_words;
955
956                         /* update offset */
957                         cd->offset = cd->buffer + (cd->offset - tmp);
958                 } else {
959                         unsigned int offset_r = (cd->offset - tmp) << 2;
960
961                         /* update pointer to offset location.
962                          * This is a 64bit quantity, so we need to
963                          * deal with 3 cases:
964                          *  -   entirely in first page
965                          *  -   entirely in second page
966                          *  -   4 bytes in each page
967                          */
968                         if (offset_r + 8 <= len1) {
969                                 cd->offset = p + (cd->offset - tmp);
970                         } else if (offset_r >= len1) {
971                                 cd->offset -= len1 >> 2;
972                         } else {
973                                 /* sitting on the fence */
974                                 BUG_ON(offset_r != len1 - 4);
975                                 cd->offset = p + (cd->offset - tmp);
976                                 cd->offset1 = tmp;
977                         }
978
979                         len2 = (num_entry_words << 2) - len1;
980
981                         /* move from temp page to current and next pages */
982                         memmove(p, tmp, len1);
983                         memmove(tmp, (caddr_t)tmp+len1, len2);
984
985                         p = tmp + (len2 >> 2);
986                 }
987         }
988         else {
989                 cd->common.err = nfserr_toosmall;
990                 return -EINVAL;
991         }
992
993         cd->buflen -= num_entry_words;
994         cd->buffer = p;
995         cd->common.err = nfs_ok;
996         return 0;
997
998 }
999
1000 int
1001 nfs3svc_encode_entry(void *cd, const char *name,
1002                      int namlen, loff_t offset, u64 ino, unsigned int d_type)
1003 {
1004         return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
1005 }
1006
1007 int
1008 nfs3svc_encode_entry_plus(void *cd, const char *name,
1009                           int namlen, loff_t offset, u64 ino,
1010                           unsigned int d_type)
1011 {
1012         return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
1013 }
1014
1015 /* FSSTAT */
1016 int
1017 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p,
1018                                         struct nfsd3_fsstatres *resp)
1019 {
1020         struct kstatfs  *s = &resp->stats;
1021         u64             bs = s->f_bsize;
1022
1023         *p++ = xdr_zero;        /* no post_op_attr */
1024
1025         if (resp->status == 0) {
1026                 p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
1027                 p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
1028                 p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
1029                 p = xdr_encode_hyper(p, s->f_files);    /* total inodes */
1030                 p = xdr_encode_hyper(p, s->f_ffree);    /* free inodes */
1031                 p = xdr_encode_hyper(p, s->f_ffree);    /* user available inodes */
1032                 *p++ = htonl(resp->invarsec);   /* mean unchanged time */
1033         }
1034         return xdr_ressize_check(rqstp, p);
1035 }
1036
1037 /* FSINFO */
1038 int
1039 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p,
1040                                         struct nfsd3_fsinfores *resp)
1041 {
1042         *p++ = xdr_zero;        /* no post_op_attr */
1043
1044         if (resp->status == 0) {
1045                 *p++ = htonl(resp->f_rtmax);
1046                 *p++ = htonl(resp->f_rtpref);
1047                 *p++ = htonl(resp->f_rtmult);
1048                 *p++ = htonl(resp->f_wtmax);
1049                 *p++ = htonl(resp->f_wtpref);
1050                 *p++ = htonl(resp->f_wtmult);
1051                 *p++ = htonl(resp->f_dtpref);
1052                 p = xdr_encode_hyper(p, resp->f_maxfilesize);
1053                 *p++ = xdr_one;
1054                 *p++ = xdr_zero;
1055                 *p++ = htonl(resp->f_properties);
1056         }
1057
1058         return xdr_ressize_check(rqstp, p);
1059 }
1060
1061 /* PATHCONF */
1062 int
1063 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p,
1064                                         struct nfsd3_pathconfres *resp)
1065 {
1066         *p++ = xdr_zero;        /* no post_op_attr */
1067
1068         if (resp->status == 0) {
1069                 *p++ = htonl(resp->p_link_max);
1070                 *p++ = htonl(resp->p_name_max);
1071                 *p++ = htonl(resp->p_no_trunc);
1072                 *p++ = htonl(resp->p_chown_restricted);
1073                 *p++ = htonl(resp->p_case_insensitive);
1074                 *p++ = htonl(resp->p_case_preserving);
1075         }
1076
1077         return xdr_ressize_check(rqstp, p);
1078 }
1079
1080 /* COMMIT */
1081 int
1082 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
1083                                         struct nfsd3_commitres *resp)
1084 {
1085         p = encode_wcc_data(rqstp, p, &resp->fh);
1086         /* Write verifier */
1087         if (resp->status == 0) {
1088                 *p++ = htonl(nfssvc_boot.tv_sec);
1089                 *p++ = htonl(nfssvc_boot.tv_usec);
1090         }
1091         return xdr_ressize_check(rqstp, p);
1092 }
1093
1094 /*
1095  * XDR release functions
1096  */
1097 int
1098 nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
1099                                         struct nfsd3_attrstat *resp)
1100 {
1101         fh_put(&resp->fh);
1102         return 1;
1103 }
1104
1105 int
1106 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p,
1107                                         struct nfsd3_fhandle_pair *resp)
1108 {
1109         fh_put(&resp->fh1);
1110         fh_put(&resp->fh2);
1111         return 1;
1112 }