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