update to 2.6.9-rc1
[linux-flexiantxendom0-3.2.10.git] / 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 #include <linux/nfsacl.h>
25
26 #define NFSDDBG_FACILITY                NFSDDBG_XDR
27
28 #ifdef NFSD_OPTIMIZE_SPACE
29 # define inline
30 #endif
31
32
33 /*
34  * Mapping of S_IF* types to NFS file types
35  */
36 static u32      nfs3_ftypes[] = {
37         NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
38         NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
39         NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
40         NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
41 };
42
43 /*
44  * XDR functions for basic NFS types
45  */
46 static inline u32 *
47 encode_time3(u32 *p, struct timespec *time)
48 {
49         *p++ = htonl((u32) time->tv_sec); *p++ = htonl(time->tv_nsec);
50         return p;
51 }
52
53 static inline u32 *
54 decode_time3(u32 *p, struct timespec *time)
55 {
56         time->tv_sec = ntohl(*p++);
57         time->tv_nsec = ntohl(*p++);
58         return p;
59 }
60
61 static inline u32 *
62 decode_fh(u32 *p, struct svc_fh *fhp)
63 {
64         unsigned int size;
65         fh_init(fhp, NFS3_FHSIZE);
66         size = ntohl(*p++);
67         if (size > NFS3_FHSIZE)
68                 return NULL;
69
70         memcpy(&fhp->fh_handle.fh_base, p, size);
71         fhp->fh_handle.fh_size = size;
72         return p + XDR_QUADLEN(size);
73 }
74
75 static inline u32 *
76 encode_fh(u32 *p, struct svc_fh *fhp)
77 {
78         unsigned int size = fhp->fh_handle.fh_size;
79         *p++ = htonl(size);
80         if (size) p[XDR_QUADLEN(size)-1]=0;
81         memcpy(p, &fhp->fh_handle.fh_base, size);
82         return p + XDR_QUADLEN(size);
83 }
84
85 /*
86  * Decode a file name and make sure that the path contains
87  * no slashes or null bytes.
88  */
89 static inline u32 *
90 decode_filename(u32 *p, char **namp, int *lenp)
91 {
92         char            *name;
93         int             i;
94
95         if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXNAMLEN)) != NULL) {
96                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
97                         if (*name == '\0' || *name == '/')
98                                 return NULL;
99                 }
100         }
101
102         return p;
103 }
104
105 static inline u32 *
106 decode_pathname(u32 *p, char **namp, int *lenp)
107 {
108         char            *name;
109         int             i;
110
111         if ((p = xdr_decode_string_inplace(p, namp, lenp, NFS3_MAXPATHLEN)) != NULL) {
112                 for (i = 0, name = *namp; i < *lenp; i++, name++) {
113                         if (*name == '\0')
114                                 return NULL;
115                 }
116         }
117
118         return p;
119 }
120
121 static inline u32 *
122 decode_sattr3(u32 *p, struct iattr *iap)
123 {
124         u32     tmp;
125
126         iap->ia_valid = 0;
127
128         if (*p++) {
129                 iap->ia_valid |= ATTR_MODE;
130                 iap->ia_mode = ntohl(*p++);
131         }
132         if (*p++) {
133                 iap->ia_valid |= ATTR_UID;
134                 iap->ia_uid = ntohl(*p++);
135         }
136         if (*p++) {
137                 iap->ia_valid |= ATTR_GID;
138                 iap->ia_gid = ntohl(*p++);
139         }
140         if (*p++) {
141                 u64     newsize;
142
143                 iap->ia_valid |= ATTR_SIZE;
144                 p = xdr_decode_hyper(p, &newsize);
145                 if (newsize <= NFS_OFFSET_MAX)
146                         iap->ia_size = newsize;
147                 else
148                         iap->ia_size = NFS_OFFSET_MAX;
149         }
150         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
151                 iap->ia_valid |= ATTR_ATIME;
152         } else if (tmp == 2) {          /* set to client time */
153                 iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
154                 iap->ia_atime.tv_sec = ntohl(*p++);
155                 iap->ia_atime.tv_nsec = ntohl(*p++);
156         }
157         if ((tmp = ntohl(*p++)) == 1) { /* set to server time */
158                 iap->ia_valid |= ATTR_MTIME;
159         } else if (tmp == 2) {          /* set to client time */
160                 iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
161                 iap->ia_mtime.tv_sec = ntohl(*p++);
162                 iap->ia_mtime.tv_nsec = ntohl(*p++);
163         }
164         return p;
165 }
166
167 static inline u32 *
168 encode_fattr3(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
169 {
170         struct vfsmount *mnt = fhp->fh_export->ex_mnt;
171         struct dentry   *dentry = fhp->fh_dentry;
172         struct kstat stat;
173         struct timespec time;
174
175         vfs_getattr(mnt, dentry, &stat);
176
177         *p++ = htonl(nfs3_ftypes[(stat.mode & S_IFMT) >> 12]);
178         *p++ = htonl((u32) stat.mode);
179         *p++ = htonl((u32) stat.nlink);
180         *p++ = htonl((u32) nfsd_ruid(rqstp, stat.uid));
181         *p++ = htonl((u32) nfsd_rgid(rqstp, stat.gid));
182         if (S_ISLNK(stat.mode) && stat.size > NFS3_MAXPATHLEN) {
183                 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
184         } else {
185                 p = xdr_encode_hyper(p, (u64) stat.size);
186         }
187         p = xdr_encode_hyper(p, ((u64)stat.blocks) << 9);
188         *p++ = htonl((u32) MAJOR(stat.rdev));
189         *p++ = htonl((u32) MINOR(stat.rdev));
190         if (is_fsid(fhp, rqstp->rq_reffh))
191                 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
192         else
193                 p = xdr_encode_hyper(p, (u64) huge_encode_dev(stat.dev));
194         p = xdr_encode_hyper(p, (u64) stat.ino);
195         p = encode_time3(p, &stat.atime);
196         lease_get_mtime(dentry->d_inode, &time); 
197         p = encode_time3(p, &time);
198         p = encode_time3(p, &stat.ctime);
199
200         return p;
201 }
202
203 static inline u32 *
204 encode_saved_post_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
205 {
206         struct inode    *inode = fhp->fh_dentry->d_inode;
207
208         /* Attributes to follow */
209         *p++ = xdr_one;
210
211         *p++ = htonl(nfs3_ftypes[(fhp->fh_post_mode & S_IFMT) >> 12]);
212         *p++ = htonl((u32) fhp->fh_post_mode);
213         *p++ = htonl((u32) fhp->fh_post_nlink);
214         *p++ = htonl((u32) nfsd_ruid(rqstp, fhp->fh_post_uid));
215         *p++ = htonl((u32) nfsd_rgid(rqstp, fhp->fh_post_gid));
216         if (S_ISLNK(fhp->fh_post_mode) && fhp->fh_post_size > NFS3_MAXPATHLEN) {
217                 p = xdr_encode_hyper(p, (u64) NFS3_MAXPATHLEN);
218         } else {
219                 p = xdr_encode_hyper(p, (u64) fhp->fh_post_size);
220         }
221         p = xdr_encode_hyper(p, ((u64)fhp->fh_post_blocks) << 9);
222         *p++ = fhp->fh_post_rdev[0];
223         *p++ = fhp->fh_post_rdev[1];
224         if (is_fsid(fhp, rqstp->rq_reffh))
225                 p = xdr_encode_hyper(p, (u64) fhp->fh_export->ex_fsid);
226         else
227                 p = xdr_encode_hyper(p, (u64)huge_encode_dev(inode->i_sb->s_dev));
228         p = xdr_encode_hyper(p, (u64) inode->i_ino);
229         p = encode_time3(p, &fhp->fh_post_atime);
230         p = encode_time3(p, &fhp->fh_post_mtime);
231         p = encode_time3(p, &fhp->fh_post_ctime);
232
233         return p;
234 }
235
236 /*
237  * Encode post-operation attributes.
238  * The inode may be NULL if the call failed because of a stale file
239  * handle. In this case, no attributes are returned.
240  */
241 static u32 *
242 encode_post_op_attr(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
243 {
244         struct dentry *dentry = fhp->fh_dentry;
245         if (dentry && dentry->d_inode != NULL) {
246                 *p++ = xdr_one;         /* attributes follow */
247                 return encode_fattr3(rqstp, p, fhp);
248         }
249         *p++ = xdr_zero;
250         return p;
251 }
252
253 /*
254  * Enocde weak cache consistency data
255  */
256 static u32 *
257 encode_wcc_data(struct svc_rqst *rqstp, u32 *p, struct svc_fh *fhp)
258 {
259         struct dentry   *dentry = fhp->fh_dentry;
260
261         if (dentry && dentry->d_inode && fhp->fh_post_saved) {
262                 if (fhp->fh_pre_saved) {
263                         *p++ = xdr_one;
264                         p = xdr_encode_hyper(p, (u64) fhp->fh_pre_size);
265                         p = encode_time3(p, &fhp->fh_pre_mtime);
266                         p = encode_time3(p, &fhp->fh_pre_ctime);
267                 } else {
268                         *p++ = xdr_zero;
269                 }
270                 return encode_saved_post_attr(rqstp, p, fhp);
271         }
272         /* no pre- or post-attrs */
273         *p++ = xdr_zero;
274         return encode_post_op_attr(rqstp, p, fhp);
275 }
276
277
278 /*
279  * XDR decode functions
280  */
281 int
282 nfs3svc_decode_fhandle(struct svc_rqst *rqstp, u32 *p, struct nfsd_fhandle *args)
283 {
284         if (!(p = decode_fh(p, &args->fh)))
285                 return 0;
286         return xdr_argsize_check(rqstp, p);
287 }
288
289 int
290 nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, u32 *p,
291                                         struct nfsd3_sattrargs *args)
292 {
293         if (!(p = decode_fh(p, &args->fh))
294          || !(p = decode_sattr3(p, &args->attrs)))
295                 return 0;
296
297         if ((args->check_guard = ntohl(*p++)) != 0) { 
298                 struct timespec time; 
299                 p = decode_time3(p, &time);
300                 args->guardtime = time.tv_sec;
301         }
302
303         return xdr_argsize_check(rqstp, p);
304 }
305
306 int
307 nfs3svc_decode_diropargs(struct svc_rqst *rqstp, u32 *p,
308                                         struct nfsd3_diropargs *args)
309 {
310         if (!(p = decode_fh(p, &args->fh))
311          || !(p = decode_filename(p, &args->name, &args->len)))
312                 return 0;
313
314         return xdr_argsize_check(rqstp, p);
315 }
316
317 int
318 nfs3svc_decode_accessargs(struct svc_rqst *rqstp, u32 *p,
319                                         struct nfsd3_accessargs *args)
320 {
321         if (!(p = decode_fh(p, &args->fh)))
322                 return 0;
323         args->access = ntohl(*p++);
324
325         return xdr_argsize_check(rqstp, p);
326 }
327
328 int
329 nfs3svc_decode_readargs(struct svc_rqst *rqstp, u32 *p,
330                                         struct nfsd3_readargs *args)
331 {
332         unsigned int len;
333         int v,pn;
334
335         if (!(p = decode_fh(p, &args->fh))
336          || !(p = xdr_decode_hyper(p, &args->offset)))
337                 return 0;
338
339         len = args->count = ntohl(*p++);
340
341         if (len > NFSSVC_MAXBLKSIZE)
342                 len = NFSSVC_MAXBLKSIZE;
343
344         /* set up the kvec */
345         v=0;
346         while (len > 0) {
347                 pn = rqstp->rq_resused;
348                 svc_take_page(rqstp);
349                 args->vec[v].iov_base = page_address(rqstp->rq_respages[pn]);
350                 args->vec[v].iov_len = len < PAGE_SIZE? len : PAGE_SIZE;
351                 len -= args->vec[v].iov_len;
352                 v++;
353         }
354         args->vlen = v;
355         return xdr_argsize_check(rqstp, p);
356 }
357
358 int
359 nfs3svc_decode_writeargs(struct svc_rqst *rqstp, u32 *p,
360                                         struct nfsd3_writeargs *args)
361 {
362         unsigned int len, v, hdr;
363
364         if (!(p = decode_fh(p, &args->fh))
365          || !(p = xdr_decode_hyper(p, &args->offset)))
366                 return 0;
367
368         args->count = ntohl(*p++);
369         args->stable = ntohl(*p++);
370         len = args->len = ntohl(*p++);
371
372         hdr = (void*)p - rqstp->rq_arg.head[0].iov_base;
373         if (rqstp->rq_arg.len < len + hdr)
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         if (len > 8192)
579                 len = 8192;
580         args->count = len;
581
582         while (len > 0) {
583                 pn = rqstp->rq_resused;
584                 svc_take_page(rqstp);
585                 if (!args->buffer)
586                         args->buffer = page_address(rqstp->rq_respages[pn]);
587                 len -= PAGE_SIZE;
588         }
589
590         return xdr_argsize_check(rqstp, p);
591 }
592
593 int
594 nfs3svc_decode_commitargs(struct svc_rqst *rqstp, u32 *p,
595                                         struct nfsd3_commitargs *args)
596 {
597         if (!(p = decode_fh(p, &args->fh)))
598                 return 0;
599         p = xdr_decode_hyper(p, &args->offset);
600         args->count = ntohl(*p++);
601
602         return xdr_argsize_check(rqstp, p);
603 }
604
605 #ifdef CONFIG_NFSD_ACL
606 int
607 nfs3svc_decode_getaclargs(struct svc_rqst *rqstp, u32 *p,
608                           struct nfsd3_getaclargs *args)
609 {
610         if (!(p = decode_fh(p, &args->fh)))
611                 return 0;
612         args->mask = ntohl(*p); p++;
613
614         return xdr_argsize_check(rqstp, p);
615 }
616 #endif  /* CONFIG_NFSD_ACL */
617
618 #ifdef CONFIG_NFSD_ACL
619 int
620 nfs3svc_decode_setaclargs(struct svc_rqst *rqstp, u32 *p,
621                           struct nfsd3_setaclargs *args)
622 {
623         struct iovec *head = rqstp->rq_arg.head;
624         unsigned int base;
625         int n;
626
627         if (!(p = decode_fh(p, &args->fh)))
628                 return 0;
629         args->mask = ntohl(*p++);
630         if (args->mask & ~(NFS3_ACL|NFS3_ACLCNT|NFS3_DFACL|NFS3_DFACLCNT) ||
631             !xdr_argsize_check(rqstp, p))
632                 return 0;
633
634         base = (char *)p - (char *)head->iov_base;
635         n = nfsacl_decode(&rqstp->rq_arg, base, NULL,
636                           (args->mask & NFS3_ACL) ?
637                           &args->acl_access : NULL);
638         if (n > 0)
639                 n = nfsacl_decode(&rqstp->rq_arg, base + n, NULL,
640                                   (args->mask & NFS3_DFACL) ?
641                                   &args->acl_default : NULL);
642         return (n > 0);
643 }
644 #endif  /* CONFIG_NFSD_ACL */
645
646 /*
647  * XDR encode functions
648  */
649 /*
650  * There must be an encoding function for void results so svc_process
651  * will work properly.
652  */
653 int
654 nfs3svc_encode_voidres(struct svc_rqst *rqstp, u32 *p, void *dummy)
655 {
656         return xdr_ressize_check(rqstp, p);
657 }
658
659 /* GETATTR */
660 int
661 nfs3svc_encode_attrstat(struct svc_rqst *rqstp, u32 *p,
662                                         struct nfsd3_attrstat *resp)
663 {
664         if (resp->status == 0)
665                 p = encode_fattr3(rqstp, p, &resp->fh);
666         return xdr_ressize_check(rqstp, p);
667 }
668
669 /* SETATTR, REMOVE, RMDIR */
670 int
671 nfs3svc_encode_wccstat(struct svc_rqst *rqstp, u32 *p,
672                                         struct nfsd3_attrstat *resp)
673 {
674         p = encode_wcc_data(rqstp, p, &resp->fh);
675         return xdr_ressize_check(rqstp, p);
676 }
677
678 /* LOOKUP */
679 int
680 nfs3svc_encode_diropres(struct svc_rqst *rqstp, u32 *p,
681                                         struct nfsd3_diropres *resp)
682 {
683         if (resp->status == 0) {
684                 p = encode_fh(p, &resp->fh);
685                 p = encode_post_op_attr(rqstp, p, &resp->fh);
686         }
687         p = encode_post_op_attr(rqstp, p, &resp->dirfh);
688         return xdr_ressize_check(rqstp, p);
689 }
690
691 /* ACCESS */
692 int
693 nfs3svc_encode_accessres(struct svc_rqst *rqstp, u32 *p,
694                                         struct nfsd3_accessres *resp)
695 {
696         p = encode_post_op_attr(rqstp, p, &resp->fh);
697         if (resp->status == 0)
698                 *p++ = htonl(resp->access);
699         return xdr_ressize_check(rqstp, p);
700 }
701
702 /* READLINK */
703 int
704 nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, u32 *p,
705                                         struct nfsd3_readlinkres *resp)
706 {
707         p = encode_post_op_attr(rqstp, p, &resp->fh);
708         if (resp->status == 0) {
709                 *p++ = htonl(resp->len);
710                 xdr_ressize_check(rqstp, p);
711                 rqstp->rq_res.page_len = resp->len;
712                 if (resp->len & 3) {
713                         /* need to pad the tail */
714                         rqstp->rq_restailpage = 0;
715                         rqstp->rq_res.tail[0].iov_base = p;
716                         *p = 0;
717                         rqstp->rq_res.tail[0].iov_len = 4 - (resp->len&3);
718                 }
719                 return 1;
720         } else
721                 return xdr_ressize_check(rqstp, p);
722 }
723
724 /* READ */
725 int
726 nfs3svc_encode_readres(struct svc_rqst *rqstp, u32 *p,
727                                         struct nfsd3_readres *resp)
728 {
729         p = encode_post_op_attr(rqstp, p, &resp->fh);
730         if (resp->status == 0) {
731                 *p++ = htonl(resp->count);
732                 *p++ = htonl(resp->eof);
733                 *p++ = htonl(resp->count);      /* xdr opaque count */
734                 xdr_ressize_check(rqstp, p);
735                 /* now update rqstp->rq_res to reflect data aswell */
736                 rqstp->rq_res.page_len = resp->count;
737                 if (resp->count & 3) {
738                         /* need to pad the tail */
739                         rqstp->rq_restailpage = 0;
740                         rqstp->rq_res.tail[0].iov_base = p;
741                         *p = 0;
742                         rqstp->rq_res.tail[0].iov_len = 4 - (resp->count & 3);
743                 }
744                 return 1;
745         } else
746                 return xdr_ressize_check(rqstp, p);
747 }
748
749 /* WRITE */
750 int
751 nfs3svc_encode_writeres(struct svc_rqst *rqstp, u32 *p,
752                                         struct nfsd3_writeres *resp)
753 {
754         p = encode_wcc_data(rqstp, p, &resp->fh);
755         if (resp->status == 0) {
756                 *p++ = htonl(resp->count);
757                 *p++ = htonl(resp->committed);
758                 *p++ = htonl(nfssvc_boot.tv_sec);
759                 *p++ = htonl(nfssvc_boot.tv_usec);
760         }
761         return xdr_ressize_check(rqstp, p);
762 }
763
764 /* CREATE, MKDIR, SYMLINK, MKNOD */
765 int
766 nfs3svc_encode_createres(struct svc_rqst *rqstp, u32 *p,
767                                         struct nfsd3_diropres *resp)
768 {
769         if (resp->status == 0) {
770                 *p++ = xdr_one;
771                 p = encode_fh(p, &resp->fh);
772                 p = encode_post_op_attr(rqstp, p, &resp->fh);
773         }
774         p = encode_wcc_data(rqstp, p, &resp->dirfh);
775         return xdr_ressize_check(rqstp, p);
776 }
777
778 /* RENAME */
779 int
780 nfs3svc_encode_renameres(struct svc_rqst *rqstp, u32 *p,
781                                         struct nfsd3_renameres *resp)
782 {
783         p = encode_wcc_data(rqstp, p, &resp->ffh);
784         p = encode_wcc_data(rqstp, p, &resp->tfh);
785         return xdr_ressize_check(rqstp, p);
786 }
787
788 /* LINK */
789 int
790 nfs3svc_encode_linkres(struct svc_rqst *rqstp, u32 *p,
791                                         struct nfsd3_linkres *resp)
792 {
793         p = encode_post_op_attr(rqstp, p, &resp->fh);
794         p = encode_wcc_data(rqstp, p, &resp->tfh);
795         return xdr_ressize_check(rqstp, p);
796 }
797
798 /* READDIR */
799 int
800 nfs3svc_encode_readdirres(struct svc_rqst *rqstp, u32 *p,
801                                         struct nfsd3_readdirres *resp)
802 {
803         p = encode_post_op_attr(rqstp, p, &resp->fh);
804
805         if (resp->status == 0) {
806                 /* stupid readdir cookie */
807                 memcpy(p, resp->verf, 8); p += 2;
808                 xdr_ressize_check(rqstp, p);
809                 if (rqstp->rq_res.head[0].iov_len + (2<<2) > PAGE_SIZE)
810                         return 1; /*No room for trailer */
811                 rqstp->rq_res.page_len = (resp->count) << 2;
812
813                 /* add the 'tail' to the end of the 'head' page - page 0. */
814                 rqstp->rq_restailpage = 0;
815                 rqstp->rq_res.tail[0].iov_base = p;
816                 *p++ = 0;               /* no more entries */
817                 *p++ = htonl(resp->common.err == nfserr_eof);
818                 rqstp->rq_res.tail[0].iov_len = 2<<2;
819                 return 1;
820         } else
821                 return xdr_ressize_check(rqstp, p);
822 }
823
824 static inline u32 *
825 encode_entry_baggage(struct nfsd3_readdirres *cd, u32 *p, const char *name,
826              int namlen, ino_t ino)
827 {
828         *p++ = xdr_one;                          /* mark entry present */
829         p    = xdr_encode_hyper(p, ino);         /* file id */
830         p    = xdr_encode_array(p, name, namlen);/* name length & name */
831
832         cd->offset = p;                         /* remember pointer */
833         p = xdr_encode_hyper(p, NFS_OFFSET_MAX);/* offset of next entry */
834
835         return p;
836 }
837
838 static inline u32 *
839 encode_entryplus_baggage(struct nfsd3_readdirres *cd, u32 *p,
840                 struct svc_fh *fhp)
841 {
842                 p = encode_post_op_attr(cd->rqstp, p, fhp);
843                 *p++ = xdr_one;                 /* yes, a file handle follows */
844                 p = encode_fh(p, fhp);
845                 fh_put(fhp);
846                 return p;
847 }
848
849 static int
850 compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
851                 const char *name, int namlen)
852 {
853         struct svc_export       *exp;
854         struct dentry           *dparent, *dchild;
855         int rv = 0;
856
857         dparent = cd->fh.fh_dentry;
858         exp  = cd->fh.fh_export;
859
860         fh_init(fhp, NFS3_FHSIZE);
861         if (isdotent(name, namlen)) {
862                 if (namlen == 2) {
863                         dchild = dget_parent(dparent);
864                 } else
865                         dchild = dget(dparent);
866         } else
867                 dchild = lookup_one_len(name, dparent, namlen);
868         if (IS_ERR(dchild))
869                 return 1;
870         if (d_mountpoint(dchild) ||
871             fh_compose(fhp, exp, dchild, &cd->fh) != 0 ||
872             !dchild->d_inode)
873                 rv = 1;
874         dput(dchild);
875         return rv;
876 }
877
878 /*
879  * Encode a directory entry. This one works for both normal readdir
880  * and readdirplus.
881  * The normal readdir reply requires 2 (fileid) + 1 (stringlen)
882  * + string + 2 (cookie) + 1 (next) words, i.e. 6 + strlen.
883  * 
884  * The readdirplus baggage is 1+21 words for post_op_attr, plus the
885  * file handle.
886  */
887
888 #define NFS3_ENTRY_BAGGAGE      (2 + 1 + 2 + 1)
889 #define NFS3_ENTRYPLUS_BAGGAGE  (1 + 21 + 1 + (NFS3_FHSIZE >> 2))
890 static int
891 encode_entry(struct readdir_cd *ccd, const char *name,
892              int namlen, off_t offset, ino_t ino, unsigned int d_type, int plus)
893 {
894         struct nfsd3_readdirres *cd = container_of(ccd, struct nfsd3_readdirres,
895                                                         common);
896         u32             *p = cd->buffer;
897         caddr_t         curr_page_addr = NULL;
898         int             pn;             /* current page number */
899         int             slen;           /* string (name) length */
900         int             elen;           /* estimated entry length in words */
901         int             num_entry_words = 0;    /* actual number of words */
902
903         if (cd->offset) {
904                 u64 offset64 = offset;
905
906                 if (unlikely(cd->offset1)) {
907                         /* we ended up with offset on a page boundary */
908                         *cd->offset = htonl(offset64 >> 32);
909                         *cd->offset1 = htonl(offset64 & 0xffffffff);
910                         cd->offset1 = NULL;
911                 } else {
912                         xdr_encode_hyper(cd->offset, (u64) offset);
913                 }
914         }
915
916         /*
917         dprintk("encode_entry(%.*s @%ld%s)\n",
918                 namlen, name, (long) offset, plus? " plus" : "");
919          */
920
921         /* truncate filename if too long */
922         if (namlen > NFS3_MAXNAMLEN)
923                 namlen = NFS3_MAXNAMLEN;
924
925         slen = XDR_QUADLEN(namlen);
926         elen = slen + NFS3_ENTRY_BAGGAGE
927                 + (plus? NFS3_ENTRYPLUS_BAGGAGE : 0);
928
929         if (cd->buflen < elen) {
930                 cd->common.err = nfserr_toosmall;
931                 return -EINVAL;
932         }
933
934         /* determine which page in rq_respages[] we are currently filling */
935         for (pn=1; pn < cd->rqstp->rq_resused; pn++) {
936                 curr_page_addr = page_address(cd->rqstp->rq_respages[pn]);
937
938                 if (((caddr_t)cd->buffer >= curr_page_addr) &&
939                     ((caddr_t)cd->buffer <  curr_page_addr + PAGE_SIZE))
940                         break;
941         }
942
943         if ((caddr_t)(cd->buffer + elen) < (curr_page_addr + PAGE_SIZE)) {
944                 /* encode entry in current page */
945
946                 p = encode_entry_baggage(cd, p, name, namlen, ino);
947
948                 /* throw in readdirplus baggage */
949                 if (plus) {
950                         struct svc_fh   fh;
951
952                         if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
953                                 *p++ = 0;
954                                 *p++ = 0;
955                         } else
956                                 p = encode_entryplus_baggage(cd, p, &fh);
957                 }
958                 num_entry_words = p - cd->buffer;
959         } else if (cd->rqstp->rq_respages[pn+1] != NULL) {
960                 /* temporarily encode entry into next page, then move back to
961                  * current and next page in rq_respages[] */
962                 u32 *p1, *tmp;
963                 int len1, len2;
964
965                 /* grab next page for temporary storage of entry */
966                 p1 = tmp = page_address(cd->rqstp->rq_respages[pn+1]);
967
968                 p1 = encode_entry_baggage(cd, p1, name, namlen, ino);
969
970                 /* throw in readdirplus baggage */
971                 if (plus) {
972                         struct svc_fh   fh;
973
974                         if (compose_entry_fh(cd, &fh, name, namlen) > 0) {
975                                 /* zero out the filehandle */
976                                 *p1++ = 0;
977                                 *p1++ = 0;
978                         } else
979                                 p1 = encode_entryplus_baggage(cd, p1, &fh);
980                 }
981
982                 /* determine entry word length and lengths to go in pages */
983                 num_entry_words = p1 - tmp;
984                 len1 = curr_page_addr + PAGE_SIZE - (caddr_t)cd->buffer;
985                 if ((num_entry_words << 2) < len1) {
986                         /* the actual number of words in the entry is less
987                          * than elen and can still fit in the current page
988                          */
989                         memmove(p, tmp, num_entry_words << 2);
990                         p += num_entry_words;
991
992                         /* update offset */
993                         cd->offset = cd->buffer + (cd->offset - tmp);
994                 } else {
995                         unsigned int offset_r = (cd->offset - tmp) << 2;
996
997                         /* update pointer to offset location.
998                          * This is a 64bit quantity, so we need to
999                          * deal with 3 cases:
1000                          *  -   entirely in first page
1001                          *  -   entirely in second page
1002                          *  -   4 bytes in each page
1003                          */
1004                         if (offset_r + 8 <= len1) {
1005                                 cd->offset = p + (cd->offset - tmp);
1006                         } else if (offset_r >= len1) {
1007                                 cd->offset -= len1 >> 2;
1008                         } else {
1009                                 /* sitting on the fence */
1010                                 BUG_ON(offset_r != len1 - 4);
1011                                 cd->offset = p + (cd->offset - tmp);
1012                                 cd->offset1 = tmp;
1013                         }
1014
1015                         len2 = (num_entry_words << 2) - len1;
1016
1017                         /* move from temp page to current and next pages */
1018                         memmove(p, tmp, len1);
1019                         memmove(tmp, (caddr_t)tmp+len1, len2);
1020
1021                         p = tmp + (len2 >> 2);
1022                 }
1023         }
1024         else {
1025                 cd->common.err = nfserr_toosmall;
1026                 return -EINVAL;
1027         }
1028
1029         cd->buflen -= num_entry_words;
1030         cd->buffer = p;
1031         cd->common.err = nfs_ok;
1032         return 0;
1033
1034 }
1035
1036 int
1037 nfs3svc_encode_entry(struct readdir_cd *cd, const char *name,
1038                      int namlen, loff_t offset, ino_t ino, unsigned int d_type)
1039 {
1040         return encode_entry(cd, name, namlen, offset, ino, d_type, 0);
1041 }
1042
1043 int
1044 nfs3svc_encode_entry_plus(struct readdir_cd *cd, const char *name,
1045                           int namlen, loff_t offset, ino_t ino, unsigned int d_type)
1046 {
1047         return encode_entry(cd, name, namlen, offset, ino, d_type, 1);
1048 }
1049
1050 /* FSSTAT */
1051 int
1052 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, u32 *p,
1053                                         struct nfsd3_fsstatres *resp)
1054 {
1055         struct kstatfs  *s = &resp->stats;
1056         u64             bs = s->f_bsize;
1057
1058         *p++ = xdr_zero;        /* no post_op_attr */
1059
1060         if (resp->status == 0) {
1061                 p = xdr_encode_hyper(p, bs * s->f_blocks);      /* total bytes */
1062                 p = xdr_encode_hyper(p, bs * s->f_bfree);       /* free bytes */
1063                 p = xdr_encode_hyper(p, bs * s->f_bavail);      /* user available bytes */
1064                 p = xdr_encode_hyper(p, s->f_files);    /* total inodes */
1065                 p = xdr_encode_hyper(p, s->f_ffree);    /* free inodes */
1066                 p = xdr_encode_hyper(p, s->f_ffree);    /* user available inodes */
1067                 *p++ = htonl(resp->invarsec);   /* mean unchanged time */
1068         }
1069         return xdr_ressize_check(rqstp, p);
1070 }
1071
1072 /* FSINFO */
1073 int
1074 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, u32 *p,
1075                                         struct nfsd3_fsinfores *resp)
1076 {
1077         *p++ = xdr_zero;        /* no post_op_attr */
1078
1079         if (resp->status == 0) {
1080                 *p++ = htonl(resp->f_rtmax);
1081                 *p++ = htonl(resp->f_rtpref);
1082                 *p++ = htonl(resp->f_rtmult);
1083                 *p++ = htonl(resp->f_wtmax);
1084                 *p++ = htonl(resp->f_wtpref);
1085                 *p++ = htonl(resp->f_wtmult);
1086                 *p++ = htonl(resp->f_dtpref);
1087                 p = xdr_encode_hyper(p, resp->f_maxfilesize);
1088                 *p++ = xdr_one;
1089                 *p++ = xdr_zero;
1090                 *p++ = htonl(resp->f_properties);
1091         }
1092
1093         return xdr_ressize_check(rqstp, p);
1094 }
1095
1096 /* PATHCONF */
1097 int
1098 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, u32 *p,
1099                                         struct nfsd3_pathconfres *resp)
1100 {
1101         *p++ = xdr_zero;        /* no post_op_attr */
1102
1103         if (resp->status == 0) {
1104                 *p++ = htonl(resp->p_link_max);
1105                 *p++ = htonl(resp->p_name_max);
1106                 *p++ = htonl(resp->p_no_trunc);
1107                 *p++ = htonl(resp->p_chown_restricted);
1108                 *p++ = htonl(resp->p_case_insensitive);
1109                 *p++ = htonl(resp->p_case_preserving);
1110         }
1111
1112         return xdr_ressize_check(rqstp, p);
1113 }
1114
1115 /* COMMIT */
1116 int
1117 nfs3svc_encode_commitres(struct svc_rqst *rqstp, u32 *p,
1118                                         struct nfsd3_commitres *resp)
1119 {
1120         p = encode_wcc_data(rqstp, p, &resp->fh);
1121         /* Write verifier */
1122         if (resp->status == 0) {
1123                 *p++ = htonl(nfssvc_boot.tv_sec);
1124                 *p++ = htonl(nfssvc_boot.tv_usec);
1125         }
1126         return xdr_ressize_check(rqstp, p);
1127 }
1128
1129 #ifdef CONFIG_NFSD_ACL
1130 /* GETACL */
1131 int
1132 nfs3svc_encode_getaclres(struct svc_rqst *rqstp, u32 *p,
1133                          struct nfsd3_getaclres *resp)
1134 {
1135         struct dentry *dentry = resp->fh.fh_dentry;
1136
1137         p = encode_post_op_attr(rqstp, p, &resp->fh);
1138         if (resp->status == 0 && dentry && dentry->d_inode) {
1139                 struct inode *inode = dentry->d_inode;
1140                 int w = nfsacl_size(
1141                         (resp->mask & NFS3_ACL)   ? resp->acl_access  : NULL,
1142                         (resp->mask & NFS3_DFACL) ? resp->acl_default : NULL);
1143                 struct iovec *head = rqstp->rq_res.head;
1144                 unsigned int base;
1145                 int n;
1146
1147                 *p++ = htonl(resp->mask);
1148                 if (!xdr_ressize_check(rqstp, p))
1149                         return 0;
1150                 base = (char *)p - (char *)head->iov_base;
1151
1152                 rqstp->rq_res.page_len = w;
1153                 while (w > 0) {
1154                         if (!svc_take_res_page(rqstp))
1155                                 return 0;
1156                         w -= PAGE_SIZE;
1157                 }
1158
1159                 n = nfsacl_encode(&rqstp->rq_res, base, inode,
1160                                   resp->acl_access,
1161                                   resp->mask & NFS3_ACL, 0);
1162                 if (n > 0)
1163                         n = nfsacl_encode(&rqstp->rq_res, base + n, inode,
1164                                           resp->acl_default,
1165                                           resp->mask & NFS3_DFACL,
1166                                           NFS3_ACL_DEFAULT);
1167                 if (n <= 0)
1168                         return 0;
1169         } else
1170                 if (!xdr_ressize_check(rqstp, p))
1171                         return 0;
1172
1173         return 1;
1174 }
1175 #endif  /* CONFIG_NFSD_ACL */
1176
1177 #ifdef CONFIG_NFSD_ACL
1178 /* SETACL */
1179 int
1180 nfs3svc_encode_setaclres(struct svc_rqst *rqstp, u32 *p,
1181                          struct nfsd3_attrstat *resp)
1182 {
1183         p = encode_post_op_attr(rqstp, p, &resp->fh);
1184
1185         return xdr_ressize_check(rqstp, p);
1186 }
1187 #endif  /* CONFIG_NFSD_ACL */
1188
1189 /*
1190  * XDR release functions
1191  */
1192 int
1193 nfs3svc_release_fhandle(struct svc_rqst *rqstp, u32 *p,
1194                                         struct nfsd3_attrstat *resp)
1195 {
1196         fh_put(&resp->fh);
1197         return 1;
1198 }
1199
1200 int
1201 nfs3svc_release_fhandle2(struct svc_rqst *rqstp, u32 *p,
1202                                         struct nfsd3_fhandle_pair *resp)
1203 {
1204         fh_put(&resp->fh1);
1205         fh_put(&resp->fh2);
1206         return 1;
1207 }
1208
1209 #ifdef CONFIG_NFSD_ACL
1210 int
1211 nfs3svc_release_getacl(struct svc_rqst *rqstp, u32 *p,
1212                        struct nfsd3_getaclres *resp)
1213 {
1214         fh_put(&resp->fh);
1215         posix_acl_release(resp->acl_access);
1216         posix_acl_release(resp->acl_default);
1217         return 1;
1218 }
1219 #endif  /* CONFIG_NFSD_ACL */