xref: /openbmc/linux/fs/nfs/nfs3xdr.c (revision e868d61272caa648214046a096e5a6bfc068dc8c)
1 /*
2  * linux/fs/nfs/nfs3xdr.c
3  *
4  * XDR functions to encode/decode NFSv3 RPC arguments and results.
5  *
6  * Copyright (C) 1996, 1997 Olaf Kirch
7  */
8 
9 #include <linux/param.h>
10 #include <linux/time.h>
11 #include <linux/mm.h>
12 #include <linux/slab.h>
13 #include <linux/utsname.h>
14 #include <linux/errno.h>
15 #include <linux/string.h>
16 #include <linux/in.h>
17 #include <linux/pagemap.h>
18 #include <linux/proc_fs.h>
19 #include <linux/kdev_t.h>
20 #include <linux/sunrpc/clnt.h>
21 #include <linux/nfs.h>
22 #include <linux/nfs3.h>
23 #include <linux/nfs_fs.h>
24 #include <linux/nfsacl.h>
25 #include "internal.h"
26 
27 #define NFSDBG_FACILITY		NFSDBG_XDR
28 
29 /* Mapping from NFS error code to "errno" error code. */
30 #define errno_NFSERR_IO		EIO
31 
32 /*
33  * Declare the space requirements for NFS arguments and replies as
34  * number of 32bit-words
35  */
36 #define NFS3_fhandle_sz		(1+16)
37 #define NFS3_fh_sz		(NFS3_fhandle_sz)	/* shorthand */
38 #define NFS3_sattr_sz		(15)
39 #define NFS3_filename_sz	(1+(NFS3_MAXNAMLEN>>2))
40 #define NFS3_path_sz		(1+(NFS3_MAXPATHLEN>>2))
41 #define NFS3_fattr_sz		(21)
42 #define NFS3_wcc_attr_sz		(6)
43 #define NFS3_pre_op_attr_sz	(1+NFS3_wcc_attr_sz)
44 #define NFS3_post_op_attr_sz	(1+NFS3_fattr_sz)
45 #define NFS3_wcc_data_sz		(NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
46 #define NFS3_fsstat_sz
47 #define NFS3_fsinfo_sz
48 #define NFS3_pathconf_sz
49 #define NFS3_entry_sz		(NFS3_filename_sz+3)
50 
51 #define NFS3_sattrargs_sz	(NFS3_fh_sz+NFS3_sattr_sz+3)
52 #define NFS3_diropargs_sz	(NFS3_fh_sz+NFS3_filename_sz)
53 #define NFS3_accessargs_sz	(NFS3_fh_sz+1)
54 #define NFS3_readlinkargs_sz	(NFS3_fh_sz)
55 #define NFS3_readargs_sz	(NFS3_fh_sz+3)
56 #define NFS3_writeargs_sz	(NFS3_fh_sz+5)
57 #define NFS3_createargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
58 #define NFS3_mkdirargs_sz	(NFS3_diropargs_sz+NFS3_sattr_sz)
59 #define NFS3_symlinkargs_sz	(NFS3_diropargs_sz+1+NFS3_sattr_sz)
60 #define NFS3_mknodargs_sz	(NFS3_diropargs_sz+2+NFS3_sattr_sz)
61 #define NFS3_renameargs_sz	(NFS3_diropargs_sz+NFS3_diropargs_sz)
62 #define NFS3_linkargs_sz		(NFS3_fh_sz+NFS3_diropargs_sz)
63 #define NFS3_readdirargs_sz	(NFS3_fh_sz+2)
64 #define NFS3_commitargs_sz	(NFS3_fh_sz+3)
65 
66 #define NFS3_attrstat_sz	(1+NFS3_fattr_sz)
67 #define NFS3_wccstat_sz		(1+NFS3_wcc_data_sz)
68 #define NFS3_lookupres_sz	(1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69 #define NFS3_accessres_sz	(1+NFS3_post_op_attr_sz+1)
70 #define NFS3_readlinkres_sz	(1+NFS3_post_op_attr_sz+1)
71 #define NFS3_readres_sz		(1+NFS3_post_op_attr_sz+3)
72 #define NFS3_writeres_sz	(1+NFS3_wcc_data_sz+4)
73 #define NFS3_createres_sz	(1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
74 #define NFS3_renameres_sz	(1+(2 * NFS3_wcc_data_sz))
75 #define NFS3_linkres_sz		(1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76 #define NFS3_readdirres_sz	(1+NFS3_post_op_attr_sz+2)
77 #define NFS3_fsstatres_sz	(1+NFS3_post_op_attr_sz+13)
78 #define NFS3_fsinfores_sz	(1+NFS3_post_op_attr_sz+12)
79 #define NFS3_pathconfres_sz	(1+NFS3_post_op_attr_sz+6)
80 #define NFS3_commitres_sz	(1+NFS3_wcc_data_sz+2)
81 
82 #define ACL3_getaclargs_sz	(NFS3_fh_sz+1)
83 #define ACL3_setaclargs_sz	(NFS3_fh_sz+1+2*(2+5*3))
84 #define ACL3_getaclres_sz	(1+NFS3_post_op_attr_sz+1+2*(2+5*3))
85 #define ACL3_setaclres_sz	(1+NFS3_post_op_attr_sz)
86 
87 /*
88  * Map file type to S_IFMT bits
89  */
90 static struct {
91 	unsigned int	mode;
92 	unsigned int	nfs2type;
93 } nfs_type2fmt[] = {
94       { 0,		NFNON	},
95       { S_IFREG,	NFREG	},
96       { S_IFDIR,	NFDIR	},
97       { S_IFBLK,	NFBLK	},
98       { S_IFCHR,	NFCHR	},
99       { S_IFLNK,	NFLNK	},
100       { S_IFSOCK,	NFSOCK	},
101       { S_IFIFO,	NFFIFO	},
102       { 0,		NFBAD	}
103 };
104 
105 /*
106  * Common NFS XDR functions as inlines
107  */
108 static inline __be32 *
109 xdr_encode_fhandle(__be32 *p, struct nfs_fh *fh)
110 {
111 	return xdr_encode_array(p, fh->data, fh->size);
112 }
113 
114 static inline __be32 *
115 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
116 {
117 	if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
118 		memcpy(fh->data, p, fh->size);
119 		return p + XDR_QUADLEN(fh->size);
120 	}
121 	return NULL;
122 }
123 
124 /*
125  * Encode/decode time.
126  */
127 static inline __be32 *
128 xdr_encode_time3(__be32 *p, struct timespec *timep)
129 {
130 	*p++ = htonl(timep->tv_sec);
131 	*p++ = htonl(timep->tv_nsec);
132 	return p;
133 }
134 
135 static inline __be32 *
136 xdr_decode_time3(__be32 *p, struct timespec *timep)
137 {
138 	timep->tv_sec = ntohl(*p++);
139 	timep->tv_nsec = ntohl(*p++);
140 	return p;
141 }
142 
143 static __be32 *
144 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
145 {
146 	unsigned int	type, major, minor;
147 	int		fmode;
148 
149 	type = ntohl(*p++);
150 	if (type >= NF3BAD)
151 		type = NF3BAD;
152 	fmode = nfs_type2fmt[type].mode;
153 	fattr->type = nfs_type2fmt[type].nfs2type;
154 	fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
155 	fattr->nlink = ntohl(*p++);
156 	fattr->uid = ntohl(*p++);
157 	fattr->gid = ntohl(*p++);
158 	p = xdr_decode_hyper(p, &fattr->size);
159 	p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
160 
161 	/* Turn remote device info into Linux-specific dev_t */
162 	major = ntohl(*p++);
163 	minor = ntohl(*p++);
164 	fattr->rdev = MKDEV(major, minor);
165 	if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
166 		fattr->rdev = 0;
167 
168 	p = xdr_decode_hyper(p, &fattr->fsid.major);
169 	fattr->fsid.minor = 0;
170 	p = xdr_decode_hyper(p, &fattr->fileid);
171 	p = xdr_decode_time3(p, &fattr->atime);
172 	p = xdr_decode_time3(p, &fattr->mtime);
173 	p = xdr_decode_time3(p, &fattr->ctime);
174 
175 	/* Update the mode bits */
176 	fattr->valid |= (NFS_ATTR_FATTR | NFS_ATTR_FATTR_V3);
177 	return p;
178 }
179 
180 static inline __be32 *
181 xdr_encode_sattr(__be32 *p, struct iattr *attr)
182 {
183 	if (attr->ia_valid & ATTR_MODE) {
184 		*p++ = xdr_one;
185 		*p++ = htonl(attr->ia_mode & S_IALLUGO);
186 	} else {
187 		*p++ = xdr_zero;
188 	}
189 	if (attr->ia_valid & ATTR_UID) {
190 		*p++ = xdr_one;
191 		*p++ = htonl(attr->ia_uid);
192 	} else {
193 		*p++ = xdr_zero;
194 	}
195 	if (attr->ia_valid & ATTR_GID) {
196 		*p++ = xdr_one;
197 		*p++ = htonl(attr->ia_gid);
198 	} else {
199 		*p++ = xdr_zero;
200 	}
201 	if (attr->ia_valid & ATTR_SIZE) {
202 		*p++ = xdr_one;
203 		p = xdr_encode_hyper(p, (__u64) attr->ia_size);
204 	} else {
205 		*p++ = xdr_zero;
206 	}
207 	if (attr->ia_valid & ATTR_ATIME_SET) {
208 		*p++ = xdr_two;
209 		p = xdr_encode_time3(p, &attr->ia_atime);
210 	} else if (attr->ia_valid & ATTR_ATIME) {
211 		*p++ = xdr_one;
212 	} else {
213 		*p++ = xdr_zero;
214 	}
215 	if (attr->ia_valid & ATTR_MTIME_SET) {
216 		*p++ = xdr_two;
217 		p = xdr_encode_time3(p, &attr->ia_mtime);
218 	} else if (attr->ia_valid & ATTR_MTIME) {
219 		*p++ = xdr_one;
220 	} else {
221 		*p++ = xdr_zero;
222 	}
223 	return p;
224 }
225 
226 static inline __be32 *
227 xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
228 {
229 	p = xdr_decode_hyper(p, &fattr->pre_size);
230 	p = xdr_decode_time3(p, &fattr->pre_mtime);
231 	p = xdr_decode_time3(p, &fattr->pre_ctime);
232 	fattr->valid |= NFS_ATTR_WCC;
233 	return p;
234 }
235 
236 static inline __be32 *
237 xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
238 {
239 	if (*p++)
240 		p = xdr_decode_fattr(p, fattr);
241 	return p;
242 }
243 
244 static inline __be32 *
245 xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
246 {
247 	if (*p++)
248 		return xdr_decode_wcc_attr(p, fattr);
249 	return p;
250 }
251 
252 
253 static inline __be32 *
254 xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
255 {
256 	p = xdr_decode_pre_op_attr(p, fattr);
257 	return xdr_decode_post_op_attr(p, fattr);
258 }
259 
260 /*
261  * NFS encode functions
262  */
263 
264 /*
265  * Encode file handle argument
266  */
267 static int
268 nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
269 {
270 	p = xdr_encode_fhandle(p, fh);
271 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
272 	return 0;
273 }
274 
275 /*
276  * Encode SETATTR arguments
277  */
278 static int
279 nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
280 {
281 	p = xdr_encode_fhandle(p, args->fh);
282 	p = xdr_encode_sattr(p, args->sattr);
283 	*p++ = htonl(args->guard);
284 	if (args->guard)
285 		p = xdr_encode_time3(p, &args->guardtime);
286 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
287 	return 0;
288 }
289 
290 /*
291  * Encode directory ops argument
292  */
293 static int
294 nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
295 {
296 	p = xdr_encode_fhandle(p, args->fh);
297 	p = xdr_encode_array(p, args->name, args->len);
298 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
299 	return 0;
300 }
301 
302 /*
303  * Encode access() argument
304  */
305 static int
306 nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
307 {
308 	p = xdr_encode_fhandle(p, args->fh);
309 	*p++ = htonl(args->access);
310 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
311 	return 0;
312 }
313 
314 /*
315  * Arguments to a READ call. Since we read data directly into the page
316  * cache, we also set up the reply iovec here so that iov[1] points
317  * exactly to the page we want to fetch.
318  */
319 static int
320 nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
321 {
322 	struct rpc_auth	*auth = req->rq_task->tk_auth;
323 	unsigned int replen;
324 	u32 count = args->count;
325 
326 	p = xdr_encode_fhandle(p, args->fh);
327 	p = xdr_encode_hyper(p, args->offset);
328 	*p++ = htonl(count);
329 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
330 
331 	/* Inline the page array */
332 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
333 	xdr_inline_pages(&req->rq_rcv_buf, replen,
334 			 args->pages, args->pgbase, count);
335 	return 0;
336 }
337 
338 /*
339  * Write arguments. Splice the buffer to be written into the iovec.
340  */
341 static int
342 nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
343 {
344 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
345 	u32 count = args->count;
346 
347 	p = xdr_encode_fhandle(p, args->fh);
348 	p = xdr_encode_hyper(p, args->offset);
349 	*p++ = htonl(count);
350 	*p++ = htonl(args->stable);
351 	*p++ = htonl(count);
352 	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
353 
354 	/* Copy the page array */
355 	xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
356 	return 0;
357 }
358 
359 /*
360  * Encode CREATE arguments
361  */
362 static int
363 nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
364 {
365 	p = xdr_encode_fhandle(p, args->fh);
366 	p = xdr_encode_array(p, args->name, args->len);
367 
368 	*p++ = htonl(args->createmode);
369 	if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
370 		*p++ = args->verifier[0];
371 		*p++ = args->verifier[1];
372 	} else
373 		p = xdr_encode_sattr(p, args->sattr);
374 
375 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
376 	return 0;
377 }
378 
379 /*
380  * Encode MKDIR arguments
381  */
382 static int
383 nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
384 {
385 	p = xdr_encode_fhandle(p, args->fh);
386 	p = xdr_encode_array(p, args->name, args->len);
387 	p = xdr_encode_sattr(p, args->sattr);
388 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
389 	return 0;
390 }
391 
392 /*
393  * Encode SYMLINK arguments
394  */
395 static int
396 nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
397 {
398 	p = xdr_encode_fhandle(p, args->fromfh);
399 	p = xdr_encode_array(p, args->fromname, args->fromlen);
400 	p = xdr_encode_sattr(p, args->sattr);
401 	*p++ = htonl(args->pathlen);
402 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
403 
404 	/* Copy the page */
405 	xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
406 	return 0;
407 }
408 
409 /*
410  * Encode MKNOD arguments
411  */
412 static int
413 nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
414 {
415 	p = xdr_encode_fhandle(p, args->fh);
416 	p = xdr_encode_array(p, args->name, args->len);
417 	*p++ = htonl(args->type);
418 	p = xdr_encode_sattr(p, args->sattr);
419 	if (args->type == NF3CHR || args->type == NF3BLK) {
420 		*p++ = htonl(MAJOR(args->rdev));
421 		*p++ = htonl(MINOR(args->rdev));
422 	}
423 
424 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
425 	return 0;
426 }
427 
428 /*
429  * Encode RENAME arguments
430  */
431 static int
432 nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs3_renameargs *args)
433 {
434 	p = xdr_encode_fhandle(p, args->fromfh);
435 	p = xdr_encode_array(p, args->fromname, args->fromlen);
436 	p = xdr_encode_fhandle(p, args->tofh);
437 	p = xdr_encode_array(p, args->toname, args->tolen);
438 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
439 	return 0;
440 }
441 
442 /*
443  * Encode LINK arguments
444  */
445 static int
446 nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
447 {
448 	p = xdr_encode_fhandle(p, args->fromfh);
449 	p = xdr_encode_fhandle(p, args->tofh);
450 	p = xdr_encode_array(p, args->toname, args->tolen);
451 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
452 	return 0;
453 }
454 
455 /*
456  * Encode arguments to readdir call
457  */
458 static int
459 nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
460 {
461 	struct rpc_auth	*auth = req->rq_task->tk_auth;
462 	unsigned int replen;
463 	u32 count = args->count;
464 
465 	p = xdr_encode_fhandle(p, args->fh);
466 	p = xdr_encode_hyper(p, args->cookie);
467 	*p++ = args->verf[0];
468 	*p++ = args->verf[1];
469 	if (args->plus) {
470 		/* readdirplus: need dircount + buffer size.
471 		 * We just make sure we make dircount big enough */
472 		*p++ = htonl(count >> 3);
473 	}
474 	*p++ = htonl(count);
475 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
476 
477 	/* Inline the page array */
478 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
479 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
480 	return 0;
481 }
482 
483 /*
484  * Decode the result of a readdir call.
485  * We just check for syntactical correctness.
486  */
487 static int
488 nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
489 {
490 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
491 	struct kvec *iov = rcvbuf->head;
492 	struct page **page;
493 	int hdrlen, recvd;
494 	int status, nr;
495 	unsigned int len, pglen;
496 	__be32 *entry, *end, *kaddr;
497 
498 	status = ntohl(*p++);
499 	/* Decode post_op_attrs */
500 	p = xdr_decode_post_op_attr(p, res->dir_attr);
501 	if (status)
502 		return -nfs_stat_to_errno(status);
503 	/* Decode verifier cookie */
504 	if (res->verf) {
505 		res->verf[0] = *p++;
506 		res->verf[1] = *p++;
507 	} else {
508 		p += 2;
509 	}
510 
511 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
512 	if (iov->iov_len < hdrlen) {
513 		printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
514 				"length %d > %Zu\n", hdrlen, iov->iov_len);
515 		return -errno_NFSERR_IO;
516 	} else if (iov->iov_len != hdrlen) {
517 		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
518 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
519 	}
520 
521 	pglen = rcvbuf->page_len;
522 	recvd = rcvbuf->len - hdrlen;
523 	if (pglen > recvd)
524 		pglen = recvd;
525 	page = rcvbuf->pages;
526 	kaddr = p = kmap_atomic(*page, KM_USER0);
527 	end = (__be32 *)((char *)p + pglen);
528 	entry = p;
529 	for (nr = 0; *p++; nr++) {
530 		if (p + 3 > end)
531 			goto short_pkt;
532 		p += 2;				/* inode # */
533 		len = ntohl(*p++);		/* string length */
534 		p += XDR_QUADLEN(len) + 2;	/* name + cookie */
535 		if (len > NFS3_MAXNAMLEN) {
536 			printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
537 						len);
538 			goto err_unmap;
539 		}
540 
541 		if (res->plus) {
542 			/* post_op_attr */
543 			if (p + 2 > end)
544 				goto short_pkt;
545 			if (*p++) {
546 				p += 21;
547 				if (p + 1 > end)
548 					goto short_pkt;
549 			}
550 			/* post_op_fh3 */
551 			if (*p++) {
552 				if (p + 1 > end)
553 					goto short_pkt;
554 				len = ntohl(*p++);
555 				if (len > NFS3_FHSIZE) {
556 					printk(KERN_WARNING "NFS: giant filehandle in "
557 						"readdir (len %x)!\n", len);
558 					goto err_unmap;
559 				}
560 				p += XDR_QUADLEN(len);
561 			}
562 		}
563 
564 		if (p + 2 > end)
565 			goto short_pkt;
566 		entry = p;
567 	}
568 	if (!nr && (entry[0] != 0 || entry[1] == 0))
569 		goto short_pkt;
570  out:
571 	kunmap_atomic(kaddr, KM_USER0);
572 	return nr;
573  short_pkt:
574 	entry[0] = entry[1] = 0;
575 	/* truncate listing ? */
576 	if (!nr) {
577 		printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
578 		entry[1] = 1;
579 	}
580 	goto out;
581 err_unmap:
582 	nr = -errno_NFSERR_IO;
583 	goto out;
584 }
585 
586 __be32 *
587 nfs3_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
588 {
589 	struct nfs_entry old = *entry;
590 
591 	if (!*p++) {
592 		if (!*p)
593 			return ERR_PTR(-EAGAIN);
594 		entry->eof = 1;
595 		return ERR_PTR(-EBADCOOKIE);
596 	}
597 
598 	p = xdr_decode_hyper(p, &entry->ino);
599 	entry->len  = ntohl(*p++);
600 	entry->name = (const char *) p;
601 	p += XDR_QUADLEN(entry->len);
602 	entry->prev_cookie = entry->cookie;
603 	p = xdr_decode_hyper(p, &entry->cookie);
604 
605 	if (plus) {
606 		entry->fattr->valid = 0;
607 		p = xdr_decode_post_op_attr(p, entry->fattr);
608 		/* In fact, a post_op_fh3: */
609 		if (*p++) {
610 			p = xdr_decode_fhandle(p, entry->fh);
611 			/* Ugh -- server reply was truncated */
612 			if (p == NULL) {
613 				dprintk("NFS: FH truncated\n");
614 				*entry = old;
615 				return ERR_PTR(-EAGAIN);
616 			}
617 		} else
618 			memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
619 	}
620 
621 	entry->eof = !p[0] && p[1];
622 	return p;
623 }
624 
625 /*
626  * Encode COMMIT arguments
627  */
628 static int
629 nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
630 {
631 	p = xdr_encode_fhandle(p, args->fh);
632 	p = xdr_encode_hyper(p, args->offset);
633 	*p++ = htonl(args->count);
634 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
635 	return 0;
636 }
637 
638 #ifdef CONFIG_NFS_V3_ACL
639 /*
640  * Encode GETACL arguments
641  */
642 static int
643 nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
644 		    struct nfs3_getaclargs *args)
645 {
646 	struct rpc_auth *auth = req->rq_task->tk_auth;
647 	unsigned int replen;
648 
649 	p = xdr_encode_fhandle(p, args->fh);
650 	*p++ = htonl(args->mask);
651 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
652 
653 	if (args->mask & (NFS_ACL | NFS_DFACL)) {
654 		/* Inline the page array */
655 		replen = (RPC_REPHDRSIZE + auth->au_rslack +
656 			  ACL3_getaclres_sz) << 2;
657 		xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
658 				 NFSACL_MAXPAGES << PAGE_SHIFT);
659 	}
660 	return 0;
661 }
662 
663 /*
664  * Encode SETACL arguments
665  */
666 static int
667 nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
668                    struct nfs3_setaclargs *args)
669 {
670 	struct xdr_buf *buf = &req->rq_snd_buf;
671 	unsigned int base, len_in_head, len = nfsacl_size(
672 		(args->mask & NFS_ACL)   ? args->acl_access  : NULL,
673 		(args->mask & NFS_DFACL) ? args->acl_default : NULL);
674 	int count, err;
675 
676 	p = xdr_encode_fhandle(p, NFS_FH(args->inode));
677 	*p++ = htonl(args->mask);
678 	base = (char *)p - (char *)buf->head->iov_base;
679 	/* put as much of the acls into head as possible. */
680 	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
681 	len -= len_in_head;
682 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
683 
684 	for (count = 0; (count << PAGE_SHIFT) < len; count++) {
685 		args->pages[count] = alloc_page(GFP_KERNEL);
686 		if (!args->pages[count]) {
687 			while (count)
688 				__free_page(args->pages[--count]);
689 			return -ENOMEM;
690 		}
691 	}
692 	xdr_encode_pages(buf, args->pages, 0, len);
693 
694 	err = nfsacl_encode(buf, base, args->inode,
695 			    (args->mask & NFS_ACL) ?
696 			    args->acl_access : NULL, 1, 0);
697 	if (err > 0)
698 		err = nfsacl_encode(buf, base + err, args->inode,
699 				    (args->mask & NFS_DFACL) ?
700 				    args->acl_default : NULL, 1,
701 				    NFS_ACL_DEFAULT);
702 	return (err > 0) ? 0 : err;
703 }
704 #endif  /* CONFIG_NFS_V3_ACL */
705 
706 /*
707  * NFS XDR decode functions
708  */
709 
710 /*
711  * Decode attrstat reply.
712  */
713 static int
714 nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
715 {
716 	int	status;
717 
718 	if ((status = ntohl(*p++)))
719 		return -nfs_stat_to_errno(status);
720 	xdr_decode_fattr(p, fattr);
721 	return 0;
722 }
723 
724 /*
725  * Decode status+wcc_data reply
726  * SATTR, REMOVE, RMDIR
727  */
728 static int
729 nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
730 {
731 	int	status;
732 
733 	if ((status = ntohl(*p++)))
734 		status = -nfs_stat_to_errno(status);
735 	xdr_decode_wcc_data(p, fattr);
736 	return status;
737 }
738 
739 /*
740  * Decode LOOKUP reply
741  */
742 static int
743 nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
744 {
745 	int	status;
746 
747 	if ((status = ntohl(*p++))) {
748 		status = -nfs_stat_to_errno(status);
749 	} else {
750 		if (!(p = xdr_decode_fhandle(p, res->fh)))
751 			return -errno_NFSERR_IO;
752 		p = xdr_decode_post_op_attr(p, res->fattr);
753 	}
754 	xdr_decode_post_op_attr(p, res->dir_attr);
755 	return status;
756 }
757 
758 /*
759  * Decode ACCESS reply
760  */
761 static int
762 nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
763 {
764 	int	status = ntohl(*p++);
765 
766 	p = xdr_decode_post_op_attr(p, res->fattr);
767 	if (status)
768 		return -nfs_stat_to_errno(status);
769 	res->access = ntohl(*p++);
770 	return 0;
771 }
772 
773 static int
774 nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
775 {
776 	struct rpc_auth *auth = req->rq_task->tk_auth;
777 	unsigned int replen;
778 
779 	p = xdr_encode_fhandle(p, args->fh);
780 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
781 
782 	/* Inline the page array */
783 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
784 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
785 	return 0;
786 }
787 
788 /*
789  * Decode READLINK reply
790  */
791 static int
792 nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
793 {
794 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
795 	struct kvec *iov = rcvbuf->head;
796 	int hdrlen, len, recvd;
797 	char	*kaddr;
798 	int	status;
799 
800 	status = ntohl(*p++);
801 	p = xdr_decode_post_op_attr(p, fattr);
802 
803 	if (status != 0)
804 		return -nfs_stat_to_errno(status);
805 
806 	/* Convert length of symlink */
807 	len = ntohl(*p++);
808 	if (len >= rcvbuf->page_len || len <= 0) {
809 		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
810 		return -ENAMETOOLONG;
811 	}
812 
813 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
814 	if (iov->iov_len < hdrlen) {
815 		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
816 				"length %d > %Zu\n", hdrlen, iov->iov_len);
817 		return -errno_NFSERR_IO;
818 	} else if (iov->iov_len != hdrlen) {
819 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
820 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
821 	}
822 	recvd = req->rq_rcv_buf.len - hdrlen;
823 	if (recvd < len) {
824 		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
825 				"count %u > recvd %u\n", len, recvd);
826 		return -EIO;
827 	}
828 
829 	/* NULL terminate the string we got */
830 	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
831 	kaddr[len+rcvbuf->page_base] = '\0';
832 	kunmap_atomic(kaddr, KM_USER0);
833 	return 0;
834 }
835 
836 /*
837  * Decode READ reply
838  */
839 static int
840 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
841 {
842 	struct kvec *iov = req->rq_rcv_buf.head;
843 	int	status, count, ocount, recvd, hdrlen;
844 
845 	status = ntohl(*p++);
846 	p = xdr_decode_post_op_attr(p, res->fattr);
847 
848 	if (status != 0)
849 		return -nfs_stat_to_errno(status);
850 
851 	/* Decode reply could and EOF flag. NFSv3 is somewhat redundant
852 	 * in that it puts the count both in the res struct and in the
853 	 * opaque data count. */
854 	count    = ntohl(*p++);
855 	res->eof = ntohl(*p++);
856 	ocount   = ntohl(*p++);
857 
858 	if (ocount != count) {
859 		printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
860 		return -errno_NFSERR_IO;
861 	}
862 
863 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
864 	if (iov->iov_len < hdrlen) {
865 		printk(KERN_WARNING "NFS: READ reply header overflowed:"
866 				"length %d > %Zu\n", hdrlen, iov->iov_len);
867        		return -errno_NFSERR_IO;
868 	} else if (iov->iov_len != hdrlen) {
869 		dprintk("NFS: READ header is short. iovec will be shifted.\n");
870 		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
871 	}
872 
873 	recvd = req->rq_rcv_buf.len - hdrlen;
874 	if (count > recvd) {
875 		printk(KERN_WARNING "NFS: server cheating in read reply: "
876 			"count %d > recvd %d\n", count, recvd);
877 		count = recvd;
878 		res->eof = 0;
879 	}
880 
881 	if (count < res->count)
882 		res->count = count;
883 
884 	return count;
885 }
886 
887 /*
888  * Decode WRITE response
889  */
890 static int
891 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
892 {
893 	int	status;
894 
895 	status = ntohl(*p++);
896 	p = xdr_decode_wcc_data(p, res->fattr);
897 
898 	if (status != 0)
899 		return -nfs_stat_to_errno(status);
900 
901 	res->count = ntohl(*p++);
902 	res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
903 	res->verf->verifier[0] = *p++;
904 	res->verf->verifier[1] = *p++;
905 
906 	return res->count;
907 }
908 
909 /*
910  * Decode a CREATE response
911  */
912 static int
913 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
914 {
915 	int	status;
916 
917 	status = ntohl(*p++);
918 	if (status == 0) {
919 		if (*p++) {
920 			if (!(p = xdr_decode_fhandle(p, res->fh)))
921 				return -errno_NFSERR_IO;
922 			p = xdr_decode_post_op_attr(p, res->fattr);
923 		} else {
924 			memset(res->fh, 0, sizeof(*res->fh));
925 			/* Do decode post_op_attr but set it to NULL */
926 			p = xdr_decode_post_op_attr(p, res->fattr);
927 			res->fattr->valid = 0;
928 		}
929 	} else {
930 		status = -nfs_stat_to_errno(status);
931 	}
932 	p = xdr_decode_wcc_data(p, res->dir_attr);
933 	return status;
934 }
935 
936 /*
937  * Decode RENAME reply
938  */
939 static int
940 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
941 {
942 	int	status;
943 
944 	if ((status = ntohl(*p++)) != 0)
945 		status = -nfs_stat_to_errno(status);
946 	p = xdr_decode_wcc_data(p, res->fromattr);
947 	p = xdr_decode_wcc_data(p, res->toattr);
948 	return status;
949 }
950 
951 /*
952  * Decode LINK reply
953  */
954 static int
955 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
956 {
957 	int	status;
958 
959 	if ((status = ntohl(*p++)) != 0)
960 		status = -nfs_stat_to_errno(status);
961 	p = xdr_decode_post_op_attr(p, res->fattr);
962 	p = xdr_decode_wcc_data(p, res->dir_attr);
963 	return status;
964 }
965 
966 /*
967  * Decode FSSTAT reply
968  */
969 static int
970 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
971 {
972 	int		status;
973 
974 	status = ntohl(*p++);
975 
976 	p = xdr_decode_post_op_attr(p, res->fattr);
977 	if (status != 0)
978 		return -nfs_stat_to_errno(status);
979 
980 	p = xdr_decode_hyper(p, &res->tbytes);
981 	p = xdr_decode_hyper(p, &res->fbytes);
982 	p = xdr_decode_hyper(p, &res->abytes);
983 	p = xdr_decode_hyper(p, &res->tfiles);
984 	p = xdr_decode_hyper(p, &res->ffiles);
985 	p = xdr_decode_hyper(p, &res->afiles);
986 
987 	/* ignore invarsec */
988 	return 0;
989 }
990 
991 /*
992  * Decode FSINFO reply
993  */
994 static int
995 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
996 {
997 	int		status;
998 
999 	status = ntohl(*p++);
1000 
1001 	p = xdr_decode_post_op_attr(p, res->fattr);
1002 	if (status != 0)
1003 		return -nfs_stat_to_errno(status);
1004 
1005 	res->rtmax  = ntohl(*p++);
1006 	res->rtpref = ntohl(*p++);
1007 	res->rtmult = ntohl(*p++);
1008 	res->wtmax  = ntohl(*p++);
1009 	res->wtpref = ntohl(*p++);
1010 	res->wtmult = ntohl(*p++);
1011 	res->dtpref = ntohl(*p++);
1012 	p = xdr_decode_hyper(p, &res->maxfilesize);
1013 
1014 	/* ignore time_delta and properties */
1015 	res->lease_time = 0;
1016 	return 0;
1017 }
1018 
1019 /*
1020  * Decode PATHCONF reply
1021  */
1022 static int
1023 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1024 {
1025 	int		status;
1026 
1027 	status = ntohl(*p++);
1028 
1029 	p = xdr_decode_post_op_attr(p, res->fattr);
1030 	if (status != 0)
1031 		return -nfs_stat_to_errno(status);
1032 	res->max_link = ntohl(*p++);
1033 	res->max_namelen = ntohl(*p++);
1034 
1035 	/* ignore remaining fields */
1036 	return 0;
1037 }
1038 
1039 /*
1040  * Decode COMMIT reply
1041  */
1042 static int
1043 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1044 {
1045 	int		status;
1046 
1047 	status = ntohl(*p++);
1048 	p = xdr_decode_wcc_data(p, res->fattr);
1049 	if (status != 0)
1050 		return -nfs_stat_to_errno(status);
1051 
1052 	res->verf->verifier[0] = *p++;
1053 	res->verf->verifier[1] = *p++;
1054 	return 0;
1055 }
1056 
1057 #ifdef CONFIG_NFS_V3_ACL
1058 /*
1059  * Decode GETACL reply
1060  */
1061 static int
1062 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1063 		   struct nfs3_getaclres *res)
1064 {
1065 	struct xdr_buf *buf = &req->rq_rcv_buf;
1066 	int status = ntohl(*p++);
1067 	struct posix_acl **acl;
1068 	unsigned int *aclcnt;
1069 	int err, base;
1070 
1071 	if (status != 0)
1072 		return -nfs_stat_to_errno(status);
1073 	p = xdr_decode_post_op_attr(p, res->fattr);
1074 	res->mask = ntohl(*p++);
1075 	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1076 		return -EINVAL;
1077 	base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1078 
1079 	acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1080 	aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1081 	err = nfsacl_decode(buf, base, aclcnt, acl);
1082 
1083 	acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1084 	aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1085 	if (err > 0)
1086 		err = nfsacl_decode(buf, base + err, aclcnt, acl);
1087 	return (err > 0) ? 0 : err;
1088 }
1089 
1090 /*
1091  * Decode setacl reply.
1092  */
1093 static int
1094 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1095 {
1096 	int status = ntohl(*p++);
1097 
1098 	if (status)
1099 		return -nfs_stat_to_errno(status);
1100 	xdr_decode_post_op_attr(p, fattr);
1101 	return 0;
1102 }
1103 #endif  /* CONFIG_NFS_V3_ACL */
1104 
1105 #define PROC(proc, argtype, restype, timer)				\
1106 [NFS3PROC_##proc] = {							\
1107 	.p_proc      = NFS3PROC_##proc,					\
1108 	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
1109 	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
1110 	.p_arglen    = NFS3_##argtype##_sz,				\
1111 	.p_replen    = NFS3_##restype##_sz,				\
1112 	.p_timer     = timer,						\
1113 	.p_statidx   = NFS3PROC_##proc,					\
1114 	.p_name      = #proc,						\
1115 	}
1116 
1117 struct rpc_procinfo	nfs3_procedures[] = {
1118   PROC(GETATTR,		fhandle,	attrstat, 1),
1119   PROC(SETATTR, 	sattrargs,	wccstat, 0),
1120   PROC(LOOKUP,		diropargs,	lookupres, 2),
1121   PROC(ACCESS,		accessargs,	accessres, 1),
1122   PROC(READLINK,	readlinkargs,	readlinkres, 3),
1123   PROC(READ,		readargs,	readres, 3),
1124   PROC(WRITE,		writeargs,	writeres, 4),
1125   PROC(CREATE,		createargs,	createres, 0),
1126   PROC(MKDIR,		mkdirargs,	createres, 0),
1127   PROC(SYMLINK,		symlinkargs,	createres, 0),
1128   PROC(MKNOD,		mknodargs,	createres, 0),
1129   PROC(REMOVE,		diropargs,	wccstat, 0),
1130   PROC(RMDIR,		diropargs,	wccstat, 0),
1131   PROC(RENAME,		renameargs,	renameres, 0),
1132   PROC(LINK,		linkargs,	linkres, 0),
1133   PROC(READDIR,		readdirargs,	readdirres, 3),
1134   PROC(READDIRPLUS,	readdirargs,	readdirres, 3),
1135   PROC(FSSTAT,		fhandle,	fsstatres, 0),
1136   PROC(FSINFO,  	fhandle,	fsinfores, 0),
1137   PROC(PATHCONF,	fhandle,	pathconfres, 0),
1138   PROC(COMMIT,		commitargs,	commitres, 5),
1139 };
1140 
1141 struct rpc_version		nfs_version3 = {
1142 	.number			= 3,
1143 	.nrprocs		= ARRAY_SIZE(nfs3_procedures),
1144 	.procs			= nfs3_procedures
1145 };
1146 
1147 #ifdef CONFIG_NFS_V3_ACL
1148 static struct rpc_procinfo	nfs3_acl_procedures[] = {
1149 	[ACLPROC3_GETACL] = {
1150 		.p_proc = ACLPROC3_GETACL,
1151 		.p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1152 		.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1153 		.p_arglen = ACL3_getaclargs_sz,
1154 		.p_replen = ACL3_getaclres_sz,
1155 		.p_timer = 1,
1156 		.p_name = "GETACL",
1157 	},
1158 	[ACLPROC3_SETACL] = {
1159 		.p_proc = ACLPROC3_SETACL,
1160 		.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1161 		.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1162 		.p_arglen = ACL3_setaclargs_sz,
1163 		.p_replen = ACL3_setaclres_sz,
1164 		.p_timer = 0,
1165 		.p_name = "SETACL",
1166 	},
1167 };
1168 
1169 struct rpc_version		nfsacl_version3 = {
1170 	.number			= 3,
1171 	.nrprocs		= sizeof(nfs3_acl_procedures)/
1172 				  sizeof(nfs3_acl_procedures[0]),
1173 	.procs			= nfs3_acl_procedures,
1174 };
1175 #endif  /* CONFIG_NFS_V3_ACL */
1176