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