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