xref: /kernel/linux/linux-6.6/fs/nfsd/nfs3xdr.c (revision 62306a36)
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/*
18 * Force construction of an empty post-op attr
19 */
20static const struct svc_fh nfs3svc_null_fh = {
21	.fh_no_wcc	= true,
22};
23
24/*
25 * time_delta. {1, 0} means the server is accurate only
26 * to the nearest second.
27 */
28static const struct timespec64 nfs3svc_time_delta = {
29	.tv_sec		= 1,
30	.tv_nsec	= 0,
31};
32
33/*
34 * Mapping of S_IF* types to NFS file types
35 */
36static const u32 nfs3_ftypes[] = {
37	NF3NON,  NF3FIFO, NF3CHR, NF3BAD,
38	NF3DIR,  NF3BAD,  NF3BLK, NF3BAD,
39	NF3REG,  NF3BAD,  NF3LNK, NF3BAD,
40	NF3SOCK, NF3BAD,  NF3LNK, NF3BAD,
41};
42
43
44/*
45 * Basic NFSv3 data types (RFC 1813 Sections 2.5 and 2.6)
46 */
47
48static __be32 *
49encode_nfstime3(__be32 *p, const struct timespec64 *time)
50{
51	*p++ = cpu_to_be32((u32)time->tv_sec);
52	*p++ = cpu_to_be32(time->tv_nsec);
53
54	return p;
55}
56
57static bool
58svcxdr_decode_nfstime3(struct xdr_stream *xdr, struct timespec64 *timep)
59{
60	__be32 *p;
61
62	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
63	if (!p)
64		return false;
65	timep->tv_sec = be32_to_cpup(p++);
66	timep->tv_nsec = be32_to_cpup(p);
67
68	return true;
69}
70
71/**
72 * svcxdr_decode_nfs_fh3 - Decode an NFSv3 file handle
73 * @xdr: XDR stream positioned at an undecoded NFSv3 FH
74 * @fhp: OUT: filled-in server file handle
75 *
76 * Return values:
77 *  %false: The encoded file handle was not valid
78 *  %true: @fhp has been initialized
79 */
80bool
81svcxdr_decode_nfs_fh3(struct xdr_stream *xdr, struct svc_fh *fhp)
82{
83	__be32 *p;
84	u32 size;
85
86	if (xdr_stream_decode_u32(xdr, &size) < 0)
87		return false;
88	if (size == 0 || size > NFS3_FHSIZE)
89		return false;
90	p = xdr_inline_decode(xdr, size);
91	if (!p)
92		return false;
93	fh_init(fhp, NFS3_FHSIZE);
94	fhp->fh_handle.fh_size = size;
95	memcpy(&fhp->fh_handle.fh_raw, p, size);
96
97	return true;
98}
99
100/**
101 * svcxdr_encode_nfsstat3 - Encode an NFSv3 status code
102 * @xdr: XDR stream
103 * @status: status value to encode
104 *
105 * Return values:
106 *   %false: Send buffer space was exhausted
107 *   %true: Success
108 */
109bool
110svcxdr_encode_nfsstat3(struct xdr_stream *xdr, __be32 status)
111{
112	__be32 *p;
113
114	p = xdr_reserve_space(xdr, sizeof(status));
115	if (!p)
116		return false;
117	*p = status;
118
119	return true;
120}
121
122static bool
123svcxdr_encode_nfs_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
124{
125	u32 size = fhp->fh_handle.fh_size;
126	__be32 *p;
127
128	p = xdr_reserve_space(xdr, XDR_UNIT + size);
129	if (!p)
130		return false;
131	*p++ = cpu_to_be32(size);
132	if (size)
133		p[XDR_QUADLEN(size) - 1] = 0;
134	memcpy(p, &fhp->fh_handle.fh_raw, size);
135
136	return true;
137}
138
139static bool
140svcxdr_encode_post_op_fh3(struct xdr_stream *xdr, const struct svc_fh *fhp)
141{
142	if (xdr_stream_encode_item_present(xdr) < 0)
143		return false;
144	if (!svcxdr_encode_nfs_fh3(xdr, fhp))
145		return false;
146
147	return true;
148}
149
150static bool
151svcxdr_encode_cookieverf3(struct xdr_stream *xdr, const __be32 *verf)
152{
153	__be32 *p;
154
155	p = xdr_reserve_space(xdr, NFS3_COOKIEVERFSIZE);
156	if (!p)
157		return false;
158	memcpy(p, verf, NFS3_COOKIEVERFSIZE);
159
160	return true;
161}
162
163static bool
164svcxdr_encode_writeverf3(struct xdr_stream *xdr, const __be32 *verf)
165{
166	__be32 *p;
167
168	p = xdr_reserve_space(xdr, NFS3_WRITEVERFSIZE);
169	if (!p)
170		return false;
171	memcpy(p, verf, NFS3_WRITEVERFSIZE);
172
173	return true;
174}
175
176static bool
177svcxdr_decode_filename3(struct xdr_stream *xdr, char **name, unsigned int *len)
178{
179	u32 size, i;
180	__be32 *p;
181	char *c;
182
183	if (xdr_stream_decode_u32(xdr, &size) < 0)
184		return false;
185	if (size == 0 || size > NFS3_MAXNAMLEN)
186		return false;
187	p = xdr_inline_decode(xdr, size);
188	if (!p)
189		return false;
190
191	*len = size;
192	*name = (char *)p;
193	for (i = 0, c = *name; i < size; i++, c++) {
194		if (*c == '\0' || *c == '/')
195			return false;
196	}
197
198	return true;
199}
200
201static bool
202svcxdr_decode_diropargs3(struct xdr_stream *xdr, struct svc_fh *fhp,
203			 char **name, unsigned int *len)
204{
205	return svcxdr_decode_nfs_fh3(xdr, fhp) &&
206		svcxdr_decode_filename3(xdr, name, len);
207}
208
209static bool
210svcxdr_decode_sattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
211		     struct iattr *iap)
212{
213	u32 set_it;
214
215	iap->ia_valid = 0;
216
217	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
218		return false;
219	if (set_it) {
220		u32 mode;
221
222		if (xdr_stream_decode_u32(xdr, &mode) < 0)
223			return false;
224		iap->ia_valid |= ATTR_MODE;
225		iap->ia_mode = mode;
226	}
227	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
228		return false;
229	if (set_it) {
230		u32 uid;
231
232		if (xdr_stream_decode_u32(xdr, &uid) < 0)
233			return false;
234		iap->ia_uid = make_kuid(nfsd_user_namespace(rqstp), uid);
235		if (uid_valid(iap->ia_uid))
236			iap->ia_valid |= ATTR_UID;
237	}
238	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
239		return false;
240	if (set_it) {
241		u32 gid;
242
243		if (xdr_stream_decode_u32(xdr, &gid) < 0)
244			return false;
245		iap->ia_gid = make_kgid(nfsd_user_namespace(rqstp), gid);
246		if (gid_valid(iap->ia_gid))
247			iap->ia_valid |= ATTR_GID;
248	}
249	if (xdr_stream_decode_bool(xdr, &set_it) < 0)
250		return false;
251	if (set_it) {
252		u64 newsize;
253
254		if (xdr_stream_decode_u64(xdr, &newsize) < 0)
255			return false;
256		iap->ia_valid |= ATTR_SIZE;
257		iap->ia_size = newsize;
258	}
259	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
260		return false;
261	switch (set_it) {
262	case DONT_CHANGE:
263		break;
264	case SET_TO_SERVER_TIME:
265		iap->ia_valid |= ATTR_ATIME;
266		break;
267	case SET_TO_CLIENT_TIME:
268		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_atime))
269			return false;
270		iap->ia_valid |= ATTR_ATIME | ATTR_ATIME_SET;
271		break;
272	default:
273		return false;
274	}
275	if (xdr_stream_decode_u32(xdr, &set_it) < 0)
276		return false;
277	switch (set_it) {
278	case DONT_CHANGE:
279		break;
280	case SET_TO_SERVER_TIME:
281		iap->ia_valid |= ATTR_MTIME;
282		break;
283	case SET_TO_CLIENT_TIME:
284		if (!svcxdr_decode_nfstime3(xdr, &iap->ia_mtime))
285			return false;
286		iap->ia_valid |= ATTR_MTIME | ATTR_MTIME_SET;
287		break;
288	default:
289		return false;
290	}
291
292	return true;
293}
294
295static bool
296svcxdr_decode_sattrguard3(struct xdr_stream *xdr, struct nfsd3_sattrargs *args)
297{
298	__be32 *p;
299	u32 check;
300
301	if (xdr_stream_decode_bool(xdr, &check) < 0)
302		return false;
303	if (check) {
304		p = xdr_inline_decode(xdr, XDR_UNIT * 2);
305		if (!p)
306			return false;
307		args->check_guard = 1;
308		args->guardtime = be32_to_cpup(p);
309	} else
310		args->check_guard = 0;
311
312	return true;
313}
314
315static bool
316svcxdr_decode_specdata3(struct xdr_stream *xdr, struct nfsd3_mknodargs *args)
317{
318	__be32 *p;
319
320	p = xdr_inline_decode(xdr, XDR_UNIT * 2);
321	if (!p)
322		return false;
323	args->major = be32_to_cpup(p++);
324	args->minor = be32_to_cpup(p);
325
326	return true;
327}
328
329static bool
330svcxdr_decode_devicedata3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
331			  struct nfsd3_mknodargs *args)
332{
333	return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
334		svcxdr_decode_specdata3(xdr, args);
335}
336
337static bool
338svcxdr_encode_fattr3(struct svc_rqst *rqstp, struct xdr_stream *xdr,
339		     const struct svc_fh *fhp, const struct kstat *stat)
340{
341	struct user_namespace *userns = nfsd_user_namespace(rqstp);
342	__be32 *p;
343	u64 fsid;
344
345	p = xdr_reserve_space(xdr, XDR_UNIT * 21);
346	if (!p)
347		return false;
348
349	*p++ = cpu_to_be32(nfs3_ftypes[(stat->mode & S_IFMT) >> 12]);
350	*p++ = cpu_to_be32((u32)(stat->mode & S_IALLUGO));
351	*p++ = cpu_to_be32((u32)stat->nlink);
352	*p++ = cpu_to_be32((u32)from_kuid_munged(userns, stat->uid));
353	*p++ = cpu_to_be32((u32)from_kgid_munged(userns, stat->gid));
354	if (S_ISLNK(stat->mode) && stat->size > NFS3_MAXPATHLEN)
355		p = xdr_encode_hyper(p, (u64)NFS3_MAXPATHLEN);
356	else
357		p = xdr_encode_hyper(p, (u64)stat->size);
358
359	/* used */
360	p = xdr_encode_hyper(p, ((u64)stat->blocks) << 9);
361
362	/* rdev */
363	*p++ = cpu_to_be32((u32)MAJOR(stat->rdev));
364	*p++ = cpu_to_be32((u32)MINOR(stat->rdev));
365
366	switch(fsid_source(fhp)) {
367	case FSIDSOURCE_FSID:
368		fsid = (u64)fhp->fh_export->ex_fsid;
369		break;
370	case FSIDSOURCE_UUID:
371		fsid = ((u64 *)fhp->fh_export->ex_uuid)[0];
372		fsid ^= ((u64 *)fhp->fh_export->ex_uuid)[1];
373		break;
374	default:
375		fsid = (u64)huge_encode_dev(fhp->fh_dentry->d_sb->s_dev);
376	}
377	p = xdr_encode_hyper(p, fsid);
378
379	/* fileid */
380	p = xdr_encode_hyper(p, stat->ino);
381
382	p = encode_nfstime3(p, &stat->atime);
383	p = encode_nfstime3(p, &stat->mtime);
384	encode_nfstime3(p, &stat->ctime);
385
386	return true;
387}
388
389static bool
390svcxdr_encode_wcc_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
391{
392	__be32 *p;
393
394	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
395	if (!p)
396		return false;
397	p = xdr_encode_hyper(p, (u64)fhp->fh_pre_size);
398	p = encode_nfstime3(p, &fhp->fh_pre_mtime);
399	encode_nfstime3(p, &fhp->fh_pre_ctime);
400
401	return true;
402}
403
404static bool
405svcxdr_encode_pre_op_attr(struct xdr_stream *xdr, const struct svc_fh *fhp)
406{
407	if (!fhp->fh_pre_saved) {
408		if (xdr_stream_encode_item_absent(xdr) < 0)
409			return false;
410		return true;
411	}
412
413	if (xdr_stream_encode_item_present(xdr) < 0)
414		return false;
415	return svcxdr_encode_wcc_attr(xdr, fhp);
416}
417
418/**
419 * svcxdr_encode_post_op_attr - Encode NFSv3 post-op attributes
420 * @rqstp: Context of a completed RPC transaction
421 * @xdr: XDR stream
422 * @fhp: File handle to encode
423 *
424 * Return values:
425 *   %false: Send buffer space was exhausted
426 *   %true: Success
427 */
428bool
429svcxdr_encode_post_op_attr(struct svc_rqst *rqstp, struct xdr_stream *xdr,
430			   const struct svc_fh *fhp)
431{
432	struct dentry *dentry = fhp->fh_dentry;
433	struct kstat stat;
434
435	/*
436	 * The inode may be NULL if the call failed because of a
437	 * stale file handle. In this case, no attributes are
438	 * returned.
439	 */
440	if (fhp->fh_no_wcc || !dentry || !d_really_is_positive(dentry))
441		goto no_post_op_attrs;
442	if (fh_getattr(fhp, &stat) != nfs_ok)
443		goto no_post_op_attrs;
444
445	if (xdr_stream_encode_item_present(xdr) < 0)
446		return false;
447	lease_get_mtime(d_inode(dentry), &stat.mtime);
448	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &stat))
449		return false;
450
451	return true;
452
453no_post_op_attrs:
454	return xdr_stream_encode_item_absent(xdr) > 0;
455}
456
457/*
458 * Encode weak cache consistency data
459 */
460static bool
461svcxdr_encode_wcc_data(struct svc_rqst *rqstp, struct xdr_stream *xdr,
462		       const struct svc_fh *fhp)
463{
464	struct dentry *dentry = fhp->fh_dentry;
465
466	if (!dentry || !d_really_is_positive(dentry) || !fhp->fh_post_saved)
467		goto neither;
468
469	/* before */
470	if (!svcxdr_encode_pre_op_attr(xdr, fhp))
471		return false;
472
473	/* after */
474	if (xdr_stream_encode_item_present(xdr) < 0)
475		return false;
476	if (!svcxdr_encode_fattr3(rqstp, xdr, fhp, &fhp->fh_post_attr))
477		return false;
478
479	return true;
480
481neither:
482	if (xdr_stream_encode_item_absent(xdr) < 0)
483		return false;
484	if (!svcxdr_encode_post_op_attr(rqstp, xdr, fhp))
485		return false;
486
487	return true;
488}
489
490/*
491 * XDR decode functions
492 */
493
494bool
495nfs3svc_decode_fhandleargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
496{
497	struct nfsd_fhandle *args = rqstp->rq_argp;
498
499	return svcxdr_decode_nfs_fh3(xdr, &args->fh);
500}
501
502bool
503nfs3svc_decode_sattrargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
504{
505	struct nfsd3_sattrargs *args = rqstp->rq_argp;
506
507	return svcxdr_decode_nfs_fh3(xdr, &args->fh) &&
508		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs) &&
509		svcxdr_decode_sattrguard3(xdr, args);
510}
511
512bool
513nfs3svc_decode_diropargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
514{
515	struct nfsd3_diropargs *args = rqstp->rq_argp;
516
517	return svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len);
518}
519
520bool
521nfs3svc_decode_accessargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
522{
523	struct nfsd3_accessargs *args = rqstp->rq_argp;
524
525	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
526		return false;
527	if (xdr_stream_decode_u32(xdr, &args->access) < 0)
528		return false;
529
530	return true;
531}
532
533bool
534nfs3svc_decode_readargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
535{
536	struct nfsd3_readargs *args = rqstp->rq_argp;
537
538	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
539		return false;
540	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
541		return false;
542	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
543		return false;
544
545	return true;
546}
547
548bool
549nfs3svc_decode_writeargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
550{
551	struct nfsd3_writeargs *args = rqstp->rq_argp;
552	u32 max_blocksize = svc_max_payload(rqstp);
553
554	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
555		return false;
556	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
557		return false;
558	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
559		return false;
560	if (xdr_stream_decode_u32(xdr, &args->stable) < 0)
561		return false;
562
563	/* opaque data */
564	if (xdr_stream_decode_u32(xdr, &args->len) < 0)
565		return false;
566
567	/* request sanity */
568	if (args->count != args->len)
569		return false;
570	if (args->count > max_blocksize) {
571		args->count = max_blocksize;
572		args->len = max_blocksize;
573	}
574
575	return xdr_stream_subsegment(xdr, &args->payload, args->count);
576}
577
578bool
579nfs3svc_decode_createargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
580{
581	struct nfsd3_createargs *args = rqstp->rq_argp;
582
583	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
584		return false;
585	if (xdr_stream_decode_u32(xdr, &args->createmode) < 0)
586		return false;
587	switch (args->createmode) {
588	case NFS3_CREATE_UNCHECKED:
589	case NFS3_CREATE_GUARDED:
590		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
591	case NFS3_CREATE_EXCLUSIVE:
592		args->verf = xdr_inline_decode(xdr, NFS3_CREATEVERFSIZE);
593		if (!args->verf)
594			return false;
595		break;
596	default:
597		return false;
598	}
599	return true;
600}
601
602bool
603nfs3svc_decode_mkdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
604{
605	struct nfsd3_createargs *args = rqstp->rq_argp;
606
607	return svcxdr_decode_diropargs3(xdr, &args->fh,
608					&args->name, &args->len) &&
609		svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
610}
611
612bool
613nfs3svc_decode_symlinkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
614{
615	struct nfsd3_symlinkargs *args = rqstp->rq_argp;
616	struct kvec *head = rqstp->rq_arg.head;
617
618	if (!svcxdr_decode_diropargs3(xdr, &args->ffh, &args->fname, &args->flen))
619		return false;
620	if (!svcxdr_decode_sattr3(rqstp, xdr, &args->attrs))
621		return false;
622	if (xdr_stream_decode_u32(xdr, &args->tlen) < 0)
623		return false;
624
625	/* symlink_data */
626	args->first.iov_len = head->iov_len - xdr_stream_pos(xdr);
627	args->first.iov_base = xdr_inline_decode(xdr, args->tlen);
628	return args->first.iov_base != NULL;
629}
630
631bool
632nfs3svc_decode_mknodargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
633{
634	struct nfsd3_mknodargs *args = rqstp->rq_argp;
635
636	if (!svcxdr_decode_diropargs3(xdr, &args->fh, &args->name, &args->len))
637		return false;
638	if (xdr_stream_decode_u32(xdr, &args->ftype) < 0)
639		return false;
640	switch (args->ftype) {
641	case NF3CHR:
642	case NF3BLK:
643		return svcxdr_decode_devicedata3(rqstp, xdr, args);
644	case NF3SOCK:
645	case NF3FIFO:
646		return svcxdr_decode_sattr3(rqstp, xdr, &args->attrs);
647	case NF3REG:
648	case NF3DIR:
649	case NF3LNK:
650		/* Valid XDR but illegal file types */
651		break;
652	default:
653		return false;
654	}
655
656	return true;
657}
658
659bool
660nfs3svc_decode_renameargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
661{
662	struct nfsd3_renameargs *args = rqstp->rq_argp;
663
664	return svcxdr_decode_diropargs3(xdr, &args->ffh,
665					&args->fname, &args->flen) &&
666		svcxdr_decode_diropargs3(xdr, &args->tfh,
667					 &args->tname, &args->tlen);
668}
669
670bool
671nfs3svc_decode_linkargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
672{
673	struct nfsd3_linkargs *args = rqstp->rq_argp;
674
675	return svcxdr_decode_nfs_fh3(xdr, &args->ffh) &&
676		svcxdr_decode_diropargs3(xdr, &args->tfh,
677					 &args->tname, &args->tlen);
678}
679
680bool
681nfs3svc_decode_readdirargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
682{
683	struct nfsd3_readdirargs *args = rqstp->rq_argp;
684
685	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
686		return false;
687	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
688		return false;
689	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
690	if (!args->verf)
691		return false;
692	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
693		return false;
694
695	return true;
696}
697
698bool
699nfs3svc_decode_readdirplusargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
700{
701	struct nfsd3_readdirargs *args = rqstp->rq_argp;
702	u32 dircount;
703
704	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
705		return false;
706	if (xdr_stream_decode_u64(xdr, &args->cookie) < 0)
707		return false;
708	args->verf = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
709	if (!args->verf)
710		return false;
711	/* dircount is ignored */
712	if (xdr_stream_decode_u32(xdr, &dircount) < 0)
713		return false;
714	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
715		return false;
716
717	return true;
718}
719
720bool
721nfs3svc_decode_commitargs(struct svc_rqst *rqstp, struct xdr_stream *xdr)
722{
723	struct nfsd3_commitargs *args = rqstp->rq_argp;
724
725	if (!svcxdr_decode_nfs_fh3(xdr, &args->fh))
726		return false;
727	if (xdr_stream_decode_u64(xdr, &args->offset) < 0)
728		return false;
729	if (xdr_stream_decode_u32(xdr, &args->count) < 0)
730		return false;
731
732	return true;
733}
734
735/*
736 * XDR encode functions
737 */
738
739/* GETATTR */
740bool
741nfs3svc_encode_getattrres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
742{
743	struct nfsd3_attrstat *resp = rqstp->rq_resp;
744
745	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
746		return false;
747	switch (resp->status) {
748	case nfs_ok:
749		lease_get_mtime(d_inode(resp->fh.fh_dentry), &resp->stat.mtime);
750		if (!svcxdr_encode_fattr3(rqstp, xdr, &resp->fh, &resp->stat))
751			return false;
752		break;
753	}
754
755	return true;
756}
757
758/* SETATTR, REMOVE, RMDIR */
759bool
760nfs3svc_encode_wccstat(struct svc_rqst *rqstp, struct xdr_stream *xdr)
761{
762	struct nfsd3_attrstat *resp = rqstp->rq_resp;
763
764	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
765		svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh);
766}
767
768/* LOOKUP */
769bool
770nfs3svc_encode_lookupres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
771{
772	struct nfsd3_diropres *resp = rqstp->rq_resp;
773
774	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
775		return false;
776	switch (resp->status) {
777	case nfs_ok:
778		if (!svcxdr_encode_nfs_fh3(xdr, &resp->fh))
779			return false;
780		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
781			return false;
782		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
783			return false;
784		break;
785	default:
786		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->dirfh))
787			return false;
788	}
789
790	return true;
791}
792
793/* ACCESS */
794bool
795nfs3svc_encode_accessres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
796{
797	struct nfsd3_accessres *resp = rqstp->rq_resp;
798
799	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
800		return false;
801	switch (resp->status) {
802	case nfs_ok:
803		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
804			return false;
805		if (xdr_stream_encode_u32(xdr, resp->access) < 0)
806			return false;
807		break;
808	default:
809		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
810			return false;
811	}
812
813	return true;
814}
815
816/* READLINK */
817bool
818nfs3svc_encode_readlinkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
819{
820	struct nfsd3_readlinkres *resp = rqstp->rq_resp;
821	struct kvec *head = rqstp->rq_res.head;
822
823	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
824		return false;
825	switch (resp->status) {
826	case nfs_ok:
827		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
828			return false;
829		if (xdr_stream_encode_u32(xdr, resp->len) < 0)
830			return false;
831		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages, 0,
832					   resp->len);
833		if (svc_encode_result_payload(rqstp, head->iov_len, resp->len) < 0)
834			return false;
835		break;
836	default:
837		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
838			return false;
839	}
840
841	return true;
842}
843
844/* READ */
845bool
846nfs3svc_encode_readres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
847{
848	struct nfsd3_readres *resp = rqstp->rq_resp;
849	struct kvec *head = rqstp->rq_res.head;
850
851	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
852		return false;
853	switch (resp->status) {
854	case nfs_ok:
855		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
856			return false;
857		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
858			return false;
859		if (xdr_stream_encode_bool(xdr, resp->eof) < 0)
860			return false;
861		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
862			return false;
863		svcxdr_encode_opaque_pages(rqstp, xdr, resp->pages,
864					   rqstp->rq_res.page_base,
865					   resp->count);
866		if (svc_encode_result_payload(rqstp, head->iov_len, resp->count) < 0)
867			return false;
868		break;
869	default:
870		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
871			return false;
872	}
873
874	return true;
875}
876
877/* WRITE */
878bool
879nfs3svc_encode_writeres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
880{
881	struct nfsd3_writeres *resp = rqstp->rq_resp;
882
883	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
884		return false;
885	switch (resp->status) {
886	case nfs_ok:
887		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
888			return false;
889		if (xdr_stream_encode_u32(xdr, resp->count) < 0)
890			return false;
891		if (xdr_stream_encode_u32(xdr, resp->committed) < 0)
892			return false;
893		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
894			return false;
895		break;
896	default:
897		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
898			return false;
899	}
900
901	return true;
902}
903
904/* CREATE, MKDIR, SYMLINK, MKNOD */
905bool
906nfs3svc_encode_createres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
907{
908	struct nfsd3_diropres *resp = rqstp->rq_resp;
909
910	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
911		return false;
912	switch (resp->status) {
913	case nfs_ok:
914		if (!svcxdr_encode_post_op_fh3(xdr, &resp->fh))
915			return false;
916		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
917			return false;
918		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
919			return false;
920		break;
921	default:
922		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->dirfh))
923			return false;
924	}
925
926	return true;
927}
928
929/* RENAME */
930bool
931nfs3svc_encode_renameres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
932{
933	struct nfsd3_renameres *resp = rqstp->rq_resp;
934
935	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
936		svcxdr_encode_wcc_data(rqstp, xdr, &resp->ffh) &&
937		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
938}
939
940/* LINK */
941bool
942nfs3svc_encode_linkres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
943{
944	struct nfsd3_linkres *resp = rqstp->rq_resp;
945
946	return svcxdr_encode_nfsstat3(xdr, resp->status) &&
947		svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh) &&
948		svcxdr_encode_wcc_data(rqstp, xdr, &resp->tfh);
949}
950
951/* READDIR */
952bool
953nfs3svc_encode_readdirres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
954{
955	struct nfsd3_readdirres *resp = rqstp->rq_resp;
956	struct xdr_buf *dirlist = &resp->dirlist;
957
958	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
959		return false;
960	switch (resp->status) {
961	case nfs_ok:
962		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
963			return false;
964		if (!svcxdr_encode_cookieverf3(xdr, resp->verf))
965			return false;
966		svcxdr_encode_opaque_pages(rqstp, xdr, dirlist->pages, 0,
967					   dirlist->len);
968		/* no more entries */
969		if (xdr_stream_encode_item_absent(xdr) < 0)
970			return false;
971		if (xdr_stream_encode_bool(xdr, resp->common.err == nfserr_eof) < 0)
972			return false;
973		break;
974	default:
975		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &resp->fh))
976			return false;
977	}
978
979	return true;
980}
981
982static __be32
983compose_entry_fh(struct nfsd3_readdirres *cd, struct svc_fh *fhp,
984		 const char *name, int namlen, u64 ino)
985{
986	struct svc_export	*exp;
987	struct dentry		*dparent, *dchild;
988	__be32 rv = nfserr_noent;
989
990	dparent = cd->fh.fh_dentry;
991	exp  = cd->fh.fh_export;
992
993	if (isdotent(name, namlen)) {
994		if (namlen == 2) {
995			dchild = dget_parent(dparent);
996			/*
997			 * Don't return filehandle for ".." if we're at
998			 * the filesystem or export root:
999			 */
1000			if (dchild == dparent)
1001				goto out;
1002			if (dparent == exp->ex_path.dentry)
1003				goto out;
1004		} else
1005			dchild = dget(dparent);
1006	} else
1007		dchild = lookup_positive_unlocked(name, dparent, namlen);
1008	if (IS_ERR(dchild))
1009		return rv;
1010	if (d_mountpoint(dchild))
1011		goto out;
1012	if (dchild->d_inode->i_ino != ino)
1013		goto out;
1014	rv = fh_compose(fhp, exp, dchild, &cd->fh);
1015out:
1016	dput(dchild);
1017	return rv;
1018}
1019
1020/**
1021 * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1022 * @resp: readdir result context
1023 * @offset: offset cookie to encode
1024 *
1025 * The buffer space for the offset cookie has already been reserved
1026 * by svcxdr_encode_entry3_common().
1027 */
1028void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1029{
1030	__be64 cookie = cpu_to_be64(offset);
1031
1032	if (!resp->cookie_offset)
1033		return;
1034	write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1035			       sizeof(cookie));
1036	resp->cookie_offset = 0;
1037}
1038
1039static bool
1040svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1041			    int namlen, loff_t offset, u64 ino)
1042{
1043	struct xdr_buf *dirlist = &resp->dirlist;
1044	struct xdr_stream *xdr = &resp->xdr;
1045
1046	if (xdr_stream_encode_item_present(xdr) < 0)
1047		return false;
1048	/* fileid */
1049	if (xdr_stream_encode_u64(xdr, ino) < 0)
1050		return false;
1051	/* name */
1052	if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1053		return false;
1054	/* cookie */
1055	resp->cookie_offset = dirlist->len;
1056	if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1057		return false;
1058
1059	return true;
1060}
1061
1062/**
1063 * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1064 * @data: directory context
1065 * @name: name of the object to be encoded
1066 * @namlen: length of that name, in bytes
1067 * @offset: the offset of the previous entry
1068 * @ino: the fileid of this entry
1069 * @d_type: unused
1070 *
1071 * Return values:
1072 *   %0: Entry was successfully encoded.
1073 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1074 *
1075 * On exit, the following fields are updated:
1076 *   - resp->xdr
1077 *   - resp->common.err
1078 *   - resp->cookie_offset
1079 */
1080int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1081			  loff_t offset, u64 ino, unsigned int d_type)
1082{
1083	struct readdir_cd *ccd = data;
1084	struct nfsd3_readdirres *resp = container_of(ccd,
1085						     struct nfsd3_readdirres,
1086						     common);
1087	unsigned int starting_length = resp->dirlist.len;
1088
1089	/* The offset cookie for the previous entry */
1090	nfs3svc_encode_cookie3(resp, offset);
1091
1092	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1093		goto out_toosmall;
1094
1095	xdr_commit_encode(&resp->xdr);
1096	resp->common.err = nfs_ok;
1097	return 0;
1098
1099out_toosmall:
1100	resp->cookie_offset = 0;
1101	resp->common.err = nfserr_toosmall;
1102	resp->dirlist.len = starting_length;
1103	return -EINVAL;
1104}
1105
1106static bool
1107svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1108			  int namlen, u64 ino)
1109{
1110	struct xdr_stream *xdr = &resp->xdr;
1111	struct svc_fh *fhp = &resp->scratch;
1112	bool result;
1113
1114	result = false;
1115	fh_init(fhp, NFS3_FHSIZE);
1116	if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1117		goto out_noattrs;
1118
1119	if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1120		goto out;
1121	if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1122		goto out;
1123	result = true;
1124
1125out:
1126	fh_put(fhp);
1127	return result;
1128
1129out_noattrs:
1130	if (xdr_stream_encode_item_absent(xdr) < 0)
1131		return false;
1132	if (xdr_stream_encode_item_absent(xdr) < 0)
1133		return false;
1134	return true;
1135}
1136
1137/**
1138 * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1139 * @data: directory context
1140 * @name: name of the object to be encoded
1141 * @namlen: length of that name, in bytes
1142 * @offset: the offset of the previous entry
1143 * @ino: the fileid of this entry
1144 * @d_type: unused
1145 *
1146 * Return values:
1147 *   %0: Entry was successfully encoded.
1148 *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1149 *
1150 * On exit, the following fields are updated:
1151 *   - resp->xdr
1152 *   - resp->common.err
1153 *   - resp->cookie_offset
1154 */
1155int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1156			      loff_t offset, u64 ino, unsigned int d_type)
1157{
1158	struct readdir_cd *ccd = data;
1159	struct nfsd3_readdirres *resp = container_of(ccd,
1160						     struct nfsd3_readdirres,
1161						     common);
1162	unsigned int starting_length = resp->dirlist.len;
1163
1164	/* The offset cookie for the previous entry */
1165	nfs3svc_encode_cookie3(resp, offset);
1166
1167	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1168		goto out_toosmall;
1169	if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1170		goto out_toosmall;
1171
1172	xdr_commit_encode(&resp->xdr);
1173	resp->common.err = nfs_ok;
1174	return 0;
1175
1176out_toosmall:
1177	resp->cookie_offset = 0;
1178	resp->common.err = nfserr_toosmall;
1179	resp->dirlist.len = starting_length;
1180	return -EINVAL;
1181}
1182
1183static bool
1184svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1185			   const struct nfsd3_fsstatres *resp)
1186{
1187	const struct kstatfs *s = &resp->stats;
1188	u64 bs = s->f_bsize;
1189	__be32 *p;
1190
1191	p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1192	if (!p)
1193		return false;
1194	p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1195	p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1196	p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1197	p = xdr_encode_hyper(p, s->f_files);		/* total inodes */
1198	p = xdr_encode_hyper(p, s->f_ffree);		/* free inodes */
1199	p = xdr_encode_hyper(p, s->f_ffree);		/* user available inodes */
1200	*p = cpu_to_be32(resp->invarsec);		/* mean unchanged time */
1201
1202	return true;
1203}
1204
1205/* FSSTAT */
1206bool
1207nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1208{
1209	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1210
1211	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1212		return false;
1213	switch (resp->status) {
1214	case nfs_ok:
1215		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1216			return false;
1217		if (!svcxdr_encode_fsstat3resok(xdr, resp))
1218			return false;
1219		break;
1220	default:
1221		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1222			return false;
1223	}
1224
1225	return true;
1226}
1227
1228static bool
1229svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1230			   const struct nfsd3_fsinfores *resp)
1231{
1232	__be32 *p;
1233
1234	p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1235	if (!p)
1236		return false;
1237	*p++ = cpu_to_be32(resp->f_rtmax);
1238	*p++ = cpu_to_be32(resp->f_rtpref);
1239	*p++ = cpu_to_be32(resp->f_rtmult);
1240	*p++ = cpu_to_be32(resp->f_wtmax);
1241	*p++ = cpu_to_be32(resp->f_wtpref);
1242	*p++ = cpu_to_be32(resp->f_wtmult);
1243	*p++ = cpu_to_be32(resp->f_dtpref);
1244	p = xdr_encode_hyper(p, resp->f_maxfilesize);
1245	p = encode_nfstime3(p, &nfs3svc_time_delta);
1246	*p = cpu_to_be32(resp->f_properties);
1247
1248	return true;
1249}
1250
1251/* FSINFO */
1252bool
1253nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1254{
1255	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1256
1257	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1258		return false;
1259	switch (resp->status) {
1260	case nfs_ok:
1261		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1262			return false;
1263		if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1264			return false;
1265		break;
1266	default:
1267		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1268			return false;
1269	}
1270
1271	return true;
1272}
1273
1274static bool
1275svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1276			     const struct nfsd3_pathconfres *resp)
1277{
1278	__be32 *p;
1279
1280	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1281	if (!p)
1282		return false;
1283	*p++ = cpu_to_be32(resp->p_link_max);
1284	*p++ = cpu_to_be32(resp->p_name_max);
1285	p = xdr_encode_bool(p, resp->p_no_trunc);
1286	p = xdr_encode_bool(p, resp->p_chown_restricted);
1287	p = xdr_encode_bool(p, resp->p_case_insensitive);
1288	xdr_encode_bool(p, resp->p_case_preserving);
1289
1290	return true;
1291}
1292
1293/* PATHCONF */
1294bool
1295nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1296{
1297	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1298
1299	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1300		return false;
1301	switch (resp->status) {
1302	case nfs_ok:
1303		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1304			return false;
1305		if (!svcxdr_encode_pathconf3resok(xdr, resp))
1306			return false;
1307		break;
1308	default:
1309		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1310			return false;
1311	}
1312
1313	return true;
1314}
1315
1316/* COMMIT */
1317bool
1318nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1319{
1320	struct nfsd3_commitres *resp = rqstp->rq_resp;
1321
1322	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1323		return false;
1324	switch (resp->status) {
1325	case nfs_ok:
1326		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1327			return false;
1328		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1329			return false;
1330		break;
1331	default:
1332		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1333			return false;
1334	}
1335
1336	return true;
1337}
1338
1339/*
1340 * XDR release functions
1341 */
1342void
1343nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1344{
1345	struct nfsd3_attrstat *resp = rqstp->rq_resp;
1346
1347	fh_put(&resp->fh);
1348}
1349
1350void
1351nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1352{
1353	struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1354
1355	fh_put(&resp->fh1);
1356	fh_put(&resp->fh2);
1357}
1358