xref: /openbmc/linux/fs/nfs/nfs3xdr.c (revision f42b3800)
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 	size_t hdrlen;
510 	u32 len, recvd, pglen;
511 	int status, nr;
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 %Zu > %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 0x%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 0x%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 	size_t hdrlen;
819 	u32 len, recvd;
820 	char	*kaddr;
821 	int	status;
822 
823 	status = ntohl(*p++);
824 	p = xdr_decode_post_op_attr(p, fattr);
825 
826 	if (status != 0)
827 		return -nfs_stat_to_errno(status);
828 
829 	/* Convert length of symlink */
830 	len = ntohl(*p++);
831 	if (len >= rcvbuf->page_len) {
832 		dprintk("nfs: server returned giant symlink!\n");
833 		return -ENAMETOOLONG;
834 	}
835 
836 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
837 	if (iov->iov_len < hdrlen) {
838 		dprintk("NFS: READLINK reply header overflowed:"
839 				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
840 		return -errno_NFSERR_IO;
841 	} else if (iov->iov_len != hdrlen) {
842 		dprintk("NFS: READLINK header is short. "
843 			"iovec will be shifted.\n");
844 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
845 	}
846 	recvd = req->rq_rcv_buf.len - hdrlen;
847 	if (recvd < len) {
848 		dprintk("NFS: server cheating in readlink reply: "
849 				"count %u > recvd %u\n", len, recvd);
850 		return -EIO;
851 	}
852 
853 	/* NULL terminate the string we got */
854 	kaddr = (char*)kmap_atomic(rcvbuf->pages[0], KM_USER0);
855 	kaddr[len+rcvbuf->page_base] = '\0';
856 	kunmap_atomic(kaddr, KM_USER0);
857 	return 0;
858 }
859 
860 /*
861  * Decode READ reply
862  */
863 static int
864 nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
865 {
866 	struct kvec *iov = req->rq_rcv_buf.head;
867 	size_t hdrlen;
868 	u32 count, ocount, recvd;
869 	int status;
870 
871 	status = ntohl(*p++);
872 	p = xdr_decode_post_op_attr(p, res->fattr);
873 
874 	if (status != 0)
875 		return -nfs_stat_to_errno(status);
876 
877 	/* Decode reply count and EOF flag. NFSv3 is somewhat redundant
878 	 * in that it puts the count both in the res struct and in the
879 	 * opaque data count. */
880 	count    = ntohl(*p++);
881 	res->eof = ntohl(*p++);
882 	ocount   = ntohl(*p++);
883 
884 	if (ocount != count) {
885 		dprintk("NFS: READ count doesn't match RPC opaque count.\n");
886 		return -errno_NFSERR_IO;
887 	}
888 
889 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
890 	if (iov->iov_len < hdrlen) {
891 		dprintk("NFS: READ reply header overflowed:"
892 				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
893        		return -errno_NFSERR_IO;
894 	} else if (iov->iov_len != hdrlen) {
895 		dprintk("NFS: READ header is short. iovec will be shifted.\n");
896 		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
897 	}
898 
899 	recvd = req->rq_rcv_buf.len - hdrlen;
900 	if (count > recvd) {
901 		dprintk("NFS: server cheating in read reply: "
902 			"count %u > recvd %u\n", count, recvd);
903 		count = recvd;
904 		res->eof = 0;
905 	}
906 
907 	if (count < res->count)
908 		res->count = count;
909 
910 	return count;
911 }
912 
913 /*
914  * Decode WRITE response
915  */
916 static int
917 nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
918 {
919 	int	status;
920 
921 	status = ntohl(*p++);
922 	p = xdr_decode_wcc_data(p, res->fattr);
923 
924 	if (status != 0)
925 		return -nfs_stat_to_errno(status);
926 
927 	res->count = ntohl(*p++);
928 	res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
929 	res->verf->verifier[0] = *p++;
930 	res->verf->verifier[1] = *p++;
931 
932 	return res->count;
933 }
934 
935 /*
936  * Decode a CREATE response
937  */
938 static int
939 nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
940 {
941 	int	status;
942 
943 	status = ntohl(*p++);
944 	if (status == 0) {
945 		if (*p++) {
946 			if (!(p = xdr_decode_fhandle(p, res->fh)))
947 				return -errno_NFSERR_IO;
948 			p = xdr_decode_post_op_attr(p, res->fattr);
949 		} else {
950 			memset(res->fh, 0, sizeof(*res->fh));
951 			/* Do decode post_op_attr but set it to NULL */
952 			p = xdr_decode_post_op_attr(p, res->fattr);
953 			res->fattr->valid = 0;
954 		}
955 	} else {
956 		status = -nfs_stat_to_errno(status);
957 	}
958 	p = xdr_decode_wcc_data(p, res->dir_attr);
959 	return status;
960 }
961 
962 /*
963  * Decode RENAME reply
964  */
965 static int
966 nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs3_renameres *res)
967 {
968 	int	status;
969 
970 	if ((status = ntohl(*p++)) != 0)
971 		status = -nfs_stat_to_errno(status);
972 	p = xdr_decode_wcc_data(p, res->fromattr);
973 	p = xdr_decode_wcc_data(p, res->toattr);
974 	return status;
975 }
976 
977 /*
978  * Decode LINK reply
979  */
980 static int
981 nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
982 {
983 	int	status;
984 
985 	if ((status = ntohl(*p++)) != 0)
986 		status = -nfs_stat_to_errno(status);
987 	p = xdr_decode_post_op_attr(p, res->fattr);
988 	p = xdr_decode_wcc_data(p, res->dir_attr);
989 	return status;
990 }
991 
992 /*
993  * Decode FSSTAT reply
994  */
995 static int
996 nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
997 {
998 	int		status;
999 
1000 	status = ntohl(*p++);
1001 
1002 	p = xdr_decode_post_op_attr(p, res->fattr);
1003 	if (status != 0)
1004 		return -nfs_stat_to_errno(status);
1005 
1006 	p = xdr_decode_hyper(p, &res->tbytes);
1007 	p = xdr_decode_hyper(p, &res->fbytes);
1008 	p = xdr_decode_hyper(p, &res->abytes);
1009 	p = xdr_decode_hyper(p, &res->tfiles);
1010 	p = xdr_decode_hyper(p, &res->ffiles);
1011 	p = xdr_decode_hyper(p, &res->afiles);
1012 
1013 	/* ignore invarsec */
1014 	return 0;
1015 }
1016 
1017 /*
1018  * Decode FSINFO reply
1019  */
1020 static int
1021 nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1022 {
1023 	int		status;
1024 
1025 	status = ntohl(*p++);
1026 
1027 	p = xdr_decode_post_op_attr(p, res->fattr);
1028 	if (status != 0)
1029 		return -nfs_stat_to_errno(status);
1030 
1031 	res->rtmax  = ntohl(*p++);
1032 	res->rtpref = ntohl(*p++);
1033 	res->rtmult = ntohl(*p++);
1034 	res->wtmax  = ntohl(*p++);
1035 	res->wtpref = ntohl(*p++);
1036 	res->wtmult = ntohl(*p++);
1037 	res->dtpref = ntohl(*p++);
1038 	p = xdr_decode_hyper(p, &res->maxfilesize);
1039 
1040 	/* ignore time_delta and properties */
1041 	res->lease_time = 0;
1042 	return 0;
1043 }
1044 
1045 /*
1046  * Decode PATHCONF reply
1047  */
1048 static int
1049 nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1050 {
1051 	int		status;
1052 
1053 	status = ntohl(*p++);
1054 
1055 	p = xdr_decode_post_op_attr(p, res->fattr);
1056 	if (status != 0)
1057 		return -nfs_stat_to_errno(status);
1058 	res->max_link = ntohl(*p++);
1059 	res->max_namelen = ntohl(*p++);
1060 
1061 	/* ignore remaining fields */
1062 	return 0;
1063 }
1064 
1065 /*
1066  * Decode COMMIT reply
1067  */
1068 static int
1069 nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1070 {
1071 	int		status;
1072 
1073 	status = ntohl(*p++);
1074 	p = xdr_decode_wcc_data(p, res->fattr);
1075 	if (status != 0)
1076 		return -nfs_stat_to_errno(status);
1077 
1078 	res->verf->verifier[0] = *p++;
1079 	res->verf->verifier[1] = *p++;
1080 	return 0;
1081 }
1082 
1083 #ifdef CONFIG_NFS_V3_ACL
1084 /*
1085  * Decode GETACL reply
1086  */
1087 static int
1088 nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
1089 		   struct nfs3_getaclres *res)
1090 {
1091 	struct xdr_buf *buf = &req->rq_rcv_buf;
1092 	int status = ntohl(*p++);
1093 	struct posix_acl **acl;
1094 	unsigned int *aclcnt;
1095 	int err, base;
1096 
1097 	if (status != 0)
1098 		return -nfs_stat_to_errno(status);
1099 	p = xdr_decode_post_op_attr(p, res->fattr);
1100 	res->mask = ntohl(*p++);
1101 	if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1102 		return -EINVAL;
1103 	base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1104 
1105 	acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1106 	aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1107 	err = nfsacl_decode(buf, base, aclcnt, acl);
1108 
1109 	acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1110 	aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1111 	if (err > 0)
1112 		err = nfsacl_decode(buf, base + err, aclcnt, acl);
1113 	return (err > 0) ? 0 : err;
1114 }
1115 
1116 /*
1117  * Decode setacl reply.
1118  */
1119 static int
1120 nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1121 {
1122 	int status = ntohl(*p++);
1123 
1124 	if (status)
1125 		return -nfs_stat_to_errno(status);
1126 	xdr_decode_post_op_attr(p, fattr);
1127 	return 0;
1128 }
1129 #endif  /* CONFIG_NFS_V3_ACL */
1130 
1131 #define PROC(proc, argtype, restype, timer)				\
1132 [NFS3PROC_##proc] = {							\
1133 	.p_proc      = NFS3PROC_##proc,					\
1134 	.p_encode    = (kxdrproc_t) nfs3_xdr_##argtype,			\
1135 	.p_decode    = (kxdrproc_t) nfs3_xdr_##restype,			\
1136 	.p_arglen    = NFS3_##argtype##_sz,				\
1137 	.p_replen    = NFS3_##restype##_sz,				\
1138 	.p_timer     = timer,						\
1139 	.p_statidx   = NFS3PROC_##proc,					\
1140 	.p_name      = #proc,						\
1141 	}
1142 
1143 struct rpc_procinfo	nfs3_procedures[] = {
1144   PROC(GETATTR,		fhandle,	attrstat, 1),
1145   PROC(SETATTR, 	sattrargs,	wccstat, 0),
1146   PROC(LOOKUP,		diropargs,	lookupres, 2),
1147   PROC(ACCESS,		accessargs,	accessres, 1),
1148   PROC(READLINK,	readlinkargs,	readlinkres, 3),
1149   PROC(READ,		readargs,	readres, 3),
1150   PROC(WRITE,		writeargs,	writeres, 4),
1151   PROC(CREATE,		createargs,	createres, 0),
1152   PROC(MKDIR,		mkdirargs,	createres, 0),
1153   PROC(SYMLINK,		symlinkargs,	createres, 0),
1154   PROC(MKNOD,		mknodargs,	createres, 0),
1155   PROC(REMOVE,		removeargs,	removeres, 0),
1156   PROC(RMDIR,		diropargs,	wccstat, 0),
1157   PROC(RENAME,		renameargs,	renameres, 0),
1158   PROC(LINK,		linkargs,	linkres, 0),
1159   PROC(READDIR,		readdirargs,	readdirres, 3),
1160   PROC(READDIRPLUS,	readdirargs,	readdirres, 3),
1161   PROC(FSSTAT,		fhandle,	fsstatres, 0),
1162   PROC(FSINFO,  	fhandle,	fsinfores, 0),
1163   PROC(PATHCONF,	fhandle,	pathconfres, 0),
1164   PROC(COMMIT,		commitargs,	commitres, 5),
1165 };
1166 
1167 struct rpc_version		nfs_version3 = {
1168 	.number			= 3,
1169 	.nrprocs		= ARRAY_SIZE(nfs3_procedures),
1170 	.procs			= nfs3_procedures
1171 };
1172 
1173 #ifdef CONFIG_NFS_V3_ACL
1174 static struct rpc_procinfo	nfs3_acl_procedures[] = {
1175 	[ACLPROC3_GETACL] = {
1176 		.p_proc = ACLPROC3_GETACL,
1177 		.p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
1178 		.p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
1179 		.p_arglen = ACL3_getaclargs_sz,
1180 		.p_replen = ACL3_getaclres_sz,
1181 		.p_timer = 1,
1182 		.p_name = "GETACL",
1183 	},
1184 	[ACLPROC3_SETACL] = {
1185 		.p_proc = ACLPROC3_SETACL,
1186 		.p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
1187 		.p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
1188 		.p_arglen = ACL3_setaclargs_sz,
1189 		.p_replen = ACL3_setaclres_sz,
1190 		.p_timer = 0,
1191 		.p_name = "SETACL",
1192 	},
1193 };
1194 
1195 struct rpc_version		nfsacl_version3 = {
1196 	.number			= 3,
1197 	.nrprocs		= sizeof(nfs3_acl_procedures)/
1198 				  sizeof(nfs3_acl_procedures[0]),
1199 	.procs			= nfs3_acl_procedures,
1200 };
1201 #endif  /* CONFIG_NFS_V3_ACL */
1202