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