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