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