• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 *
xdr_encode_fhandle(__be32 * p,const struct nfs_fh * fhandle)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 *
xdr_decode_fhandle(__be32 * p,struct nfs_fh * fhandle)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*
xdr_encode_time(__be32 * p,struct timespec * timep)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*
xdr_encode_current_server_time(__be32 * p,struct timespec * timep)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*
xdr_decode_time(__be32 * p,struct timespec * timep)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 *
xdr_decode_fattr(__be32 * p,struct nfs_fattr * fattr)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 *
xdr_encode_sattr(__be32 * p,struct iattr * attr)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
nfs_xdr_fhandle(struct rpc_rqst * req,__be32 * p,struct nfs_fh * fh)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
nfs_xdr_sattrargs(struct rpc_rqst * req,__be32 * p,struct nfs_sattrargs * args)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
nfs_xdr_diropargs(struct rpc_rqst * req,__be32 * p,struct nfs_diropargs * args)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
nfs_xdr_removeargs(struct rpc_rqst * req,__be32 * p,const struct nfs_removeargs * args)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
nfs_xdr_readargs(struct rpc_rqst * req,__be32 * p,struct nfs_readargs * args)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
nfs_xdr_readres(struct rpc_rqst * req,__be32 * p,struct nfs_readres * res)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  	size_t hdrlen;
266  	u32 count, recvd;
267  	int status;
268  
269  	if ((status = ntohl(*p++)))
270  		return nfs_stat_to_errno(status);
271  	p = xdr_decode_fattr(p, res->fattr);
272  
273  	count = ntohl(*p++);
274  	res->eof = 0;
275  	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
276  	if (iov->iov_len < hdrlen) {
277  		dprintk("NFS: READ reply header overflowed:"
278  				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
279  		return -errno_NFSERR_IO;
280  	} else if (iov->iov_len != hdrlen) {
281  		dprintk("NFS: READ header is short. iovec will be shifted.\n");
282  		xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
283  	}
284  
285  	recvd = req->rq_rcv_buf.len - hdrlen;
286  	if (count > recvd) {
287  		dprintk("NFS: server cheating in read reply: "
288  			"count %u > recvd %u\n", count, recvd);
289  		count = recvd;
290  	}
291  
292  	dprintk("RPC:      readres OK count %u\n", count);
293  	if (count < res->count)
294  		res->count = count;
295  
296  	return count;
297  }
298  
299  
300  /*
301   * Write arguments. Splice the buffer to be written into the iovec.
302   */
303  static int
nfs_xdr_writeargs(struct rpc_rqst * req,__be32 * p,struct nfs_writeargs * args)304  nfs_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
305  {
306  	struct xdr_buf *sndbuf = &req->rq_snd_buf;
307  	u32 offset = (u32)args->offset;
308  	u32 count = args->count;
309  
310  	p = xdr_encode_fhandle(p, args->fh);
311  	*p++ = htonl(offset);
312  	*p++ = htonl(offset);
313  	*p++ = htonl(count);
314  	*p++ = htonl(count);
315  	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
316  
317  	/* Copy the page array */
318  	xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
319  	sndbuf->flags |= XDRBUF_WRITE;
320  	return 0;
321  }
322  
323  /*
324   * Encode create arguments
325   * CREATE, MKDIR
326   */
327  static int
nfs_xdr_createargs(struct rpc_rqst * req,__be32 * p,struct nfs_createargs * args)328  nfs_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs_createargs *args)
329  {
330  	p = xdr_encode_fhandle(p, args->fh);
331  	p = xdr_encode_array(p, args->name, args->len);
332  	p = xdr_encode_sattr(p, args->sattr);
333  	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
334  	return 0;
335  }
336  
337  /*
338   * Encode RENAME arguments
339   */
340  static int
nfs_xdr_renameargs(struct rpc_rqst * req,__be32 * p,struct nfs_renameargs * args)341  nfs_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
342  {
343  	p = xdr_encode_fhandle(p, args->fromfh);
344  	p = xdr_encode_array(p, args->fromname, args->fromlen);
345  	p = xdr_encode_fhandle(p, args->tofh);
346  	p = xdr_encode_array(p, args->toname, args->tolen);
347  	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
348  	return 0;
349  }
350  
351  /*
352   * Encode LINK arguments
353   */
354  static int
nfs_xdr_linkargs(struct rpc_rqst * req,__be32 * p,struct nfs_linkargs * args)355  nfs_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs_linkargs *args)
356  {
357  	p = xdr_encode_fhandle(p, args->fromfh);
358  	p = xdr_encode_fhandle(p, args->tofh);
359  	p = xdr_encode_array(p, args->toname, args->tolen);
360  	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
361  	return 0;
362  }
363  
364  /*
365   * Encode SYMLINK arguments
366   */
367  static int
nfs_xdr_symlinkargs(struct rpc_rqst * req,__be32 * p,struct nfs_symlinkargs * args)368  nfs_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_symlinkargs *args)
369  {
370  	struct xdr_buf *sndbuf = &req->rq_snd_buf;
371  	size_t pad;
372  
373  	p = xdr_encode_fhandle(p, args->fromfh);
374  	p = xdr_encode_array(p, args->fromname, args->fromlen);
375  	*p++ = htonl(args->pathlen);
376  	sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
377  
378  	xdr_encode_pages(sndbuf, args->pages, 0, args->pathlen);
379  
380  	/*
381  	 * xdr_encode_pages may have added a few bytes to ensure the
382  	 * pathname ends on a 4-byte boundary.  Start encoding the
383  	 * attributes after the pad bytes.
384  	 */
385  	pad = sndbuf->tail->iov_len;
386  	if (pad > 0)
387  		p++;
388  	p = xdr_encode_sattr(p, args->sattr);
389  	sndbuf->len += xdr_adjust_iovec(sndbuf->tail, p) - pad;
390  	return 0;
391  }
392  
393  /*
394   * Encode arguments to readdir call
395   */
396  static int
nfs_xdr_readdirargs(struct rpc_rqst * req,__be32 * p,struct nfs_readdirargs * args)397  nfs_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs_readdirargs *args)
398  {
399  	struct rpc_task	*task = req->rq_task;
400  	struct rpc_auth	*auth = task->tk_msg.rpc_cred->cr_auth;
401  	unsigned int replen;
402  	u32 count = args->count;
403  
404  	p = xdr_encode_fhandle(p, args->fh);
405  	*p++ = htonl(args->cookie);
406  	*p++ = htonl(count); /* see above */
407  	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
408  
409  	/* Inline the page array */
410  	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readdirres_sz) << 2;
411  	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
412  	return 0;
413  }
414  
415  /*
416   * Decode the result of a readdir call.
417   * We're not really decoding anymore, we just leave the buffer untouched
418   * and only check that it is syntactically correct.
419   * The real decoding happens in nfs_decode_entry below, called directly
420   * from nfs_readdir for each entry.
421   */
422  static int
nfs_xdr_readdirres(struct rpc_rqst * req,__be32 * p,void * dummy)423  nfs_xdr_readdirres(struct rpc_rqst *req, __be32 *p, void *dummy)
424  {
425  	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
426  	struct kvec *iov = rcvbuf->head;
427  	struct page **page;
428  	size_t hdrlen;
429  	unsigned int pglen, recvd;
430  	u32 len;
431  	int status, nr = 0;
432  	__be32 *end, *entry, *kaddr;
433  
434  	if ((status = ntohl(*p++)))
435  		return nfs_stat_to_errno(status);
436  
437  	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
438  	if (iov->iov_len < hdrlen) {
439  		dprintk("NFS: READDIR reply header overflowed:"
440  				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
441  		return -errno_NFSERR_IO;
442  	} else if (iov->iov_len != hdrlen) {
443  		dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
444  		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
445  	}
446  
447  	pglen = rcvbuf->page_len;
448  	recvd = rcvbuf->len - hdrlen;
449  	if (pglen > recvd)
450  		pglen = recvd;
451  	page = rcvbuf->pages;
452  	kaddr = p = kmap_atomic(*page, KM_USER0);
453  	end = (__be32 *)((char *)p + pglen);
454  	entry = p;
455  
456  	/* Make sure the packet actually has a value_follows and EOF entry */
457  	if ((entry + 1) > end)
458  		goto short_pkt;
459  
460  	for (; *p++; nr++) {
461  		if (p + 2 > end)
462  			goto short_pkt;
463  		p++; /* fileid */
464  		len = ntohl(*p++);
465  		p += XDR_QUADLEN(len) + 1;	/* name plus cookie */
466  		if (len > NFS2_MAXNAMLEN) {
467  			dprintk("NFS: giant filename in readdir (len 0x%x)!\n",
468  						len);
469  			goto err_unmap;
470  		}
471  		if (p + 2 > end)
472  			goto short_pkt;
473  		entry = p;
474  	}
475  
476  	/*
477  	 * Apparently some server sends responses that are a valid size, but
478  	 * contain no entries, and have value_follows==0 and EOF==0. For
479  	 * those, just set the EOF marker.
480  	 */
481  	if (!nr && entry[1] == 0) {
482  		dprintk("NFS: readdir reply truncated!\n");
483  		entry[1] = 1;
484  	}
485   out:
486  	kunmap_atomic(kaddr, KM_USER0);
487  	return nr;
488   short_pkt:
489  	/*
490  	 * When we get a short packet there are 2 possibilities. We can
491  	 * return an error, or fix up the response to look like a valid
492  	 * response and return what we have so far. If there are no
493  	 * entries and the packet was short, then return -EIO. If there
494  	 * are valid entries in the response, return them and pretend that
495  	 * the call was successful, but incomplete. The caller can retry the
496  	 * readdir starting at the last cookie.
497  	 */
498  	entry[0] = entry[1] = 0;
499  	if (!nr)
500  		nr = -errno_NFSERR_IO;
501  	goto out;
502  err_unmap:
503  	nr = -errno_NFSERR_IO;
504  	goto out;
505  }
506  
507  __be32 *
nfs_decode_dirent(__be32 * p,struct nfs_entry * entry,int plus)508  nfs_decode_dirent(__be32 *p, struct nfs_entry *entry, int plus)
509  {
510  	if (!*p++) {
511  		if (!*p)
512  			return ERR_PTR(-EAGAIN);
513  		entry->eof = 1;
514  		return ERR_PTR(-EBADCOOKIE);
515  	}
516  
517  	entry->ino	  = ntohl(*p++);
518  	entry->len	  = ntohl(*p++);
519  	entry->name	  = (const char *) p;
520  	p		 += XDR_QUADLEN(entry->len);
521  	entry->prev_cookie	  = entry->cookie;
522  	entry->cookie	  = ntohl(*p++);
523  	entry->eof	  = !p[0] && p[1];
524  
525  	return p;
526  }
527  
528  /*
529   * NFS XDR decode functions
530   */
531  /*
532   * Decode simple status reply
533   */
534  static int
nfs_xdr_stat(struct rpc_rqst * req,__be32 * p,void * dummy)535  nfs_xdr_stat(struct rpc_rqst *req, __be32 *p, void *dummy)
536  {
537  	int	status;
538  
539  	if ((status = ntohl(*p++)) != 0)
540  		status = nfs_stat_to_errno(status);
541  	return status;
542  }
543  
544  /*
545   * Decode attrstat reply
546   * GETATTR, SETATTR, WRITE
547   */
548  static int
nfs_xdr_attrstat(struct rpc_rqst * req,__be32 * p,struct nfs_fattr * fattr)549  nfs_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
550  {
551  	int	status;
552  
553  	if ((status = ntohl(*p++)))
554  		return nfs_stat_to_errno(status);
555  	xdr_decode_fattr(p, fattr);
556  	return 0;
557  }
558  
559  /*
560   * Decode diropres reply
561   * LOOKUP, CREATE, MKDIR
562   */
563  static int
nfs_xdr_diropres(struct rpc_rqst * req,__be32 * p,struct nfs_diropok * res)564  nfs_xdr_diropres(struct rpc_rqst *req, __be32 *p, struct nfs_diropok *res)
565  {
566  	int	status;
567  
568  	if ((status = ntohl(*p++)))
569  		return nfs_stat_to_errno(status);
570  	p = xdr_decode_fhandle(p, res->fh);
571  	xdr_decode_fattr(p, res->fattr);
572  	return 0;
573  }
574  
575  /*
576   * Encode READLINK args
577   */
578  static int
nfs_xdr_readlinkargs(struct rpc_rqst * req,__be32 * p,struct nfs_readlinkargs * args)579  nfs_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs_readlinkargs *args)
580  {
581  	struct rpc_auth	*auth = req->rq_task->tk_msg.rpc_cred->cr_auth;
582  	unsigned int replen;
583  
584  	p = xdr_encode_fhandle(p, args->fh);
585  	req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
586  
587  	/* Inline the page array */
588  	replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS_readlinkres_sz) << 2;
589  	xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
590  	return 0;
591  }
592  
593  /*
594   * Decode READLINK reply
595   */
596  static int
nfs_xdr_readlinkres(struct rpc_rqst * req,__be32 * p,void * dummy)597  nfs_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, void *dummy)
598  {
599  	struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
600  	struct kvec *iov = rcvbuf->head;
601  	size_t hdrlen;
602  	u32 len, recvd;
603  	char	*kaddr;
604  	int	status;
605  
606  	if ((status = ntohl(*p++)))
607  		return nfs_stat_to_errno(status);
608  	/* Convert length of symlink */
609  	len = ntohl(*p++);
610  	if (len >= rcvbuf->page_len) {
611  		dprintk("nfs: server returned giant symlink!\n");
612  		return -ENAMETOOLONG;
613  	}
614  	hdrlen = (u8 *) p - (u8 *) iov->iov_base;
615  	if (iov->iov_len < hdrlen) {
616  		dprintk("NFS: READLINK reply header overflowed:"
617  				"length %Zu > %Zu\n", hdrlen, iov->iov_len);
618  		return -errno_NFSERR_IO;
619  	} else if (iov->iov_len != hdrlen) {
620  		dprintk("NFS: READLINK header is short. iovec will be shifted.\n");
621  		xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
622  	}
623  	recvd = req->rq_rcv_buf.len - hdrlen;
624  	if (recvd < len) {
625  		dprintk("NFS: server cheating in readlink reply: "
626  				"count %u > recvd %u\n", len, recvd);
627  		return -EIO;
628  	}
629  
630  	/* NULL terminate the string we got */
631  	kaddr = (char *)kmap_atomic(rcvbuf->pages[0], KM_USER0);
632  	kaddr[len+rcvbuf->page_base] = '\0';
633  	kunmap_atomic(kaddr, KM_USER0);
634  	return 0;
635  }
636  
637  /*
638   * Decode WRITE reply
639   */
640  static int
nfs_xdr_writeres(struct rpc_rqst * req,__be32 * p,struct nfs_writeres * res)641  nfs_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
642  {
643  	res->verf->committed = NFS_FILE_SYNC;
644  	return nfs_xdr_attrstat(req, p, res->fattr);
645  }
646  
647  /*
648   * Decode STATFS reply
649   */
650  static int
nfs_xdr_statfsres(struct rpc_rqst * req,__be32 * p,struct nfs2_fsstat * res)651  nfs_xdr_statfsres(struct rpc_rqst *req, __be32 *p, struct nfs2_fsstat *res)
652  {
653  	int	status;
654  
655  	if ((status = ntohl(*p++)))
656  		return nfs_stat_to_errno(status);
657  
658  	res->tsize  = ntohl(*p++);
659  	res->bsize  = ntohl(*p++);
660  	res->blocks = ntohl(*p++);
661  	res->bfree  = ntohl(*p++);
662  	res->bavail = ntohl(*p++);
663  	return 0;
664  }
665  
666  /*
667   * We need to translate between nfs status return values and
668   * the local errno values which may not be the same.
669   */
670  static struct {
671  	int stat;
672  	int errno;
673  } nfs_errtbl[] = {
674  	{ NFS_OK,		0		},
675  	{ NFSERR_PERM,		-EPERM		},
676  	{ NFSERR_NOENT,		-ENOENT		},
677  	{ NFSERR_IO,		-errno_NFSERR_IO},
678  	{ NFSERR_NXIO,		-ENXIO		},
679  /*	{ NFSERR_EAGAIN,	-EAGAIN		}, */
680  	{ NFSERR_ACCES,		-EACCES		},
681  	{ NFSERR_EXIST,		-EEXIST		},
682  	{ NFSERR_XDEV,		-EXDEV		},
683  	{ NFSERR_NODEV,		-ENODEV		},
684  	{ NFSERR_NOTDIR,	-ENOTDIR	},
685  	{ NFSERR_ISDIR,		-EISDIR		},
686  	{ NFSERR_INVAL,		-EINVAL		},
687  	{ NFSERR_FBIG,		-EFBIG		},
688  	{ NFSERR_NOSPC,		-ENOSPC		},
689  	{ NFSERR_ROFS,		-EROFS		},
690  	{ NFSERR_MLINK,		-EMLINK		},
691  	{ NFSERR_NAMETOOLONG,	-ENAMETOOLONG	},
692  	{ NFSERR_NOTEMPTY,	-ENOTEMPTY	},
693  	{ NFSERR_DQUOT,		-EDQUOT		},
694  	{ NFSERR_STALE,		-ESTALE		},
695  	{ NFSERR_REMOTE,	-EREMOTE	},
696  #ifdef EWFLUSH
697  	{ NFSERR_WFLUSH,	-EWFLUSH	},
698  #endif
699  	{ NFSERR_BADHANDLE,	-EBADHANDLE	},
700  	{ NFSERR_NOT_SYNC,	-ENOTSYNC	},
701  	{ NFSERR_BAD_COOKIE,	-EBADCOOKIE	},
702  	{ NFSERR_NOTSUPP,	-ENOTSUPP	},
703  	{ NFSERR_TOOSMALL,	-ETOOSMALL	},
704  	{ NFSERR_SERVERFAULT,	-ESERVERFAULT	},
705  	{ NFSERR_BADTYPE,	-EBADTYPE	},
706  	{ NFSERR_JUKEBOX,	-EJUKEBOX	},
707  	{ -1,			-EIO		}
708  };
709  
710  /*
711   * Convert an NFS error code to a local one.
712   * This one is used jointly by NFSv2 and NFSv3.
713   */
714  int
nfs_stat_to_errno(int stat)715  nfs_stat_to_errno(int stat)
716  {
717  	int i;
718  
719  	for (i = 0; nfs_errtbl[i].stat != -1; i++) {
720  		if (nfs_errtbl[i].stat == stat)
721  			return nfs_errtbl[i].errno;
722  	}
723  	dprintk("nfs_stat_to_errno: bad nfs status return value: %d\n", stat);
724  	return nfs_errtbl[i].errno;
725  }
726  
727  #define PROC(proc, argtype, restype, timer)				\
728  [NFSPROC_##proc] = {							\
729  	.p_proc	    =  NFSPROC_##proc,					\
730  	.p_encode   =  (kxdrproc_t) nfs_xdr_##argtype,			\
731  	.p_decode   =  (kxdrproc_t) nfs_xdr_##restype,			\
732  	.p_arglen   =  NFS_##argtype##_sz,				\
733  	.p_replen   =  NFS_##restype##_sz,				\
734  	.p_timer    =  timer,						\
735  	.p_statidx  =  NFSPROC_##proc,					\
736  	.p_name     =  #proc,						\
737  	}
738  struct rpc_procinfo	nfs_procedures[] = {
739      PROC(GETATTR,	fhandle,	attrstat, 1),
740      PROC(SETATTR,	sattrargs,	attrstat, 0),
741      PROC(LOOKUP,	diropargs,	diropres, 2),
742      PROC(READLINK,	readlinkargs,	readlinkres, 3),
743      PROC(READ,		readargs,	readres, 3),
744      PROC(WRITE,		writeargs,	writeres, 4),
745      PROC(CREATE,	createargs,	diropres, 0),
746      PROC(REMOVE,	removeargs,	stat, 0),
747      PROC(RENAME,	renameargs,	stat, 0),
748      PROC(LINK,		linkargs,	stat, 0),
749      PROC(SYMLINK,	symlinkargs,	stat, 0),
750      PROC(MKDIR,		createargs,	diropres, 0),
751      PROC(RMDIR,		diropargs,	stat, 0),
752      PROC(READDIR,	readdirargs,	readdirres, 3),
753      PROC(STATFS,	fhandle,	statfsres, 0),
754  };
755  
756  struct rpc_version		nfs_version2 = {
757  	.number			= 2,
758  	.nrprocs		= ARRAY_SIZE(nfs_procedures),
759  	.procs			= nfs_procedures
760  };
761