xref: /openbmc/linux/fs/nfs/nfs2xdr.c (revision bca79478)
1 /*
2  * linux/fs/nfs/nfs2xdr.c
3  *
4  * XDR functions to encode/decode NFS RPC arguments and results.
5  *
6  * Copyright (C) 1992, 1993, 1994  Rick Sladkey
7  * Copyright (C) 1996 Olaf Kirch
8  * 04 Aug 1998  Ion Badulescu <ionut@cs.columbia.edu>
9  * 		FIFO's need special handling in NFSv2
10  */
11 
12 #include <linux/param.h>
13 #include <linux/time.h>
14 #include <linux/mm.h>
15 #include <linux/slab.h>
16 #include <linux/utsname.h>
17 #include <linux/errno.h>
18 #include <linux/string.h>
19 #include <linux/in.h>
20 #include <linux/pagemap.h>
21 #include <linux/proc_fs.h>
22 #include <linux/sunrpc/clnt.h>
23 #include <linux/nfs.h>
24 #include <linux/nfs2.h>
25 #include <linux/nfs_fs.h>
26 #include "internal.h"
27 
28 #define NFSDBG_FACILITY		NFSDBG_XDR
29 
30 /* Mapping from NFS error code to "errno" error code. */
31 #define errno_NFSERR_IO		EIO
32 
33 /*
34  * Declare the space requirements for NFS arguments and replies as
35  * number of 32bit-words
36  */
37 #define NFS_fhandle_sz		(8)
38 #define NFS_sattr_sz		(8)
39 #define NFS_filename_sz		(1+(NFS2_MAXNAMLEN>>2))
40 #define NFS_path_sz		(1+(NFS2_MAXPATHLEN>>2))
41 #define NFS_fattr_sz		(17)
42 #define NFS_info_sz		(5)
43 #define NFS_entry_sz		(NFS_filename_sz+3)
44 
45 #define NFS_diropargs_sz	(NFS_fhandle_sz+NFS_filename_sz)
46 #define NFS_removeargs_sz	(NFS_fhandle_sz+NFS_filename_sz)
47 #define NFS_sattrargs_sz	(NFS_fhandle_sz+NFS_sattr_sz)
48 #define NFS_readlinkargs_sz	(NFS_fhandle_sz)
49 #define NFS_readargs_sz		(NFS_fhandle_sz+3)
50 #define NFS_writeargs_sz	(NFS_fhandle_sz+4)
51 #define NFS_createargs_sz	(NFS_diropargs_sz+NFS_sattr_sz)
52 #define NFS_renameargs_sz	(NFS_diropargs_sz+NFS_diropargs_sz)
53 #define NFS_linkargs_sz		(NFS_fhandle_sz+NFS_diropargs_sz)
54 #define NFS_symlinkargs_sz	(NFS_diropargs_sz+1+NFS_sattr_sz)
55 #define NFS_readdirargs_sz	(NFS_fhandle_sz+2)
56 
57 #define NFS_attrstat_sz		(1+NFS_fattr_sz)
58 #define NFS_diropres_sz		(1+NFS_fhandle_sz+NFS_fattr_sz)
59 #define NFS_readlinkres_sz	(2)
60 #define NFS_readres_sz		(1+NFS_fattr_sz+1)
61 #define NFS_writeres_sz         (NFS_attrstat_sz)
62 #define NFS_stat_sz		(1)
63 #define NFS_readdirres_sz	(1)
64 #define NFS_statfsres_sz	(1+NFS_info_sz)
65 
66 /*
67  * Common NFS XDR functions as inlines
68  */
69 static inline __be32 *
70 xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fhandle)
71 {
72 	memcpy(p, fhandle->data, NFS2_FHSIZE);
73 	return p + XDR_QUADLEN(NFS2_FHSIZE);
74 }
75 
76 static inline __be32 *
77 xdr_decode_fhandle(__be32 *p, struct nfs_fh *fhandle)
78 {
79 	/* NFSv2 handles have a fixed length */
80 	fhandle->size = NFS2_FHSIZE;
81 	memcpy(fhandle->data, p, NFS2_FHSIZE);
82 	return p + XDR_QUADLEN(NFS2_FHSIZE);
83 }
84 
85 static inline __be32*
86 xdr_encode_time(__be32 *p, struct timespec *timep)
87 {
88 	*p++ = htonl(timep->tv_sec);
89 	/* Convert nanoseconds into microseconds */
90 	*p++ = htonl(timep->tv_nsec ? timep->tv_nsec / 1000 : 0);
91 	return p;
92 }
93 
94 static inline __be32*
95 xdr_encode_current_server_time(__be32 *p, struct timespec *timep)
96 {
97 	/*
98 	 * Passing the invalid value useconds=1000000 is a
99 	 * Sun convention for "set to current server time".
100 	 * It's needed to make permissions checks for the
101 	 * "touch" program across v2 mounts to Solaris and
102 	 * Irix boxes work correctly. See description of
103 	 * sattr in section 6.1 of "NFS Illustrated" by
104 	 * Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5
105 	 */
106 	*p++ = htonl(timep->tv_sec);
107 	*p++ = htonl(1000000);
108 	return p;
109 }
110 
111 static inline __be32*
112 xdr_decode_time(__be32 *p, struct timespec *timep)
113 {
114 	timep->tv_sec = ntohl(*p++);
115 	/* Convert microseconds into nanoseconds */
116 	timep->tv_nsec = ntohl(*p++) * 1000;
117 	return p;
118 }
119 
120 static __be32 *
121 xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
122 {
123 	u32 rdev, type;
124 	type = ntohl(*p++);
125 	fattr->mode = ntohl(*p++);
126 	fattr->nlink = ntohl(*p++);
127 	fattr->uid = ntohl(*p++);
128 	fattr->gid = ntohl(*p++);
129 	fattr->size = ntohl(*p++);
130 	fattr->du.nfs2.blocksize = ntohl(*p++);
131 	rdev = ntohl(*p++);
132 	fattr->du.nfs2.blocks = ntohl(*p++);
133 	fattr->fsid.major = ntohl(*p++);
134 	fattr->fsid.minor = 0;
135 	fattr->fileid = ntohl(*p++);
136 	p = xdr_decode_time(p, &fattr->atime);
137 	p = xdr_decode_time(p, &fattr->mtime);
138 	p = xdr_decode_time(p, &fattr->ctime);
139 	fattr->valid |= NFS_ATTR_FATTR_V2;
140 	fattr->rdev = new_decode_dev(rdev);
141 	if (type == NFCHR && rdev == NFS2_FIFO_DEV) {
142 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
143 		fattr->rdev = 0;
144 	}
145 	return p;
146 }
147 
148 static inline __be32 *
149 xdr_encode_sattr(__be32 *p, struct iattr *attr)
150 {
151 	const __be32 not_set = __constant_htonl(0xFFFFFFFF);
152 
153 	*p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
154 	*p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
155 	*p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
156 	*p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
157 
158 	if (attr->ia_valid & ATTR_ATIME_SET) {
159 		p = xdr_encode_time(p, &attr->ia_atime);
160 	} else if (attr->ia_valid & ATTR_ATIME) {
161 		p = xdr_encode_current_server_time(p, &attr->ia_atime);
162 	} else {
163 		*p++ = not_set;
164 		*p++ = not_set;
165 	}
166 
167 	if (attr->ia_valid & ATTR_MTIME_SET) {
168 		p = xdr_encode_time(p, &attr->ia_mtime);
169 	} else if (attr->ia_valid & ATTR_MTIME) {
170 		p = xdr_encode_current_server_time(p, &attr->ia_mtime);
171 	} else {
172 		*p++ = not_set;
173 		*p++ = not_set;
174 	}
175   	return p;
176 }
177 
178 /*
179  * NFS encode functions
180  */
181 /*
182  * Encode file handle argument
183  * GETATTR, READLINK, STATFS
184  */
185 static int
186 nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
187 {
188 	p = xdr_encode_fhandle(p, fh);
189 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
190 	return 0;
191 }
192 
193 /*
194  * Encode SETATTR arguments
195  */
196 static int
197 nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
198 {
199 	p = xdr_encode_fhandle(p, args->fh);
200 	p = xdr_encode_sattr(p, args->sattr);
201 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
202 	return 0;
203 }
204 
205 /*
206  * Encode directory ops argument
207  * LOOKUP, RMDIR
208  */
209 static int
210 nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
211 {
212 	p = xdr_encode_fhandle(p, args->fh);
213 	p = xdr_encode_array(p, args->name, args->len);
214 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
215 	return 0;
216 }
217 
218 /*
219  * Encode REMOVE argument
220  */
221 static int
222 nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
223 {
224 	p = xdr_encode_fhandle(p, args->fh);
225 	p = xdr_encode_array(p, args->name.name, args->name.len);
226 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
227 	return 0;
228 }
229 
230 /*
231  * Arguments to a READ call. Since we read data directly into the page
232  * cache, we also set up the reply iovec here so that iov[1] points
233  * exactly to the page we want to fetch.
234  */
235 static int
236 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
237 {
238 	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
239 	unsigned int replen;
240 	u32 offset = (u32)args->offset;
241 	u32 count = args->count;
242 
243 	p = xdr_encode_fhandle(p, args->fh);
244 	*p++ = htonl(offset);
245 	*p++ = htonl(count);
246 	*p++ = htonl(count);
247 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
248 
249 	/* Inline the page array */
250 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
251 	xdr_inline_pages(&req->rq_rcv_buf, replen,
252 			 args->pages, args->pgbase, count);
253 	req->rq_rcv_buf.flags |= XDRBUF_READ;
254 	return 0;
255 }
256 
257 /*
258  * Decode READ reply
259  */
260 static int
261 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
262 {
263 	struct kvec *iov = req->rq_rcv_buf.head;
264 	size_t hdrlen;
265 	u32 count, recvd;
266 	int status;
267 
268 	if ((status = ntohl(*p++)))
269 		return nfs_stat_to_errno(status);
270 	p = xdr_decode_fattr(p, res->fattr);
271 
272 	count = ntohl(*p++);
273 	res->eof = 0;
274 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
275 	if (iov->iov_len < hdrlen) {
276 		dprintk("NFS: READ reply header overflowed:"
277 				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
278 		return -errno_NFSERR_IO;
279 	} else if (iov->iov_len != hdrlen) {
280 		dprintk("NFS: READ header is short. iovec will be shifted.\n");
281 		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
282 	}
283 
284 	recvd = req->rq_rcv_buf.len - hdrlen;
285 	if (count > recvd) {
286 		dprintk("NFS: server cheating in read reply: "
287 			"count %u > recvd %u\n", count, recvd);
288 		count = recvd;
289 	}
290 
291 	dprintk("RPC:      readres OK count %u\n", count);
292 	if (count < res->count)
293 		res->count = count;
294 
295 	return count;
296 }
297 
298 
299 /*
300  * Write arguments. Splice the buffer to be written into the iovec.
301  */
302 static int
303 nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
304 {
305 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
306 	u32 offset = (u32)args->offset;
307 	u32 count = args->count;
308 
309 	p = xdr_encode_fhandle(p, args->fh);
310 	*p++ = htonl(offset);
311 	*p++ = htonl(offset);
312 	*p++ = htonl(count);
313 	*p++ = htonl(count);
314 	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
315 
316 	/* Copy the page array */
317 	xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
318 	sndbuf->flags |= XDRBUF_WRITE;
319 	return 0;
320 }
321 
322 /*
323  * Encode create arguments
324  * CREATE, MKDIR
325  */
326 static int
327 nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
328 {
329 	p = xdr_encode_fhandle(p, args->fh);
330 	p = xdr_encode_array(p, args->name, args->len);
331 	p = xdr_encode_sattr(p, args->sattr);
332 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
333 	return 0;
334 }
335 
336 /*
337  * Encode RENAME arguments
338  */
339 static int
340 nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
341 {
342 	p = xdr_encode_fhandle(p, args->fromfh);
343 	p = xdr_encode_array(p, args->fromname, args->fromlen);
344 	p = xdr_encode_fhandle(p, args->tofh);
345 	p = xdr_encode_array(p, args->toname, args->tolen);
346 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
347 	return 0;
348 }
349 
350 /*
351  * Encode LINK arguments
352  */
353 static int
354 nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
355 {
356 	p = xdr_encode_fhandle(p, args->fromfh);
357 	p = xdr_encode_fhandle(p, args->tofh);
358 	p = xdr_encode_array(p, args->toname, args->tolen);
359 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
360 	return 0;
361 }
362 
363 /*
364  * Encode SYMLINK arguments
365  */
366 static int
367 nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args)
368 {
369 	struct xdr_buf *sndbuf = &req->rq_snd_buf;
370 	size_t pad;
371 
372 	p = xdr_encode_fhandle(p, args->fromfh);
373 	p = xdr_encode_array(p, args->fromname, args->fromlen);
374 	*p++ = htonl(args->pathlen);
375 	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
376 
377 	xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);
378 
379 	/*
380 	 * xdr_encode_pages may have added a few bytes to ensure the
381 	 * pathname ends on a 4-byte boundary.  Start encoding the
382 	 * attributes after the pad bytes.
383 	 */
384 	pad = sndbuf->tail->iov_len;
385 	if (pad > 0)
386 		p++;
387 	p = xdr_encode_sattr(p, args->sattr);
388 	sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
389 	return 0;
390 }
391 
392 /*
393  * Encode arguments to readdir call
394  */
395 static int
396 nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
397 {
398 	struct rpc_task	*task = req->rq_task;
399 	struct rpc_auth	*auth = task->tk_msg.rpc_cred->cr_auth;
400 	unsigned int replen;
401 	u32 count = args->count;
402 
403 	p = xdr_encode_fhandle(p, args->fh);
404 	*p++ = htonl(args->cookie);
405 	*p++ = htonl(count); /* see above */
406 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
407 
408 	/* Inline the page array */
409 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
410 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
411 	return 0;
412 }
413 
414 /*
415  * Decode the result of a readdir call.
416  * We're not really decoding anymore, we just leave the buffer untouched
417  * and only check that it is syntactically correct.
418  * The real decoding happens in nfs_decode_entry below, called directly
419  * from nfs_readdir for each entry.
420  */
421 static int
422 nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
423 {
424 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
425 	struct kvec *iov = rcvbuf->head;
426 	struct page **page;
427 	size_t hdrlen;
428 	unsigned int pglen, recvd;
429 	u32 len;
430 	int status, nr = 0;
431 	__be32 *end, *entry, *kaddr;
432 
433 	if ((status = ntohl(*p++)))
434 		return nfs_stat_to_errno(status);
435 
436 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
437 	if (iov->iov_len < hdrlen) {
438 		dprintk("NFS: READDIR reply header overflowed:"
439 				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
440 		return -errno_NFSERR_IO;
441 	} else if (iov->iov_len != hdrlen) {
442 		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
443 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
444 	}
445 
446 	pglen = rcvbuf->page_len;
447 	recvd = rcvbuf->len - hdrlen;
448 	if (pglen > recvd)
449 		pglen = recvd;
450 	page = rcvbuf->pages;
451 	kaddr = p = kmap_atomic(*page, KM_USER0);
452 	end = (__be32 *)((char *)p + pglen);
453 	entry = p;
454 
455 	/* Make sure the packet actually has a value_follows and EOF entry */
456 	if ((entry + 1) > end)
457 		goto short_pkt;
458 
459 	for (; *p++; nr++) {
460 		if (p + 2 > end)
461 			goto short_pkt;
462 		p++; /* fileid */
463 		len = ntohl(*p++);
464 		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */
465 		if (len > NFS2_MAXNAMLEN) {
466 			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
467 						len);
468 			goto err_unmap;
469 		}
470 		if (p + 2 > end)
471 			goto short_pkt;
472 		entry = p;
473 	}
474 
475 	/*
476 	 * Apparently some server sends responses that are a valid size, but
477 	 * contain no entries, and have value_follows==0 and EOF==0. For
478 	 * those, just set the EOF marker.
479 	 */
480 	if (!nr && entry[1] == 0) {
481 		dprintk("NFS: readdir reply truncated!\n");
482 		entry[1] = 1;
483 	}
484  out:
485 	kunmap_atomic(kaddr, KM_USER0);
486 	return nr;
487  short_pkt:
488 	/*
489 	 * When we get a short packet there are 2 possibilities. We can
490 	 * return an error, or fix up the response to look like a valid
491 	 * response and return what we have so far. If there are no
492 	 * entries and the packet was short, then return -EIO. If there
493 	 * are valid entries in the response, return them and pretend that
494 	 * the call was successful, but incomplete. The caller can retry the
495 	 * readdir starting at the last cookie.
496 	 */
497 	entry[0] = entry[1] = 0;
498 	if (!nr)
499 		nr = -errno_NFSERR_IO;
500 	goto out;
501 err_unmap:
502 	nr = -errno_NFSERR_IO;
503 	goto out;
504 }
505 
506 __be32 *
507 nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
508 {
509 	if (!*p++) {
510 		if (!*p)
511 			return ERR_PTR(-EAGAIN);
512 		entry->eof = 1;
513 		return ERR_PTR(-EBADCOOKIE);
514 	}
515 
516 	entry->ino	  = ntohl(*p++);
517 	entry->len	  = ntohl(*p++);
518 	entry->name	  = (const char *) p;
519 	p		 += XDR_QUADLEN(entry->len);
520 	entry->prev_cookie	  = entry->cookie;
521 	entry->cookie	  = ntohl(*p++);
522 	entry->eof	  = !p[0] && p[1];
523 
524 	return p;
525 }
526 
527 /*
528  * NFS XDR decode functions
529  */
530 /*
531  * Decode simple status reply
532  */
533 static int
534 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
535 {
536 	int	status;
537 
538 	if ((status = ntohl(*p++)) != 0)
539 		status = nfs_stat_to_errno(status);
540 	return status;
541 }
542 
543 /*
544  * Decode attrstat reply
545  * GETATTR, SETATTR, WRITE
546  */
547 static int
548 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
549 {
550 	int	status;
551 
552 	if ((status = ntohl(*p++)))
553 		return nfs_stat_to_errno(status);
554 	xdr_decode_fattr(p, fattr);
555 	return 0;
556 }
557 
558 /*
559  * Decode diropres reply
560  * LOOKUP, CREATE, MKDIR
561  */
562 static int
563 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
564 {
565 	int	status;
566 
567 	if ((status = ntohl(*p++)))
568 		return nfs_stat_to_errno(status);
569 	p = xdr_decode_fhandle(p, res->fh);
570 	xdr_decode_fattr(p, res->fattr);
571 	return 0;
572 }
573 
574 /*
575  * Encode READLINK args
576  */
577 static int
578 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
579 {
580 	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
581 	unsigned int replen;
582 
583 	p = xdr_encode_fhandle(p, args->fh);
584 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
585 
586 	/* Inline the page array */
587 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
588 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
589 	return 0;
590 }
591 
592 /*
593  * Decode READLINK reply
594  */
595 static int
596 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
597 {
598 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
599 	struct kvec *iov = rcvbuf->head;
600 	size_t hdrlen;
601 	u32 len, recvd;
602 	char	*kaddr;
603 	int	status;
604 
605 	if ((status = ntohl(*p++)))
606 		return nfs_stat_to_errno(status);
607 	/* Convert length of symlink */
608 	len = ntohl(*p++);
609 	if (len >= rcvbuf->page_len) {
610 		dprintk("nfs: server returned giant symlink!\n");
611 		return -ENAMETOOLONG;
612 	}
613 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
614 	if (iov->iov_len < hdrlen) {
615 		dprintk("NFS: READLINK reply header overflowed:"
616 				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
617 		return -errno_NFSERR_IO;
618 	} else if (iov->iov_len != hdrlen) {
619 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
620 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
621 	}
622 	recvd = req->rq_rcv_buf.len - hdrlen;
623 	if (recvd < len) {
624 		dprintk("NFS: server cheating in readlink reply: "
625 				"count %u > recvd %u\n", len, recvd);
626 		return -EIO;
627 	}
628 
629 	/* NULL terminate the string we got */
630 	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
631 	kaddr[len+rcvbuf->page_base] = '\0';
632 	kunmap_atomic(kaddr, KM_USER0);
633 	return 0;
634 }
635 
636 /*
637  * Decode WRITE reply
638  */
639 static int
640 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
641 {
642 	res->verf->committed = NFS_FILE_SYNC;
643 	return nfs_xdr_attrstat(req, p, res->fattr);
644 }
645 
646 /*
647  * Decode STATFS reply
648  */
649 static int
650 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
651 {
652 	int	status;
653 
654 	if ((status = ntohl(*p++)))
655 		return nfs_stat_to_errno(status);
656 
657 	res->tsize  = ntohl(*p++);
658 	res->bsize  = ntohl(*p++);
659 	res->blocks = ntohl(*p++);
660 	res->bfree  = ntohl(*p++);
661 	res->bavail = ntohl(*p++);
662 	return 0;
663 }
664 
665 /*
666  * We need to translate between nfs status return values and
667  * the local errno values which may not be the same.
668  */
669 static struct {
670 	int stat;
671 	int errno;
672 } nfs_errtbl[] = {
673 	{ NFS_OK,		0		},
674 	{ NFSERR_PERM,		-EPERM		},
675 	{ NFSERR_NOENT,		-ENOENT		},
676 	{ NFSERR_IO,		-errno_NFSERR_IO},
677 	{ NFSERR_NXIO,		-ENXIO		},
678 /*	{ NFSERR_EAGAIN,	-EAGAIN		}, */
679 	{ NFSERR_ACCES,		-EACCES		},
680 	{ NFSERR_EXIST,		-EEXIST		},
681 	{ NFSERR_XDEV,		-EXDEV		},
682 	{ NFSERR_NODEV,		-ENODEV		},
683 	{ NFSERR_NOTDIR,	-ENOTDIR	},
684 	{ NFSERR_ISDIR,		-EISDIR		},
685 	{ NFSERR_INVAL,		-EINVAL		},
686 	{ NFSERR_FBIG,		-EFBIG		},
687 	{ NFSERR_NOSPC,		-ENOSPC		},
688 	{ NFSERR_ROFS,		-EROFS		},
689 	{ NFSERR_MLINK,		-EMLINK		},
690 	{ NFSERR_NAMETOOLONG,	-ENAMETOOLONG	},
691 	{ NFSERR_NOTEMPTY,	-ENOTEMPTY	},
692 	{ NFSERR_DQUOT,		-EDQUOT		},
693 	{ NFSERR_STALE,		-ESTALE		},
694 	{ NFSERR_REMOTE,	-EREMOTE	},
695 #ifdef EWFLUSH
696 	{ NFSERR_WFLUSH,	-EWFLUSH	},
697 #endif
698 	{ NFSERR_BADHANDLE,	-EBADHANDLE	},
699 	{ NFSERR_NOT_SYNC,	-ENOTSYNC	},
700 	{ NFSERR_BAD_COOKIE,	-EBADCOOKIE	},
701 	{ NFSERR_NOTSUPP,	-ENOTSUPP	},
702 	{ NFSERR_TOOSMALL,	-ETOOSMALL	},
703 	{ NFSERR_SERVERFAULT,	-ESERVERFAULT	},
704 	{ NFSERR_BADTYPE,	-EBADTYPE	},
705 	{ NFSERR_JUKEBOX,	-EJUKEBOX	},
706 	{ -1,			-EIO		}
707 };
708 
709 /*
710  * Convert an NFS error code to a local one.
711  * This one is used jointly by NFSv2 and NFSv3.
712  */
713 int
714 nfs_stat_to_errno(int stat)
715 {
716 	int i;
717 
718 	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
719 		if (nfs_errtbl[i].stat == stat)
720 			return nfs_errtbl[i].errno;
721 	}
722 	dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
723 	return nfs_errtbl[i].errno;
724 }
725 
726 #define PROC(proc, argtype, restype, timer)				\
727 [NFSPROC_##proc] = {							\
728 	.p_proc	    =  NFSPROC_##proc,					\
729 	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
730 	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
731 	.p_arglen   =  NFS_##argtype##_sz,				\
732 	.p_replen   =  NFS_##restype##_sz,				\
733 	.p_timer    =  timer,						\
734 	.p_statidx  =  NFSPROC_##proc,					\
735 	.p_name     =  #proc,						\
736 	}
737 struct rpc_procinfo	nfs_procedures[] = {
738     PROC(GETATTR,	fhandle,	attrstat, 1),
739     PROC(SETATTR,	sattrargs,	attrstat, 0),
740     PROC(LOOKUP,	diropargs,	diropres, 2),
741     PROC(READLINK,	readlinkargs,	readlinkres, 3),
742     PROC(READ,		readargs,	readres, 3),
743     PROC(WRITE,		writeargs,	writeres, 4),
744     PROC(CREATE,	createargs,	diropres, 0),
745     PROC(REMOVE,	removeargs,	stat, 0),
746     PROC(RENAME,	renameargs,	stat, 0),
747     PROC(LINK,		linkargs,	stat, 0),
748     PROC(SYMLINK,	symlinkargs,	stat, 0),
749     PROC(MKDIR,		createargs,	diropres, 0),
750     PROC(RMDIR,		diropargs,	stat, 0),
751     PROC(READDIR,	readdirargs,	readdirres, 3),
752     PROC(STATFS,	fhandle,	statfsres, 0),
753 };
754 
755 struct rpc_version		nfs_version2 = {
756 	.number			= 2,
757 	.nrprocs		= ARRAY_SIZE(nfs_procedures),
758 	.procs			= nfs_procedures
759 };
760