xref: /linux/fs/nfs/nfs3xdr.c (revision f3d9478b2ce468c3115b02ecae7e975990697f15)
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 	return p;
178 }
179 
180 static inline u32 *
181 xdr_encode_sattr(u32 *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 u32 *
227 xdr_decode_wcc_attr(u32 *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 u32 *
237 xdr_decode_post_op_attr(u32 *p, struct nfs_fattr *fattr)
238 {
239 	if (*p++)
240 		p = xdr_decode_fattr(p, fattr);
241 	return p;
242 }
243 
244 static inline u32 *
245 xdr_decode_pre_op_attr(u32 *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 u32 *
254 xdr_decode_wcc_data(u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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, u32 *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 = xdr_encode_array(p, args->topath, args->tolen);
402 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
403 	return 0;
404 }
405 
406 /*
407  * Encode MKNOD arguments
408  */
409 static int
410 nfs3_xdr_mknodargs(struct rpc_rqst *req, u32 *p, struct nfs3_mknodargs *args)
411 {
412 	p = xdr_encode_fhandle(p, args->fh);
413 	p = xdr_encode_array(p, args->name, args->len);
414 	*p++ = htonl(args->type);
415 	p = xdr_encode_sattr(p, args->sattr);
416 	if (args->type == NF3CHR || args->type == NF3BLK) {
417 		*p++ = htonl(MAJOR(args->rdev));
418 		*p++ = htonl(MINOR(args->rdev));
419 	}
420 
421 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
422 	return 0;
423 }
424 
425 /*
426  * Encode RENAME arguments
427  */
428 static int
429 nfs3_xdr_renameargs(struct rpc_rqst *req, u32 *p, struct nfs3_renameargs *args)
430 {
431 	p = xdr_encode_fhandle(p, args->fromfh);
432 	p = xdr_encode_array(p, args->fromname, args->fromlen);
433 	p = xdr_encode_fhandle(p, args->tofh);
434 	p = xdr_encode_array(p, args->toname, args->tolen);
435 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
436 	return 0;
437 }
438 
439 /*
440  * Encode LINK arguments
441  */
442 static int
443 nfs3_xdr_linkargs(struct rpc_rqst *req, u32 *p, struct nfs3_linkargs *args)
444 {
445 	p = xdr_encode_fhandle(p, args->fromfh);
446 	p = xdr_encode_fhandle(p, args->tofh);
447 	p = xdr_encode_array(p, args->toname, args->tolen);
448 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
449 	return 0;
450 }
451 
452 /*
453  * Encode arguments to readdir call
454  */
455 static int
456 nfs3_xdr_readdirargs(struct rpc_rqst *req, u32 *p, struct nfs3_readdirargs *args)
457 {
458 	struct rpc_auth	*auth = req->rq_task->tk_auth;
459 	unsigned int replen;
460 	u32 count = args->count;
461 
462 	p = xdr_encode_fhandle(p, args->fh);
463 	p = xdr_encode_hyper(p, args->cookie);
464 	*p++ = args->verf[0];
465 	*p++ = args->verf[1];
466 	if (args->plus) {
467 		/* readdirplus: need dircount + buffer size.
468 		 * We just make sure we make dircount big enough */
469 		*p++ = htonl(count >> 3);
470 	}
471 	*p++ = htonl(count);
472 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
473 
474 	/* Inline the page array */
475 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
476 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
477 	return 0;
478 }
479 
480 /*
481  * Decode the result of a readdir call.
482  * We just check for syntactical correctness.
483  */
484 static int
485 nfs3_xdr_readdirres(struct rpc_rqst *req, u32 *p, struct nfs3_readdirres *res)
486 {
487 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
488 	struct kvec *iov = rcvbuf->head;
489 	struct page **page;
490 	int hdrlen, recvd;
491 	int status, nr;
492 	unsigned int len, pglen;
493 	u32 *entry, *end, *kaddr;
494 
495 	status = ntohl(*p++);
496 	/* Decode post_op_attrs */
497 	p = xdr_decode_post_op_attr(p, res->dir_attr);
498 	if (status)
499 		return -nfs_stat_to_errno(status);
500 	/* Decode verifier cookie */
501 	if (res->verf) {
502 		res->verf[0] = *p++;
503 		res->verf[1] = *p++;
504 	} else {
505 		p += 2;
506 	}
507 
508 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
509 	if (iov->iov_len < hdrlen) {
510 		printk(KERN_WARNING "NFS: READDIR reply header overflowed:"
511 				"length %d > %Zu\n", hdrlen, iov->iov_len);
512 		return -errno_NFSERR_IO;
513 	} else if (iov->iov_len != hdrlen) {
514 		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
515 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
516 	}
517 
518 	pglen = rcvbuf->page_len;
519 	recvd = rcvbuf->len - hdrlen;
520 	if (pglen > recvd)
521 		pglen = recvd;
522 	page = rcvbuf->pages;
523 	kaddr = p = (u32 *)kmap_atomic(*page, KM_USER0);
524 	end = (u32 *)((char *)p + pglen);
525 	entry = p;
526 	for (nr = 0; *p++; nr++) {
527 		if (p + 3 > end)
528 			goto short_pkt;
529 		p += 2;				/* inode # */
530 		len = ntohl(*p++);		/* string length */
531 		p += XDR_QUADLEN(len) + 2;	/* name + cookie */
532 		if (len > NFS3_MAXNAMLEN) {
533 			printk(KERN_WARNING "NFS: giant filename in readdir (len %x)!\n",
534 						len);
535 			goto err_unmap;
536 		}
537 
538 		if (res->plus) {
539 			/* post_op_attr */
540 			if (p + 2 > end)
541 				goto short_pkt;
542 			if (*p++) {
543 				p += 21;
544 				if (p + 1 > end)
545 					goto short_pkt;
546 			}
547 			/* post_op_fh3 */
548 			if (*p++) {
549 				if (p + 1 > end)
550 					goto short_pkt;
551 				len = ntohl(*p++);
552 				if (len > NFS3_FHSIZE) {
553 					printk(KERN_WARNING "NFS: giant filehandle in "
554 						"readdir (len %x)!\n", len);
555 					goto err_unmap;
556 				}
557 				p += XDR_QUADLEN(len);
558 			}
559 		}
560 
561 		if (p + 2 > end)
562 			goto short_pkt;
563 		entry = p;
564 	}
565 	if (!nr && (entry[0] != 0 || entry[1] == 0))
566 		goto short_pkt;
567  out:
568 	kunmap_atomic(kaddr, KM_USER0);
569 	return nr;
570  short_pkt:
571 	entry[0] = entry[1] = 0;
572 	/* truncate listing ? */
573 	if (!nr) {
574 		printk(KERN_NOTICE "NFS: readdir reply truncated!\n");
575 		entry[1] = 1;
576 	}
577 	goto out;
578 err_unmap:
579 	nr = -errno_NFSERR_IO;
580 	goto out;
581 }
582 
583 u32 *
584 nfs3_decode_dirent(u32 *p, struct nfs_entry *entry, int plus)
585 {
586 	struct nfs_entry old = *entry;
587 
588 	if (!*p++) {
589 		if (!*p)
590 			return ERR_PTR(-EAGAIN);
591 		entry->eof = 1;
592 		return ERR_PTR(-EBADCOOKIE);
593 	}
594 
595 	p = xdr_decode_hyper(p, &entry->ino);
596 	entry->len  = ntohl(*p++);
597 	entry->name = (const char *) p;
598 	p += XDR_QUADLEN(entry->len);
599 	entry->prev_cookie = entry->cookie;
600 	p = xdr_decode_hyper(p, &entry->cookie);
601 
602 	if (plus) {
603 		entry->fattr->valid = 0;
604 		p = xdr_decode_post_op_attr(p, entry->fattr);
605 		/* In fact, a post_op_fh3: */
606 		if (*p++) {
607 			p = xdr_decode_fhandle(p, entry->fh);
608 			/* Ugh -- server reply was truncated */
609 			if (p == NULL) {
610 				dprintk("NFS: FH truncated\n");
611 				*entry = old;
612 				return ERR_PTR(-EAGAIN);
613 			}
614 		} else
615 			memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
616 	}
617 
618 	entry->eof = !p[0] && p[1];
619 	return p;
620 }
621 
622 /*
623  * Encode COMMIT arguments
624  */
625 static int
626 nfs3_xdr_commitargs(struct rpc_rqst *req, u32 *p, struct nfs_writeargs *args)
627 {
628 	p = xdr_encode_fhandle(p, args->fh);
629 	p = xdr_encode_hyper(p, args->offset);
630 	*p++ = htonl(args->count);
631 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
632 	return 0;
633 }
634 
635 #ifdef CONFIG_NFS_V3_ACL
636 /*
637  * Encode GETACL arguments
638  */
639 static int
640 nfs3_xdr_getaclargs(struct rpc_rqst *req, u32 *p,
641 		    struct nfs3_getaclargs *args)
642 {
643 	struct rpc_auth *auth = req->rq_task->tk_auth;
644 	unsigned int replen;
645 
646 	p = xdr_encode_fhandle(p, args->fh);
647 	*p++ = htonl(args->mask);
648 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
649 
650 	if (args->mask & (NFS_ACL | NFS_DFACL)) {
651 		/* Inline the page array */
652 		replen = (RPC_REPHDRSIZE + auth->au_rslack +
653 			  ACL3_getaclres_sz) << 2;
654 		xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
655 				 NFSACL_MAXPAGES << PAGE_SHIFT);
656 	}
657 	return 0;
658 }
659 
660 /*
661  * Encode SETACL arguments
662  */
663 static int
664 nfs3_xdr_setaclargs(struct rpc_rqst *req, u32 *p,
665                    struct nfs3_setaclargs *args)
666 {
667 	struct xdr_buf *buf = &req->rq_snd_buf;
668 	unsigned int base, len_in_head, len = nfsacl_size(
669 		(args->mask & NFS_ACL)   ? args->acl_access  : NULL,
670 		(args->mask & NFS_DFACL) ? args->acl_default : NULL);
671 	int count, err;
672 
673 	p = xdr_encode_fhandle(p, NFS_FH(args->inode));
674 	*p++ = htonl(args->mask);
675 	base = (char *)p - (char *)buf->head->iov_base;
676 	/* put as much of the acls into head as possible. */
677 	len_in_head = min_t(unsigned int, buf->head->iov_len - base, len);
678 	len -= len_in_head;
679 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p + (len_in_head >> 2));
680 
681 	for (count = 0; (count << PAGE_SHIFT) < len; count++) {
682 		args->pages[count] = alloc_page(GFP_KERNEL);
683 		if (!args->pages[count]) {
684 			while (count)
685 				__free_page(args->pages[--count]);
686 			return -ENOMEM;
687 		}
688 	}
689 	xdr_encode_pages(buf, args->pages, 0, len);
690 
691 	err = nfsacl_encode(buf, base, args->inode,
692 			    (args->mask & NFS_ACL) ?
693 			    args->acl_access : NULL, 1, 0);
694 	if (err > 0)
695 		err = nfsacl_encode(buf, base + err, args->inode,
696 				    (args->mask & NFS_DFACL) ?
697 				    args->acl_default : NULL, 1,
698 				    NFS_ACL_DEFAULT);
699 	return (err > 0) ? 0 : err;
700 }
701 #endif  /* CONFIG_NFS_V3_ACL */
702 
703 /*
704  * NFS XDR decode functions
705  */
706 
707 /*
708  * Decode attrstat reply.
709  */
710 static int
711 nfs3_xdr_attrstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
712 {
713 	int	status;
714 
715 	if ((status = ntohl(*p++)))
716 		return -nfs_stat_to_errno(status);
717 	xdr_decode_fattr(p, fattr);
718 	return 0;
719 }
720 
721 /*
722  * Decode status+wcc_data reply
723  * SATTR, REMOVE, RMDIR
724  */
725 static int
726 nfs3_xdr_wccstat(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
727 {
728 	int	status;
729 
730 	if ((status = ntohl(*p++)))
731 		status = -nfs_stat_to_errno(status);
732 	xdr_decode_wcc_data(p, fattr);
733 	return status;
734 }
735 
736 /*
737  * Decode LOOKUP reply
738  */
739 static int
740 nfs3_xdr_lookupres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
741 {
742 	int	status;
743 
744 	if ((status = ntohl(*p++))) {
745 		status = -nfs_stat_to_errno(status);
746 	} else {
747 		if (!(p = xdr_decode_fhandle(p, res->fh)))
748 			return -errno_NFSERR_IO;
749 		p = xdr_decode_post_op_attr(p, res->fattr);
750 	}
751 	xdr_decode_post_op_attr(p, res->dir_attr);
752 	return status;
753 }
754 
755 /*
756  * Decode ACCESS reply
757  */
758 static int
759 nfs3_xdr_accessres(struct rpc_rqst *req, u32 *p, struct nfs3_accessres *res)
760 {
761 	int	status = ntohl(*p++);
762 
763 	p = xdr_decode_post_op_attr(p, res->fattr);
764 	if (status)
765 		return -nfs_stat_to_errno(status);
766 	res->access = ntohl(*p++);
767 	return 0;
768 }
769 
770 static int
771 nfs3_xdr_readlinkargs(struct rpc_rqst *req, u32 *p, struct nfs3_readlinkargs *args)
772 {
773 	struct rpc_auth *auth = req->rq_task->tk_auth;
774 	unsigned int replen;
775 
776 	p = xdr_encode_fhandle(p, args->fh);
777 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
778 
779 	/* Inline the page array */
780 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
781 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
782 	return 0;
783 }
784 
785 /*
786  * Decode READLINK reply
787  */
788 static int
789 nfs3_xdr_readlinkres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
790 {
791 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
792 	struct kvec *iov = rcvbuf->head;
793 	int hdrlen, len, recvd;
794 	char	*kaddr;
795 	int	status;
796 
797 	status = ntohl(*p++);
798 	p = xdr_decode_post_op_attr(p, fattr);
799 
800 	if (status != 0)
801 		return -nfs_stat_to_errno(status);
802 
803 	/* Convert length of symlink */
804 	len = ntohl(*p++);
805 	if (len >= rcvbuf->page_len || len <= 0) {
806 		dprintk(KERN_WARNING "nfs: server returned giant symlink!\n");
807 		return -ENAMETOOLONG;
808 	}
809 
810 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
811 	if (iov->iov_len < hdrlen) {
812 		printk(KERN_WARNING "NFS: READLINK reply header overflowed:"
813 				"length %d > %Zu\n", hdrlen, iov->iov_len);
814 		return -errno_NFSERR_IO;
815 	} else if (iov->iov_len != hdrlen) {
816 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
817 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
818 	}
819 	recvd = req->rq_rcv_buf.len - hdrlen;
820 	if (recvd < len) {
821 		printk(KERN_WARNING "NFS: server cheating in readlink reply: "
822 				"count %u > recvd %u\n", len, recvd);
823 		return -EIO;
824 	}
825 
826 	/* NULL terminate the string we got */
827 	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
828 	kaddr[len+rcvbuf->page_base] = '\0';
829 	kunmap_atomic(kaddr, KM_USER0);
830 	return 0;
831 }
832 
833 /*
834  * Decode READ reply
835  */
836 static int
837 nfs3_xdr_readres(struct rpc_rqst *req, u32 *p, struct nfs_readres *res)
838 {
839 	struct kvec *iov = req->rq_rcv_buf.head;
840 	int	status, count, ocount, recvd, hdrlen;
841 
842 	status = ntohl(*p++);
843 	p = xdr_decode_post_op_attr(p, res->fattr);
844 
845 	if (status != 0)
846 		return -nfs_stat_to_errno(status);
847 
848 	/* Decode reply could and EOF flag. NFSv3 is somewhat redundant
849 	 * in that it puts the count both in the res struct and in the
850 	 * opaque data count. */
851 	count    = ntohl(*p++);
852 	res->eof = ntohl(*p++);
853 	ocount   = ntohl(*p++);
854 
855 	if (ocount != count) {
856 		printk(KERN_WARNING "NFS: READ count doesn't match RPC opaque count.\n");
857 		return -errno_NFSERR_IO;
858 	}
859 
860 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
861 	if (iov->iov_len < hdrlen) {
862 		printk(KERN_WARNING "NFS: READ reply header overflowed:"
863 				"length %d > %Zu\n", hdrlen, iov->iov_len);
864        		return -errno_NFSERR_IO;
865 	} else if (iov->iov_len != hdrlen) {
866 		dprintk("NFS: READ header is short. iovec will be shifted.\n");
867 		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
868 	}
869 
870 	recvd = req->rq_rcv_buf.len - hdrlen;
871 	if (count > recvd) {
872 		printk(KERN_WARNING "NFS: server cheating in read reply: "
873 			"count %d > recvd %d\n", count, recvd);
874 		count = recvd;
875 		res->eof = 0;
876 	}
877 
878 	if (count < res->count)
879 		res->count = count;
880 
881 	return count;
882 }
883 
884 /*
885  * Decode WRITE response
886  */
887 static int
888 nfs3_xdr_writeres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
889 {
890 	int	status;
891 
892 	status = ntohl(*p++);
893 	p = xdr_decode_wcc_data(p, res->fattr);
894 
895 	if (status != 0)
896 		return -nfs_stat_to_errno(status);
897 
898 	res->count = ntohl(*p++);
899 	res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
900 	res->verf->verifier[0] = *p++;
901 	res->verf->verifier[1] = *p++;
902 
903 	return res->count;
904 }
905 
906 /*
907  * Decode a CREATE response
908  */
909 static int
910 nfs3_xdr_createres(struct rpc_rqst *req, u32 *p, struct nfs3_diropres *res)
911 {
912 	int	status;
913 
914 	status = ntohl(*p++);
915 	if (status == 0) {
916 		if (*p++) {
917 			if (!(p = xdr_decode_fhandle(p, res->fh)))
918 				return -errno_NFSERR_IO;
919 			p = xdr_decode_post_op_attr(p, res->fattr);
920 		} else {
921 			memset(res->fh, 0, sizeof(*res->fh));
922 			/* Do decode post_op_attr but set it to NULL */
923 			p = xdr_decode_post_op_attr(p, res->fattr);
924 			res->fattr->valid = 0;
925 		}
926 	} else {
927 		status = -nfs_stat_to_errno(status);
928 	}
929 	p = xdr_decode_wcc_data(p, res->dir_attr);
930 	return status;
931 }
932 
933 /*
934  * Decode RENAME reply
935  */
936 static int
937 nfs3_xdr_renameres(struct rpc_rqst *req, u32 *p, struct nfs3_renameres *res)
938 {
939 	int	status;
940 
941 	if ((status = ntohl(*p++)) != 0)
942 		status = -nfs_stat_to_errno(status);
943 	p = xdr_decode_wcc_data(p, res->fromattr);
944 	p = xdr_decode_wcc_data(p, res->toattr);
945 	return status;
946 }
947 
948 /*
949  * Decode LINK reply
950  */
951 static int
952 nfs3_xdr_linkres(struct rpc_rqst *req, u32 *p, struct nfs3_linkres *res)
953 {
954 	int	status;
955 
956 	if ((status = ntohl(*p++)) != 0)
957 		status = -nfs_stat_to_errno(status);
958 	p = xdr_decode_post_op_attr(p, res->fattr);
959 	p = xdr_decode_wcc_data(p, res->dir_attr);
960 	return status;
961 }
962 
963 /*
964  * Decode FSSTAT reply
965  */
966 static int
967 nfs3_xdr_fsstatres(struct rpc_rqst *req, u32 *p, struct nfs_fsstat *res)
968 {
969 	int		status;
970 
971 	status = ntohl(*p++);
972 
973 	p = xdr_decode_post_op_attr(p, res->fattr);
974 	if (status != 0)
975 		return -nfs_stat_to_errno(status);
976 
977 	p = xdr_decode_hyper(p, &res->tbytes);
978 	p = xdr_decode_hyper(p, &res->fbytes);
979 	p = xdr_decode_hyper(p, &res->abytes);
980 	p = xdr_decode_hyper(p, &res->tfiles);
981 	p = xdr_decode_hyper(p, &res->ffiles);
982 	p = xdr_decode_hyper(p, &res->afiles);
983 
984 	/* ignore invarsec */
985 	return 0;
986 }
987 
988 /*
989  * Decode FSINFO reply
990  */
991 static int
992 nfs3_xdr_fsinfores(struct rpc_rqst *req, u32 *p, struct nfs_fsinfo *res)
993 {
994 	int		status;
995 
996 	status = ntohl(*p++);
997 
998 	p = xdr_decode_post_op_attr(p, res->fattr);
999 	if (status != 0)
1000 		return -nfs_stat_to_errno(status);
1001 
1002 	res->rtmax  = ntohl(*p++);
1003 	res->rtpref = ntohl(*p++);
1004 	res->rtmult = ntohl(*p++);
1005 	res->wtmax  = ntohl(*p++);
1006 	res->wtpref = ntohl(*p++);
1007 	res->wtmult = ntohl(*p++);
1008 	res->dtpref = ntohl(*p++);
1009 	p = xdr_decode_hyper(p, &res->maxfilesize);
1010 
1011 	/* ignore time_delta and properties */
1012 	res->lease_time = 0;
1013 	return 0;
1014 }
1015 
1016 /*
1017  * Decode PATHCONF reply
1018  */
1019 static int
1020 nfs3_xdr_pathconfres(struct rpc_rqst *req, u32 *p, struct nfs_pathconf *res)
1021 {
1022 	int		status;
1023 
1024 	status = ntohl(*p++);
1025 
1026 	p = xdr_decode_post_op_attr(p, res->fattr);
1027 	if (status != 0)
1028 		return -nfs_stat_to_errno(status);
1029 	res->max_link = ntohl(*p++);
1030 	res->max_namelen = ntohl(*p++);
1031 
1032 	/* ignore remaining fields */
1033 	return 0;
1034 }
1035 
1036 /*
1037  * Decode COMMIT reply
1038  */
1039 static int
1040 nfs3_xdr_commitres(struct rpc_rqst *req, u32 *p, struct nfs_writeres *res)
1041 {
1042 	int		status;
1043 
1044 	status = ntohl(*p++);
1045 	p = xdr_decode_wcc_data(p, res->fattr);
1046 	if (status != 0)
1047 		return -nfs_stat_to_errno(status);
1048 
1049 	res->verf->verifier[0] = *p++;
1050 	res->verf->verifier[1] = *p++;
1051 	return 0;
1052 }
1053 
1054 #ifdef CONFIG_NFS_V3_ACL
1055 /*
1056  * Decode GETACL reply
1057  */
1058 static int
1059 nfs3_xdr_getaclres(struct rpc_rqst *req, u32 *p,
1060 		   struct nfs3_getaclres *res)
1061 {
1062 	struct xdr_buf *buf = &req->rq_rcv_buf;
1063 	int status = ntohl(*p++);
1064 	struct posix_acl **acl;
1065 	unsigned int *aclcnt;
1066 	int err, base;
1067 
1068 	if (status != 0)
1069 		return -nfs_stat_to_errno(status);
1070 	p = xdr_decode_post_op_attr(p, res->fattr);
1071 	res->mask = ntohl(*p++);
1072 	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1073 		return -EINVAL;
1074 	base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1075 
1076 	acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1077 	aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1078 	err = nfsacl_decode(buf, base, aclcnt, acl);
1079 
1080 	acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1081 	aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1082 	if (err > 0)
1083 		err = nfsacl_decode(buf, base + err, aclcnt, acl);
1084 	return (err > 0) ? 0 : err;
1085 }
1086 
1087 /*
1088  * Decode setacl reply.
1089  */
1090 static int
1091 nfs3_xdr_setaclres(struct rpc_rqst *req, u32 *p, struct nfs_fattr *fattr)
1092 {
1093 	int status = ntohl(*p++);
1094 
1095 	if (status)
1096 		return -nfs_stat_to_errno(status);
1097 	xdr_decode_post_op_attr(p, fattr);
1098 	return 0;
1099 }
1100 #endif  /* CONFIG_NFS_V3_ACL */
1101 
1102 #ifndef MAX
1103 # define MAX(a, b)	(((a) > (b))? (a) : (b))
1104 #endif
1105 
1106 #define PROC(proc, argtype, restype, timer)				\
1107 [NFS3PROC_##proc] = {							\
1108 	.p_proc      = NFS3PROC_##proc,					\
1109 	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
1110 	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
1111 	.p_bufsiz    = MAX(NFS3_##argtype##_sz,NFS3_##restype##_sz) << 2,	\
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_bufsiz = MAX(ACL3_getaclargs_sz, ACL3_getaclres_sz) << 2,
1154 		.p_timer = 1,
1155 		.p_name = "GETACL",
1156 	},
1157 	[ACLPROC3_SETACL] = {
1158 		.p_proc = ACLPROC3_SETACL,
1159 		.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1160 		.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1161 		.p_bufsiz = MAX(ACL3_setaclargs_sz, ACL3_setaclres_sz) << 2,
1162 		.p_timer = 0,
1163 		.p_name = "SETACL",
1164 	},
1165 };
1166 
1167 struct rpc_version		nfsacl_version3 = {
1168 	.number			= 3,
1169 	.nrprocs		= sizeof(nfs3_acl_procedures)/
1170 				  sizeof(nfs3_acl_procedures[0]),
1171 	.procs			= nfs3_acl_procedures,
1172 };
1173 #endif  /* CONFIG_NFS_V3_ACL */
1174