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