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