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