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