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