xref: /openbmc/linux/fs/nfs/nfs2xdr.c (revision 04c71976)
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;
124 	fattr->type = (enum nfs_ftype) 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;
140 	fattr->rdev = new_decode_dev(rdev);
141 	if (fattr->type == NFCHR && rdev == NFS2_FIFO_DEV) {
142 		fattr->type = NFFIFO;
143 		fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
144 		fattr->rdev = 0;
145 	}
146 	return p;
147 }
148 
149 static inline __be32 *
150 xdr_encode_sattr(__be32 *p, struct iattr *attr)
151 {
152 	const __be32 not_set = __constant_htonl(0xFFFFFFFF);
153 
154 	*p++ = (attr->ia_valid & ATTR_MODE) ? htonl(attr->ia_mode) : not_set;
155 	*p++ = (attr->ia_valid & ATTR_UID) ? htonl(attr->ia_uid) : not_set;
156 	*p++ = (attr->ia_valid & ATTR_GID) ? htonl(attr->ia_gid) : not_set;
157 	*p++ = (attr->ia_valid & ATTR_SIZE) ? htonl(attr->ia_size) : not_set;
158 
159 	if (attr->ia_valid & ATTR_ATIME_SET) {
160 		p = xdr_encode_time(p, &attr->ia_atime);
161 	} else if (attr->ia_valid & ATTR_ATIME) {
162 		p = xdr_encode_current_server_time(p, &attr->ia_atime);
163 	} else {
164 		*p++ = not_set;
165 		*p++ = not_set;
166 	}
167 
168 	if (attr->ia_valid & ATTR_MTIME_SET) {
169 		p = xdr_encode_time(p, &attr->ia_mtime);
170 	} else if (attr->ia_valid & ATTR_MTIME) {
171 		p = xdr_encode_current_server_time(p, &attr->ia_mtime);
172 	} else {
173 		*p++ = not_set;
174 		*p++ = not_set;
175 	}
176   	return p;
177 }
178 
179 /*
180  * NFS encode functions
181  */
182 /*
183  * Encode file handle argument
184  * GETATTR, READLINK, STATFS
185  */
186 static int
187 nfs_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
188 {
189 	p = xdr_encode_fhandle(p, fh);
190 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
191 	return 0;
192 }
193 
194 /*
195  * Encode SETATTR arguments
196  */
197 static int
198 nfs_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs_sattrargs *args)
199 {
200 	p = xdr_encode_fhandle(p, args->fh);
201 	p = xdr_encode_sattr(p, args->sattr);
202 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
203 	return 0;
204 }
205 
206 /*
207  * Encode directory ops argument
208  * LOOKUP, RMDIR
209  */
210 static int
211 nfs_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs_diropargs *args)
212 {
213 	p = xdr_encode_fhandle(p, args->fh);
214 	p = xdr_encode_array(p, args->name, args->len);
215 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
216 	return 0;
217 }
218 
219 /*
220  * Encode REMOVE argument
221  */
222 static int
223 nfs_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
224 {
225 	p = xdr_encode_fhandle(p, args->fh);
226 	p = xdr_encode_array(p, args->name.name, args->name.len);
227 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
228 	return 0;
229 }
230 
231 /*
232  * Arguments to a READ call. Since we read data directly into the page
233  * cache, we also set up the reply iovec here so that iov[1] points
234  * exactly to the page we want to fetch.
235  */
236 static int
237 nfs_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
238 {
239 	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
240 	unsigned int replen;
241 	u32 offset = (u32)args->offset;
242 	u32 count = args->count;
243 
244 	p = xdr_encode_fhandle(p, args->fh);
245 	*p++ = htonl(offset);
246 	*p++ = htonl(count);
247 	*p++ = htonl(count);
248 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
249 
250 	/* Inline the page array */
251 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readres_sz) << 2;
252 	xdr_inline_pages(&req->rq_rcv_buf, replen,
253 			 args->pages, args->pgbase, count);
254 	req->rq_rcv_buf.flags |= XDRBUF_READ;
255 	return 0;
256 }
257 
258 /*
259  * Decode READ reply
260  */
261 static int
262 nfs_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
263 {
264 	struct kvec *iov = req->rq_rcv_buf.head;
265 	int	status, count, recvd, hdrlen;
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 %d > %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 %d > recvd %d\n", count, recvd);
287 		count = recvd;
288 	}
289 
290 	dprintk("RPC:      readres OK count %d\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 	int hdrlen, recvd;
427 	int status, nr;
428 	unsigned int len, pglen;
429 	__be32 *end, *entry, *kaddr;
430 
431 	if ((status = ntohl(*p++)))
432 		return -nfs_stat_to_errno(status);
433 
434 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
435 	if (iov->iov_len < hdrlen) {
436 		dprintk("NFS: READDIR reply header overflowed:"
437 				"length %d > %Zu\n", hdrlen, iov->iov_len);
438 		return -errno_NFSERR_IO;
439 	} else if (iov->iov_len != hdrlen) {
440 		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
441 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
442 	}
443 
444 	pglen = rcvbuf->page_len;
445 	recvd = rcvbuf->len - hdrlen;
446 	if (pglen > recvd)
447 		pglen = recvd;
448 	page = rcvbuf->pages;
449 	kaddr = p = kmap_atomic(*page, KM_USER0);
450 	end = (__be32 *)((char *)p + pglen);
451 	entry = p;
452 	for (nr = 0; *p++; nr++) {
453 		if (p + 2 > end)
454 			goto short_pkt;
455 		p++; /* fileid */
456 		len = ntohl(*p++);
457 		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */
458 		if (len > NFS2_MAXNAMLEN) {
459 			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
460 						len);
461 			goto err_unmap;
462 		}
463 		if (p + 2 > end)
464 			goto short_pkt;
465 		entry = p;
466 	}
467 	if (!nr && (entry[0] != 0 || entry[1] == 0))
468 		goto short_pkt;
469  out:
470 	kunmap_atomic(kaddr, KM_USER0);
471 	return nr;
472  short_pkt:
473 	entry[0] = entry[1] = 0;
474 	/* truncate listing ? */
475 	if (!nr) {
476 		dprintk("NFS: readdir reply truncated!\n");
477 		entry[1] = 1;
478 	}
479 	goto out;
480 err_unmap:
481 	nr = -errno_NFSERR_IO;
482 	goto out;
483 }
484 
485 __be32 *
486 nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
487 {
488 	if (!*p++) {
489 		if (!*p)
490 			return ERR_PTR(-EAGAIN);
491 		entry->eof = 1;
492 		return ERR_PTR(-EBADCOOKIE);
493 	}
494 
495 	entry->ino	  = ntohl(*p++);
496 	entry->len	  = ntohl(*p++);
497 	entry->name	  = (const char *) p;
498 	p		 += XDR_QUADLEN(entry->len);
499 	entry->prev_cookie	  = entry->cookie;
500 	entry->cookie	  = ntohl(*p++);
501 	entry->eof	  = !p[0] && p[1];
502 
503 	return p;
504 }
505 
506 /*
507  * NFS XDR decode functions
508  */
509 /*
510  * Decode simple status reply
511  */
512 static int
513 nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
514 {
515 	int	status;
516 
517 	if ((status = ntohl(*p++)) != 0)
518 		status = -nfs_stat_to_errno(status);
519 	return status;
520 }
521 
522 /*
523  * Decode attrstat reply
524  * GETATTR, SETATTR, WRITE
525  */
526 static int
527 nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
528 {
529 	int	status;
530 
531 	if ((status = ntohl(*p++)))
532 		return -nfs_stat_to_errno(status);
533 	xdr_decode_fattr(p, fattr);
534 	return 0;
535 }
536 
537 /*
538  * Decode diropres reply
539  * LOOKUP, CREATE, MKDIR
540  */
541 static int
542 nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
543 {
544 	int	status;
545 
546 	if ((status = ntohl(*p++)))
547 		return -nfs_stat_to_errno(status);
548 	p = xdr_decode_fhandle(p, res->fh);
549 	xdr_decode_fattr(p, res->fattr);
550 	return 0;
551 }
552 
553 /*
554  * Encode READLINK args
555  */
556 static int
557 nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
558 {
559 	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
560 	unsigned int replen;
561 
562 	p = xdr_encode_fhandle(p, args->fh);
563 	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
564 
565 	/* Inline the page array */
566 	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
567 	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
568 	return 0;
569 }
570 
571 /*
572  * Decode READLINK reply
573  */
574 static int
575 nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
576 {
577 	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
578 	struct kvec *iov = rcvbuf->head;
579 	int hdrlen, len, recvd;
580 	char	*kaddr;
581 	int	status;
582 
583 	if ((status = ntohl(*p++)))
584 		return -nfs_stat_to_errno(status);
585 	/* Convert length of symlink */
586 	len = ntohl(*p++);
587 	if (len >= rcvbuf->page_len || len <= 0) {
588 		dprintk("nfs: server returned giant symlink!\n");
589 		return -ENAMETOOLONG;
590 	}
591 	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
592 	if (iov->iov_len < hdrlen) {
593 		dprintk("NFS: READLINK reply header overflowed:"
594 				"length %d > %Zu\n", hdrlen, iov->iov_len);
595 		return -errno_NFSERR_IO;
596 	} else if (iov->iov_len != hdrlen) {
597 		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
598 		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
599 	}
600 	recvd = req->rq_rcv_buf.len - hdrlen;
601 	if (recvd < len) {
602 		dprintk("NFS: server cheating in readlink reply: "
603 				"count %u > recvd %u\n", len, recvd);
604 		return -EIO;
605 	}
606 
607 	/* NULL terminate the string we got */
608 	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
609 	kaddr[len+rcvbuf->page_base] = '\0';
610 	kunmap_atomic(kaddr, KM_USER0);
611 	return 0;
612 }
613 
614 /*
615  * Decode WRITE reply
616  */
617 static int
618 nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
619 {
620 	res->verf->committed = NFS_FILE_SYNC;
621 	return nfs_xdr_attrstat(req, p, res->fattr);
622 }
623 
624 /*
625  * Decode STATFS reply
626  */
627 static int
628 nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
629 {
630 	int	status;
631 
632 	if ((status = ntohl(*p++)))
633 		return -nfs_stat_to_errno(status);
634 
635 	res->tsize  = ntohl(*p++);
636 	res->bsize  = ntohl(*p++);
637 	res->blocks = ntohl(*p++);
638 	res->bfree  = ntohl(*p++);
639 	res->bavail = ntohl(*p++);
640 	return 0;
641 }
642 
643 /*
644  * We need to translate between nfs status return values and
645  * the local errno values which may not be the same.
646  */
647 static struct {
648 	int stat;
649 	int errno;
650 } nfs_errtbl[] = {
651 	{ NFS_OK,		0		},
652 	{ NFSERR_PERM,		EPERM		},
653 	{ NFSERR_NOENT,		ENOENT		},
654 	{ NFSERR_IO,		errno_NFSERR_IO	},
655 	{ NFSERR_NXIO,		ENXIO		},
656 /*	{ NFSERR_EAGAIN,	EAGAIN		}, */
657 	{ NFSERR_ACCES,		EACCES		},
658 	{ NFSERR_EXIST,		EEXIST		},
659 	{ NFSERR_XDEV,		EXDEV		},
660 	{ NFSERR_NODEV,		ENODEV		},
661 	{ NFSERR_NOTDIR,	ENOTDIR		},
662 	{ NFSERR_ISDIR,		EISDIR		},
663 	{ NFSERR_INVAL,		EINVAL		},
664 	{ NFSERR_FBIG,		EFBIG		},
665 	{ NFSERR_NOSPC,		ENOSPC		},
666 	{ NFSERR_ROFS,		EROFS		},
667 	{ NFSERR_MLINK,		EMLINK		},
668 	{ NFSERR_NAMETOOLONG,	ENAMETOOLONG	},
669 	{ NFSERR_NOTEMPTY,	ENOTEMPTY	},
670 	{ NFSERR_DQUOT,		EDQUOT		},
671 	{ NFSERR_STALE,		ESTALE		},
672 	{ NFSERR_REMOTE,	EREMOTE		},
673 #ifdef EWFLUSH
674 	{ NFSERR_WFLUSH,	EWFLUSH		},
675 #endif
676 	{ NFSERR_BADHANDLE,	EBADHANDLE	},
677 	{ NFSERR_NOT_SYNC,	ENOTSYNC	},
678 	{ NFSERR_BAD_COOKIE,	EBADCOOKIE	},
679 	{ NFSERR_NOTSUPP,	ENOTSUPP	},
680 	{ NFSERR_TOOSMALL,	ETOOSMALL	},
681 	{ NFSERR_SERVERFAULT,	ESERVERFAULT	},
682 	{ NFSERR_BADTYPE,	EBADTYPE	},
683 	{ NFSERR_JUKEBOX,	EJUKEBOX	},
684 	{ -1,			EIO		}
685 };
686 
687 /*
688  * Convert an NFS error code to a local one.
689  * This one is used jointly by NFSv2 and NFSv3.
690  */
691 int
692 nfs_stat_to_errno(int stat)
693 {
694 	int i;
695 
696 	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
697 		if (nfs_errtbl[i].stat == stat)
698 			return nfs_errtbl[i].errno;
699 	}
700 	dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
701 	return nfs_errtbl[i].errno;
702 }
703 
704 #define PROC(proc, argtype, restype, timer)				\
705 [NFSPROC_##proc] = {							\
706 	.p_proc	    =  NFSPROC_##proc,					\
707 	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
708 	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
709 	.p_arglen   =  NFS_##argtype##_sz,				\
710 	.p_replen   =  NFS_##restype##_sz,				\
711 	.p_timer    =  timer,						\
712 	.p_statidx  =  NFSPROC_##proc,					\
713 	.p_name     =  #proc,						\
714 	}
715 struct rpc_procinfo	nfs_procedures[] = {
716     PROC(GETATTR,	fhandle,	attrstat, 1),
717     PROC(SETATTR,	sattrargs,	attrstat, 0),
718     PROC(LOOKUP,	diropargs,	diropres, 2),
719     PROC(READLINK,	readlinkargs,	readlinkres, 3),
720     PROC(READ,		readargs,	readres, 3),
721     PROC(WRITE,		writeargs,	writeres, 4),
722     PROC(CREATE,	createargs,	diropres, 0),
723     PROC(REMOVE,	removeargs,	stat, 0),
724     PROC(RENAME,	renameargs,	stat, 0),
725     PROC(LINK,		linkargs,	stat, 0),
726     PROC(SYMLINK,	symlinkargs,	stat, 0),
727     PROC(MKDIR,		createargs,	diropres, 0),
728     PROC(RMDIR,		diropargs,	stat, 0),
729     PROC(READDIR,	readdirargs,	readdirres, 3),
730     PROC(STATFS,	fhandle,	statfsres, 0),
731 };
732 
733 struct rpc_version		nfs_version2 = {
734 	.number			= 2,
735 	.nrprocs		= ARRAY_SIZE(nfs_procedures),
736 	.procs			= nfs_procedures
737 };
738