xref: /linux/fs/nfsd/nfs3xdr.c (revision 79790b6818e96c58fe2bffee1b418c16e64e7b80)
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 *
encode_nfstime3(__be32 * p,const struct timespec64 * time)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
svcxdr_decode_nfstime3(struct xdr_stream * xdr,struct timespec64 * timep)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
svcxdr_decode_nfs_fh3(struct xdr_stream * xdr,struct svc_fh * fhp)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
svcxdr_encode_nfsstat3(struct xdr_stream * xdr,__be32 status)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
svcxdr_encode_nfs_fh3(struct xdr_stream * xdr,const struct svc_fh * fhp)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
svcxdr_encode_post_op_fh3(struct xdr_stream * xdr,const struct svc_fh * fhp)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
svcxdr_encode_cookieverf3(struct xdr_stream * xdr,const __be32 * verf)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
svcxdr_encode_writeverf3(struct xdr_stream * xdr,const __be32 * verf)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
svcxdr_decode_filename3(struct xdr_stream * xdr,char ** name,unsigned int * len)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
svcxdr_decode_diropargs3(struct xdr_stream * xdr,struct svc_fh * fhp,char ** name,unsigned int * len)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
svcxdr_decode_sattr3(struct svc_rqst * rqstp,struct xdr_stream * xdr,struct iattr * iap)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
svcxdr_decode_sattrguard3(struct xdr_stream * xdr,struct nfsd3_sattrargs * args)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
svcxdr_decode_specdata3(struct xdr_stream * xdr,struct nfsd3_mknodargs * args)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
svcxdr_decode_devicedata3(struct svc_rqst * rqstp,struct xdr_stream * xdr,struct nfsd3_mknodargs * args)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
svcxdr_encode_fattr3(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp,const struct kstat * stat)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
svcxdr_encode_wcc_attr(struct xdr_stream * xdr,const struct svc_fh * fhp)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
svcxdr_encode_pre_op_attr(struct xdr_stream * xdr,const struct svc_fh * fhp)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
svcxdr_encode_post_op_attr(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp)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
svcxdr_encode_wcc_data(struct svc_rqst * rqstp,struct xdr_stream * xdr,const struct svc_fh * fhp)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
nfs3svc_decode_fhandleargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_sattrargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_diropargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_accessargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_readargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_writeargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_createargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_mkdirargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_symlinkargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_mknodargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_renameargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_linkargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_readdirargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_readdirplusargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_decode_commitargs(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_getattrres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_wccstat(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_lookupres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_accessres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_readlinkres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_readres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_writeres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_createres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_renameres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_linkres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
nfs3svc_encode_readdirres(struct svc_rqst * rqstp,struct xdr_stream * xdr)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
compose_entry_fh(struct nfsd3_readdirres * cd,struct svc_fh * fhp,const char * name,int namlen,u64 ino)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_positive_unlocked(name, dparent, namlen);
1005 	if (IS_ERR(dchild))
1006 		return rv;
1007 	if (d_mountpoint(dchild))
1008 		goto out;
1009 	if (dchild->d_inode->i_ino != ino)
1010 		goto out;
1011 	rv = fh_compose(fhp, exp, dchild, &cd->fh);
1012 out:
1013 	dput(dchild);
1014 	return rv;
1015 }
1016 
1017 /**
1018  * nfs3svc_encode_cookie3 - Encode a directory offset cookie
1019  * @resp: readdir result context
1020  * @offset: offset cookie to encode
1021  *
1022  * The buffer space for the offset cookie has already been reserved
1023  * by svcxdr_encode_entry3_common().
1024  */
nfs3svc_encode_cookie3(struct nfsd3_readdirres * resp,u64 offset)1025 void nfs3svc_encode_cookie3(struct nfsd3_readdirres *resp, u64 offset)
1026 {
1027 	__be64 cookie = cpu_to_be64(offset);
1028 
1029 	if (!resp->cookie_offset)
1030 		return;
1031 	write_bytes_to_xdr_buf(&resp->dirlist, resp->cookie_offset, &cookie,
1032 			       sizeof(cookie));
1033 	resp->cookie_offset = 0;
1034 }
1035 
1036 static bool
svcxdr_encode_entry3_common(struct nfsd3_readdirres * resp,const char * name,int namlen,loff_t offset,u64 ino)1037 svcxdr_encode_entry3_common(struct nfsd3_readdirres *resp, const char *name,
1038 			    int namlen, loff_t offset, u64 ino)
1039 {
1040 	struct xdr_buf *dirlist = &resp->dirlist;
1041 	struct xdr_stream *xdr = &resp->xdr;
1042 
1043 	if (xdr_stream_encode_item_present(xdr) < 0)
1044 		return false;
1045 	/* fileid */
1046 	if (xdr_stream_encode_u64(xdr, ino) < 0)
1047 		return false;
1048 	/* name */
1049 	if (xdr_stream_encode_opaque(xdr, name, min(namlen, NFS3_MAXNAMLEN)) < 0)
1050 		return false;
1051 	/* cookie */
1052 	resp->cookie_offset = dirlist->len;
1053 	if (xdr_stream_encode_u64(xdr, OFFSET_MAX) < 0)
1054 		return false;
1055 
1056 	return true;
1057 }
1058 
1059 /**
1060  * nfs3svc_encode_entry3 - encode one NFSv3 READDIR entry
1061  * @data: directory context
1062  * @name: name of the object to be encoded
1063  * @namlen: length of that name, in bytes
1064  * @offset: the offset of the previous entry
1065  * @ino: the fileid of this entry
1066  * @d_type: unused
1067  *
1068  * Return values:
1069  *   %0: Entry was successfully encoded.
1070  *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1071  *
1072  * On exit, the following fields are updated:
1073  *   - resp->xdr
1074  *   - resp->common.err
1075  *   - resp->cookie_offset
1076  */
nfs3svc_encode_entry3(void * data,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)1077 int nfs3svc_encode_entry3(void *data, const char *name, int namlen,
1078 			  loff_t offset, u64 ino, unsigned int d_type)
1079 {
1080 	struct readdir_cd *ccd = data;
1081 	struct nfsd3_readdirres *resp = container_of(ccd,
1082 						     struct nfsd3_readdirres,
1083 						     common);
1084 	unsigned int starting_length = resp->dirlist.len;
1085 
1086 	/* The offset cookie for the previous entry */
1087 	nfs3svc_encode_cookie3(resp, offset);
1088 
1089 	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1090 		goto out_toosmall;
1091 
1092 	xdr_commit_encode(&resp->xdr);
1093 	resp->common.err = nfs_ok;
1094 	return 0;
1095 
1096 out_toosmall:
1097 	resp->cookie_offset = 0;
1098 	resp->common.err = nfserr_toosmall;
1099 	resp->dirlist.len = starting_length;
1100 	return -EINVAL;
1101 }
1102 
1103 static bool
svcxdr_encode_entry3_plus(struct nfsd3_readdirres * resp,const char * name,int namlen,u64 ino)1104 svcxdr_encode_entry3_plus(struct nfsd3_readdirres *resp, const char *name,
1105 			  int namlen, u64 ino)
1106 {
1107 	struct xdr_stream *xdr = &resp->xdr;
1108 	struct svc_fh *fhp = &resp->scratch;
1109 	bool result;
1110 
1111 	result = false;
1112 	fh_init(fhp, NFS3_FHSIZE);
1113 	if (compose_entry_fh(resp, fhp, name, namlen, ino) != nfs_ok)
1114 		goto out_noattrs;
1115 
1116 	if (!svcxdr_encode_post_op_attr(resp->rqstp, xdr, fhp))
1117 		goto out;
1118 	if (!svcxdr_encode_post_op_fh3(xdr, fhp))
1119 		goto out;
1120 	result = true;
1121 
1122 out:
1123 	fh_put(fhp);
1124 	return result;
1125 
1126 out_noattrs:
1127 	if (xdr_stream_encode_item_absent(xdr) < 0)
1128 		return false;
1129 	if (xdr_stream_encode_item_absent(xdr) < 0)
1130 		return false;
1131 	return true;
1132 }
1133 
1134 /**
1135  * nfs3svc_encode_entryplus3 - encode one NFSv3 READDIRPLUS entry
1136  * @data: directory context
1137  * @name: name of the object to be encoded
1138  * @namlen: length of that name, in bytes
1139  * @offset: the offset of the previous entry
1140  * @ino: the fileid of this entry
1141  * @d_type: unused
1142  *
1143  * Return values:
1144  *   %0: Entry was successfully encoded.
1145  *   %-EINVAL: An encoding problem occured, secondary status code in resp->common.err
1146  *
1147  * On exit, the following fields are updated:
1148  *   - resp->xdr
1149  *   - resp->common.err
1150  *   - resp->cookie_offset
1151  */
nfs3svc_encode_entryplus3(void * data,const char * name,int namlen,loff_t offset,u64 ino,unsigned int d_type)1152 int nfs3svc_encode_entryplus3(void *data, const char *name, int namlen,
1153 			      loff_t offset, u64 ino, unsigned int d_type)
1154 {
1155 	struct readdir_cd *ccd = data;
1156 	struct nfsd3_readdirres *resp = container_of(ccd,
1157 						     struct nfsd3_readdirres,
1158 						     common);
1159 	unsigned int starting_length = resp->dirlist.len;
1160 
1161 	/* The offset cookie for the previous entry */
1162 	nfs3svc_encode_cookie3(resp, offset);
1163 
1164 	if (!svcxdr_encode_entry3_common(resp, name, namlen, offset, ino))
1165 		goto out_toosmall;
1166 	if (!svcxdr_encode_entry3_plus(resp, name, namlen, ino))
1167 		goto out_toosmall;
1168 
1169 	xdr_commit_encode(&resp->xdr);
1170 	resp->common.err = nfs_ok;
1171 	return 0;
1172 
1173 out_toosmall:
1174 	resp->cookie_offset = 0;
1175 	resp->common.err = nfserr_toosmall;
1176 	resp->dirlist.len = starting_length;
1177 	return -EINVAL;
1178 }
1179 
1180 static bool
svcxdr_encode_fsstat3resok(struct xdr_stream * xdr,const struct nfsd3_fsstatres * resp)1181 svcxdr_encode_fsstat3resok(struct xdr_stream *xdr,
1182 			   const struct nfsd3_fsstatres *resp)
1183 {
1184 	const struct kstatfs *s = &resp->stats;
1185 	u64 bs = s->f_bsize;
1186 	__be32 *p;
1187 
1188 	p = xdr_reserve_space(xdr, XDR_UNIT * 13);
1189 	if (!p)
1190 		return false;
1191 	p = xdr_encode_hyper(p, bs * s->f_blocks);	/* total bytes */
1192 	p = xdr_encode_hyper(p, bs * s->f_bfree);	/* free bytes */
1193 	p = xdr_encode_hyper(p, bs * s->f_bavail);	/* user available bytes */
1194 	p = xdr_encode_hyper(p, s->f_files);		/* total inodes */
1195 	p = xdr_encode_hyper(p, s->f_ffree);		/* free inodes */
1196 	p = xdr_encode_hyper(p, s->f_ffree);		/* user available inodes */
1197 	*p = cpu_to_be32(resp->invarsec);		/* mean unchanged time */
1198 
1199 	return true;
1200 }
1201 
1202 /* FSSTAT */
1203 bool
nfs3svc_encode_fsstatres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1204 nfs3svc_encode_fsstatres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1205 {
1206 	struct nfsd3_fsstatres *resp = rqstp->rq_resp;
1207 
1208 	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1209 		return false;
1210 	switch (resp->status) {
1211 	case nfs_ok:
1212 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1213 			return false;
1214 		if (!svcxdr_encode_fsstat3resok(xdr, resp))
1215 			return false;
1216 		break;
1217 	default:
1218 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1219 			return false;
1220 	}
1221 
1222 	return true;
1223 }
1224 
1225 static bool
svcxdr_encode_fsinfo3resok(struct xdr_stream * xdr,const struct nfsd3_fsinfores * resp)1226 svcxdr_encode_fsinfo3resok(struct xdr_stream *xdr,
1227 			   const struct nfsd3_fsinfores *resp)
1228 {
1229 	__be32 *p;
1230 
1231 	p = xdr_reserve_space(xdr, XDR_UNIT * 12);
1232 	if (!p)
1233 		return false;
1234 	*p++ = cpu_to_be32(resp->f_rtmax);
1235 	*p++ = cpu_to_be32(resp->f_rtpref);
1236 	*p++ = cpu_to_be32(resp->f_rtmult);
1237 	*p++ = cpu_to_be32(resp->f_wtmax);
1238 	*p++ = cpu_to_be32(resp->f_wtpref);
1239 	*p++ = cpu_to_be32(resp->f_wtmult);
1240 	*p++ = cpu_to_be32(resp->f_dtpref);
1241 	p = xdr_encode_hyper(p, resp->f_maxfilesize);
1242 	p = encode_nfstime3(p, &nfs3svc_time_delta);
1243 	*p = cpu_to_be32(resp->f_properties);
1244 
1245 	return true;
1246 }
1247 
1248 /* FSINFO */
1249 bool
nfs3svc_encode_fsinfores(struct svc_rqst * rqstp,struct xdr_stream * xdr)1250 nfs3svc_encode_fsinfores(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1251 {
1252 	struct nfsd3_fsinfores *resp = rqstp->rq_resp;
1253 
1254 	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1255 		return false;
1256 	switch (resp->status) {
1257 	case nfs_ok:
1258 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1259 			return false;
1260 		if (!svcxdr_encode_fsinfo3resok(xdr, resp))
1261 			return false;
1262 		break;
1263 	default:
1264 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1265 			return false;
1266 	}
1267 
1268 	return true;
1269 }
1270 
1271 static bool
svcxdr_encode_pathconf3resok(struct xdr_stream * xdr,const struct nfsd3_pathconfres * resp)1272 svcxdr_encode_pathconf3resok(struct xdr_stream *xdr,
1273 			     const struct nfsd3_pathconfres *resp)
1274 {
1275 	__be32 *p;
1276 
1277 	p = xdr_reserve_space(xdr, XDR_UNIT * 6);
1278 	if (!p)
1279 		return false;
1280 	*p++ = cpu_to_be32(resp->p_link_max);
1281 	*p++ = cpu_to_be32(resp->p_name_max);
1282 	p = xdr_encode_bool(p, resp->p_no_trunc);
1283 	p = xdr_encode_bool(p, resp->p_chown_restricted);
1284 	p = xdr_encode_bool(p, resp->p_case_insensitive);
1285 	xdr_encode_bool(p, resp->p_case_preserving);
1286 
1287 	return true;
1288 }
1289 
1290 /* PATHCONF */
1291 bool
nfs3svc_encode_pathconfres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1292 nfs3svc_encode_pathconfres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1293 {
1294 	struct nfsd3_pathconfres *resp = rqstp->rq_resp;
1295 
1296 	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1297 		return false;
1298 	switch (resp->status) {
1299 	case nfs_ok:
1300 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1301 			return false;
1302 		if (!svcxdr_encode_pathconf3resok(xdr, resp))
1303 			return false;
1304 		break;
1305 	default:
1306 		if (!svcxdr_encode_post_op_attr(rqstp, xdr, &nfs3svc_null_fh))
1307 			return false;
1308 	}
1309 
1310 	return true;
1311 }
1312 
1313 /* COMMIT */
1314 bool
nfs3svc_encode_commitres(struct svc_rqst * rqstp,struct xdr_stream * xdr)1315 nfs3svc_encode_commitres(struct svc_rqst *rqstp, struct xdr_stream *xdr)
1316 {
1317 	struct nfsd3_commitres *resp = rqstp->rq_resp;
1318 
1319 	if (!svcxdr_encode_nfsstat3(xdr, resp->status))
1320 		return false;
1321 	switch (resp->status) {
1322 	case nfs_ok:
1323 		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1324 			return false;
1325 		if (!svcxdr_encode_writeverf3(xdr, resp->verf))
1326 			return false;
1327 		break;
1328 	default:
1329 		if (!svcxdr_encode_wcc_data(rqstp, xdr, &resp->fh))
1330 			return false;
1331 	}
1332 
1333 	return true;
1334 }
1335 
1336 /*
1337  * XDR release functions
1338  */
1339 void
nfs3svc_release_fhandle(struct svc_rqst * rqstp)1340 nfs3svc_release_fhandle(struct svc_rqst *rqstp)
1341 {
1342 	struct nfsd3_attrstat *resp = rqstp->rq_resp;
1343 
1344 	fh_put(&resp->fh);
1345 }
1346 
1347 void
nfs3svc_release_fhandle2(struct svc_rqst * rqstp)1348 nfs3svc_release_fhandle2(struct svc_rqst *rqstp)
1349 {
1350 	struct nfsd3_fhandle_pair *resp = rqstp->rq_resp;
1351 
1352 	fh_put(&resp->fh1);
1353 	fh_put(&resp->fh2);
1354 }
1355