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