]> git.karo-electronics.de Git - mv-sheeva.git/blob - fs/nfsd/nfs3xdr.c
thp: fix page_referenced to modify mapcount/vm_flags only if page is found
[mv-sheeva.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 aswell */
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 int
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         int rv = 0;
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                         if (dchild == dparent) {
821                                 /* filesystem root - cannot return filehandle for ".." */
822                                 dput(dchild);
823                                 return -ENOENT;
824                         }
825                 } else
826                         dchild = dget(dparent);
827         } else
828                 dchild = lookup_one_len(name, dparent, namlen);
829         if (IS_ERR(dchild))
830                 return -ENOENT;
831         rv = -ENOENT;
832         if (d_mountpoint(dchild))
833                 goto out;
834         rv = fh_compose(fhp, exp, dchild, &cd->fh);
835         if (rv)
836                 goto out;
837         if (!dchild->d_inode)
838                 goto out;
839         rv = 0;
840 out:
841         dput(dchild);
842         return rv;
843 }
844
845 __be32 *encode_entryplus_baggage(struct nfsd3_readdirres *cd, __be32 *p, const char *name, int namlen)
846 {
847         struct svc_fh   fh;
848         int err;
849
850         fh_init(&fh, NFS3_FHSIZE);
851         err = compose_entry_fh(cd, &fh, name, namlen);
852         if (err) {
853                 *p++ = 0;
854                 *p++ = 0;
855                 goto out;
856         }
857         p = encode_post_op_attr(cd->rqstp, p, &fh);
858         *p++ = xdr_one;                 /* yes, a file handle follows */
859         p = encode_fh(p, &fh);
860 out:
861         fh_put(&fh);
862         return p;
863 }
864
865 /*
866  * Encode a directory entry. This one works for both normal readdir
867  * and readdirplus.
868  * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
869  * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
870  * 
871  * The readdirplus baggage is 1+21 words for post_op_attr, plus the
872  * file handle.
873  */
874
875 #define NFS3_ENTRY_BAGGAGE      (2 + 1 + 2 + 1)
876 #define NFS3_ENTRYPLUS_BAGGAGE  (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
877 static int
878 encode_entry(struct readdir_cd *ccd, const char *name, int namlen,
879              loff_t offset, u64 ino, unsigned int d_type, int plus)
880 {
881         struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
882                                                         common);
883         __be32          *p = cd->buffer;
884         caddr_t         curr_page_addr = NULL;
885         int             pn;             /* current page number */
886         int             slen;           /* string (name) length */
887         int             elen;           /* estimated entry length in words */
888         int             num_entry_words = 0;    /* actual number of words */
889
890         if (cd->offset) {
891                 u64 offset64 = offset;
892
893                 if (unlikely(cd->offset1)) {
894                         /* we ended up with offset on a page boundary */
895                         *cd->offset = htonl(offset64 >> 32);
896                         *cd->offset1 = htonl(offset64 & 0xffffffff);
897                         cd->offset1 = NULL;
898                 } else {
899                         xdr_encode_hyper(cd->offset, offset64);
900                 }
901         }
902
903         /*
904         dprintk("encode_entry(%.*s @%ld%s)\n",
905                 namlen, name, (long) offset, plus? " plus" : "");
906          */
907
908         /* truncate filename if too long */
909         if (namlen > NFS3_MAXNAMLEN)
910                 namlen = NFS3_MAXNAMLEN;
911
912         slen = XDR_QUADLEN(namlen);
913         elen = slen + NFS3_ENTRY_BAGGAGE
914                 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
915
916         if (cd->buflen < elen) {
917                 cd->common.err = nfserr_toosmall;
918                 return -EINVAL;
919         }
920
921         /* determine which page in rq_respages[] we are currently filling */
922         for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
923                 curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
924
925                 if (((caddr_t)cd->buffer >= curr_page_addr) &&
926                     ((caddr_t)cd->buffer <  curr_page_addr + PAGE_SIZE))
927                         break;
928         }
929
930         if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
931                 /* encode entry in current page */
932
933                 p = encode_entry_baggage(cd, p, name, namlen, ino);
934
935                 if (plus)
936                         p = encode_entryplus_baggage(cd, p, name, namlen);
937                 num_entry_words = p - cd->buffer;
938         } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
939                 /* temporarily encode entry into next page, then move back to
940                  * current and next page in rq_respages[] */
941                 __be32 *p1, *tmp;
942                 int len1, len2;
943
944                 /* grab next page for temporary storage of entry */
945                 p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
946
947                 p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
948
949                 if (plus)
950                         p1 = encode_entryplus_baggage(cd, p1, name, namlen);
951
952                 /* determine entry word length and lengths to go in pages */
953                 num_entry_words = p1 - tmp;
954                 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
955                 if ((num_entry_words << 2) < len1) {
956                         /* the actual number of words in the entry is less
957                          * than elen and can still fit in the current page
958                          */
959                         memmove(p, tmp, num_entry_words << 2);
960                         p += num_entry_words;
961
962                         /* update offset */
963                         cd->offset = cd->buffer + (cd->offset - tmp);
964                 } else {
965                         unsigned int offset_r = (cd->offset - tmp) << 2;
966
967                         /* update pointer to offset location.
968                          * This is a 64bit quantity, so we need to
969                          * deal with 3 cases:
970                          *  -   entirely in first page
971                          *  -   entirely in second page
972                          *  -   4 bytes in each page
973                          */
974                         if (offset_r + 8 <= len1) {
975                                 cd->offset = p + (cd->offset - tmp);
976                         } else if (offset_r >= len1) {
977                                 cd->offset -= len1 >> 2;
978                         } else {
979                                 /* sitting on the fence */
980                                 BUG_ON(offset_r != len1 - 4);
981                                 cd->offset = p + (cd->offset - tmp);
982                                 cd->offset1 = tmp;
983                         }
984
985                         len2 = (num_entry_words << 2) - len1;
986
987                         /* move from temp page to current and next pages */
988                         memmove(p, tmp, len1);
989                         memmove(tmp, (caddr_t)tmp+len1, len2);
990
991                         p = tmp + (len2 >> 2);
992                 }
993         }
994         else {
995                 cd->common.err = nfserr_toosmall;
996                 return -EINVAL;
997         }
998
999         cd->buflen -= num_entry_words;
1000         cd->buffer = p;
1001         cd->common.err = nfs_ok;
1002         return 0;
1003
1004 }
1005
1006 int
1007 nfs3svc_encode_entry(void *cd, const char *name,
1008                      int namlen, loff_t offset, u64 ino, unsigned int d_type)
1009 {
1010         return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
1011 }
1012
1013 int
1014 nfs3svc_encode_entry_plus(void *cd, const char *name,
1015                           int namlen, loff_t offset, u64 ino,
1016                           unsigned int d_type)
1017 {
1018         return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
1019 }
1020
1021 /* FSSTAT */
1022 int
1023 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, __be32 *p,
1024                                         struct nfsd3_fsstatres *resp)
1025 {
1026         struct kstatfs  *s = &resp->stats;
1027         u64             bs = s->f_bsize;
1028
1029         *p++ = xdr_zero;        /* no post_op_attr */
1030
1031         if (resp->status == 0) {
1032                 p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
1033                 p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
1034                 p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
1035                 p = xdr_encode_hyper(p, s->f_files);    /* total inodes */
1036                 p = xdr_encode_hyper(p, s->f_ffree);    /* free inodes */
1037                 p = xdr_encode_hyper(p, s->f_ffree);    /* user available inodes */
1038                 *p++ = htonl(resp->invarsec);   /* mean unchanged time */
1039         }
1040         return xdr_ressize_check(rqstp, p);
1041 }
1042
1043 /* FSINFO */
1044 int
1045 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, __be32 *p,
1046                                         struct nfsd3_fsinfores *resp)
1047 {
1048         *p++ = xdr_zero;        /* no post_op_attr */
1049
1050         if (resp->status == 0) {
1051                 *p++ = htonl(resp->f_rtmax);
1052                 *p++ = htonl(resp->f_rtpref);
1053                 *p++ = htonl(resp->f_rtmult);
1054                 *p++ = htonl(resp->f_wtmax);
1055                 *p++ = htonl(resp->f_wtpref);
1056                 *p++ = htonl(resp->f_wtmult);
1057                 *p++ = htonl(resp->f_dtpref);
1058                 p = xdr_encode_hyper(p, resp->f_maxfilesize);
1059                 *p++ = xdr_one;
1060                 *p++ = xdr_zero;
1061                 *p++ = htonl(resp->f_properties);
1062         }
1063
1064         return xdr_ressize_check(rqstp, p);
1065 }
1066
1067 /* PATHCONF */
1068 int
1069 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, __be32 *p,
1070                                         struct nfsd3_pathconfres *resp)
1071 {
1072         *p++ = xdr_zero;        /* no post_op_attr */
1073
1074         if (resp->status == 0) {
1075                 *p++ = htonl(resp->p_link_max);
1076                 *p++ = htonl(resp->p_name_max);
1077                 *p++ = htonl(resp->p_no_trunc);
1078                 *p++ = htonl(resp->p_chown_restricted);
1079                 *p++ = htonl(resp->p_case_insensitive);
1080                 *p++ = htonl(resp->p_case_preserving);
1081         }
1082
1083         return xdr_ressize_check(rqstp, p);
1084 }
1085
1086 /* COMMIT */
1087 int
1088 nfs3svc_encode_commitres(struct svc_rqst *rqstp, __be32 *p,
1089                                         struct nfsd3_commitres *resp)
1090 {
1091         p = encode_wcc_data(rqstp, p, &resp->fh);
1092         /* Write verifier */
1093         if (resp->status == 0) {
1094                 *p++ = htonl(nfssvc_boot.tv_sec);
1095                 *p++ = htonl(nfssvc_boot.tv_usec);
1096         }
1097         return xdr_ressize_check(rqstp, p);
1098 }
1099
1100 /*
1101  * XDR release functions
1102  */
1103 int
1104 nfs3svc_release_fhandle(struct svc_rqst *rqstp, __be32 *p,
1105                                         struct nfsd3_attrstat *resp)
1106 {
1107         fh_put(&resp->fh);
1108         return 1;
1109 }
1110
1111 int
1112 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, __be32 *p,
1113                                         struct nfsd3_fhandle_pair *resp)
1114 {
1115         fh_put(&resp->fh1);
1116         fh_put(&resp->fh2);
1117         return 1;
1118 }