]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/nfs/nfs2xdr.c
NFS: Replace old NFSv2 decoder functions with xdr_stream-based ones
[mirror_ubuntu-artful-kernel.git] / fs / nfs / nfs2xdr.c
CommitLineData
1da177e4
LT
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>
1da177e4
LT
15#include <linux/errno.h>
16#include <linux/string.h>
17#include <linux/in.h>
18#include <linux/pagemap.h>
19#include <linux/proc_fs.h>
20#include <linux/sunrpc/clnt.h>
21#include <linux/nfs.h>
22#include <linux/nfs2.h>
23#include <linux/nfs_fs.h>
816724e6 24#include "internal.h"
1da177e4
LT
25
26#define NFSDBG_FACILITY NFSDBG_XDR
1da177e4 27
1da177e4
LT
28/* Mapping from NFS error code to "errno" error code. */
29#define errno_NFSERR_IO EIO
30
31/*
32 * Declare the space requirements for NFS arguments and replies as
33 * number of 32bit-words
34 */
35#define NFS_fhandle_sz (8)
36#define NFS_sattr_sz (8)
37#define NFS_filename_sz (1+(NFS2_MAXNAMLEN>>2))
38#define NFS_path_sz (1+(NFS2_MAXPATHLEN>>2))
39#define NFS_fattr_sz (17)
40#define NFS_info_sz (5)
41#define NFS_entry_sz (NFS_filename_sz+3)
42
43#define NFS_diropargs_sz (NFS_fhandle_sz+NFS_filename_sz)
4fdc17b2 44#define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
1da177e4
LT
45#define NFS_sattrargs_sz (NFS_fhandle_sz+NFS_sattr_sz)
46#define NFS_readlinkargs_sz (NFS_fhandle_sz)
47#define NFS_readargs_sz (NFS_fhandle_sz+3)
48#define NFS_writeargs_sz (NFS_fhandle_sz+4)
49#define NFS_createargs_sz (NFS_diropargs_sz+NFS_sattr_sz)
50#define NFS_renameargs_sz (NFS_diropargs_sz+NFS_diropargs_sz)
51#define NFS_linkargs_sz (NFS_fhandle_sz+NFS_diropargs_sz)
94a6d753 52#define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz)
1da177e4
LT
53#define NFS_readdirargs_sz (NFS_fhandle_sz+2)
54
55#define NFS_attrstat_sz (1+NFS_fattr_sz)
56#define NFS_diropres_sz (1+NFS_fhandle_sz+NFS_fattr_sz)
57#define NFS_readlinkres_sz (2)
58#define NFS_readres_sz (1+NFS_fattr_sz+1)
59#define NFS_writeres_sz (NFS_attrstat_sz)
60#define NFS_stat_sz (1)
61#define NFS_readdirres_sz (1)
62#define NFS_statfsres_sz (1+NFS_info_sz)
63
25a0866c
CL
64
65/*
66 * While encoding arguments, set up the reply buffer in advance to
67 * receive reply data directly into the page cache.
68 */
69static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
70 unsigned int base, unsigned int len,
71 unsigned int bufsize)
72{
73 struct rpc_auth *auth = req->rq_cred->cr_auth;
74 unsigned int replen;
75
76 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
77 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
78}
79
f796f8b3
CL
80/*
81 * Handle decode buffer overflows out-of-line.
82 */
83static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
84{
85 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
86 "Remaining buffer length is %tu words.\n",
87 func, xdr->end - xdr->p);
88}
89
25a0866c 90
1da177e4
LT
91/*
92 * Common NFS XDR functions as inlines
93 */
9d787a75
AV
94static inline __be32*
95xdr_decode_time(__be32 *p, struct timespec *timep)
1da177e4
LT
96{
97 timep->tv_sec = ntohl(*p++);
98 /* Convert microseconds into nanoseconds */
99 timep->tv_nsec = ntohl(*p++) * 1000;
100 return p;
101}
102
9d787a75
AV
103static __be32 *
104xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
1da177e4 105{
bca79478
TM
106 u32 rdev, type;
107 type = ntohl(*p++);
1da177e4
LT
108 fattr->mode = ntohl(*p++);
109 fattr->nlink = ntohl(*p++);
110 fattr->uid = ntohl(*p++);
111 fattr->gid = ntohl(*p++);
112 fattr->size = ntohl(*p++);
113 fattr->du.nfs2.blocksize = ntohl(*p++);
114 rdev = ntohl(*p++);
115 fattr->du.nfs2.blocks = ntohl(*p++);
8b4bdcf8
TM
116 fattr->fsid.major = ntohl(*p++);
117 fattr->fsid.minor = 0;
1da177e4
LT
118 fattr->fileid = ntohl(*p++);
119 p = xdr_decode_time(p, &fattr->atime);
120 p = xdr_decode_time(p, &fattr->mtime);
121 p = xdr_decode_time(p, &fattr->ctime);
9e6e70f8 122 fattr->valid |= NFS_ATTR_FATTR_V2;
1da177e4 123 fattr->rdev = new_decode_dev(rdev);
bca79478 124 if (type == NFCHR && rdev == NFS2_FIFO_DEV) {
1da177e4
LT
125 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
126 fattr->rdev = 0;
127 }
1da177e4
LT
128 return p;
129}
130
25a0866c
CL
131/*
132 * Encode/decode NFSv2 basic data types
133 *
134 * Basic NFSv2 data types are defined in section 2.3 of RFC 1094:
135 * "NFS: Network File System Protocol Specification".
136 *
137 * Not all basic data types have their own encoding and decoding
138 * functions. For run-time efficiency, some data types are encoded
139 * or decoded inline.
140 */
141
f796f8b3
CL
142/*
143 * typedef opaque nfsdata<>;
144 */
145static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
146{
147 u32 recvd, count;
148 size_t hdrlen;
149 __be32 *p;
150
151 p = xdr_inline_decode(xdr, 4);
152 if (unlikely(p == NULL))
153 goto out_overflow;
154 count = be32_to_cpup(p);
155 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
156 recvd = xdr->buf->len - hdrlen;
157 if (unlikely(count > recvd))
158 goto out_cheating;
159out:
160 xdr_read_pages(xdr, count);
161 result->eof = 0; /* NFSv2 does not pass EOF flag on the wire. */
162 result->count = count;
163 return count;
164out_cheating:
165 dprintk("NFS: server cheating in read result: "
166 "count %u > recvd %u\n", count, recvd);
167 count = recvd;
168 goto out;
169out_overflow:
170 print_overflow_msg(__func__, xdr);
171 return -EIO;
172}
173
174/*
175 * enum stat {
176 * NFS_OK = 0,
177 * NFSERR_PERM = 1,
178 * NFSERR_NOENT = 2,
179 * NFSERR_IO = 5,
180 * NFSERR_NXIO = 6,
181 * NFSERR_ACCES = 13,
182 * NFSERR_EXIST = 17,
183 * NFSERR_NODEV = 19,
184 * NFSERR_NOTDIR = 20,
185 * NFSERR_ISDIR = 21,
186 * NFSERR_FBIG = 27,
187 * NFSERR_NOSPC = 28,
188 * NFSERR_ROFS = 30,
189 * NFSERR_NAMETOOLONG = 63,
190 * NFSERR_NOTEMPTY = 66,
191 * NFSERR_DQUOT = 69,
192 * NFSERR_STALE = 70,
193 * NFSERR_WFLUSH = 99
194 * };
195 */
196static int decode_stat(struct xdr_stream *xdr, enum nfs_stat *status)
197{
198 __be32 *p;
199
200 p = xdr_inline_decode(xdr, 4);
201 if (unlikely(p == NULL))
202 goto out_overflow;
203 *status = be32_to_cpup(p);
204 return 0;
205out_overflow:
206 print_overflow_msg(__func__, xdr);
207 return -EIO;
208}
209
25a0866c
CL
210/*
211 * 2.3.3. fhandle
212 *
213 * typedef opaque fhandle[FHSIZE];
214 */
215static void encode_fhandle(struct xdr_stream *xdr, const struct nfs_fh *fh)
216{
217 __be32 *p;
218
219 BUG_ON(fh->size != NFS2_FHSIZE);
220 p = xdr_reserve_space(xdr, NFS2_FHSIZE);
221 memcpy(p, fh->data, NFS2_FHSIZE);
222}
223
f796f8b3
CL
224static int decode_fhandle(struct xdr_stream *xdr, struct nfs_fh *fh)
225{
226 __be32 *p;
227
228 p = xdr_inline_decode(xdr, NFS2_FHSIZE);
229 if (unlikely(p == NULL))
230 goto out_overflow;
231 fh->size = NFS2_FHSIZE;
232 memcpy(fh->data, p, NFS2_FHSIZE);
233 return 0;
234out_overflow:
235 print_overflow_msg(__func__, xdr);
236 return -EIO;
237}
238
282ac2a5
CL
239/*
240 * 2.3.4. timeval
241 *
242 * struct timeval {
243 * unsigned int seconds;
244 * unsigned int useconds;
245 * };
246 */
247static __be32 *xdr_encode_time(__be32 *p, const struct timespec *timep)
248{
249 *p++ = cpu_to_be32(timep->tv_sec);
250 if (timep->tv_nsec != 0)
251 *p++ = cpu_to_be32(timep->tv_nsec / NSEC_PER_USEC);
252 else
253 *p++ = cpu_to_be32(0);
254 return p;
255}
256
257/*
258 * Passing the invalid value useconds=1000000 is a Sun convention for
259 * "set to current server time". It's needed to make permissions checks
260 * for the "touch" program across v2 mounts to Solaris and Irix servers
261 * work correctly. See description of sattr in section 6.1 of "NFS
262 * Illustrated" by Brent Callaghan, Addison-Wesley, ISBN 0-201-32750-5.
263 */
264static __be32 *xdr_encode_current_server_time(__be32 *p,
265 const struct timespec *timep)
266{
267 *p++ = cpu_to_be32(timep->tv_sec);
268 *p++ = cpu_to_be32(1000000);
269 return p;
270}
271
f796f8b3
CL
272/*
273 * 2.3.5. fattr
274 *
275 * struct fattr {
276 * ftype type;
277 * unsigned int mode;
278 * unsigned int nlink;
279 * unsigned int uid;
280 * unsigned int gid;
281 * unsigned int size;
282 * unsigned int blocksize;
283 * unsigned int rdev;
284 * unsigned int blocks;
285 * unsigned int fsid;
286 * unsigned int fileid;
287 * timeval atime;
288 * timeval mtime;
289 * timeval ctime;
290 * };
291 *
292 */
293static int decode_fattr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
294{
295 __be32 *p;
296
297 p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
298 if (unlikely(p == NULL))
299 goto out_overflow;
300 xdr_decode_fattr(p, fattr);
301 return 0;
302out_overflow:
303 print_overflow_msg(__func__, xdr);
304 return -EIO;
305}
306
25a0866c
CL
307/*
308 * 2.3.6. sattr
309 *
310 * struct sattr {
311 * unsigned int mode;
312 * unsigned int uid;
313 * unsigned int gid;
314 * unsigned int size;
315 * timeval atime;
316 * timeval mtime;
317 * };
318 */
319
320#define NFS2_SATTR_NOT_SET (0xffffffff)
321
322static __be32 *xdr_time_not_set(__be32 *p)
323{
324 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
325 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
326 return p;
327}
328
329static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
330{
331 __be32 *p;
332
333 p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
334
335 if (attr->ia_valid & ATTR_MODE)
336 *p++ = cpu_to_be32(attr->ia_mode);
337 else
338 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
339 if (attr->ia_valid & ATTR_UID)
340 *p++ = cpu_to_be32(attr->ia_uid);
341 else
342 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
343 if (attr->ia_valid & ATTR_GID)
344 *p++ = cpu_to_be32(attr->ia_gid);
345 else
346 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
347 if (attr->ia_valid & ATTR_SIZE)
348 *p++ = cpu_to_be32((u32)attr->ia_size);
349 else
350 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
351
352 if (attr->ia_valid & ATTR_ATIME_SET)
353 p = xdr_encode_time(p, &attr->ia_atime);
354 else if (attr->ia_valid & ATTR_ATIME)
355 p = xdr_encode_current_server_time(p, &attr->ia_atime);
356 else
357 p = xdr_time_not_set(p);
358 if (attr->ia_valid & ATTR_MTIME_SET)
359 xdr_encode_time(p, &attr->ia_mtime);
360 else if (attr->ia_valid & ATTR_MTIME)
361 xdr_encode_current_server_time(p, &attr->ia_mtime);
362 else
363 xdr_time_not_set(p);
364}
365
366/*
367 * 2.3.7. filename
368 *
369 * typedef string filename<MAXNAMLEN>;
370 */
371static void encode_filename(struct xdr_stream *xdr,
372 const char *name, u32 length)
373{
374 __be32 *p;
375
376 BUG_ON(length > NFS2_MAXNAMLEN);
377 p = xdr_reserve_space(xdr, 4 + length);
378 xdr_encode_opaque(p, name, length);
379}
380
f796f8b3
CL
381static int decode_filename_inline(struct xdr_stream *xdr,
382 const char **name, u32 *length)
383{
384 __be32 *p;
385 u32 count;
386
387 p = xdr_inline_decode(xdr, 4);
388 if (unlikely(p == NULL))
389 goto out_overflow;
390 count = be32_to_cpup(p);
391 if (count > NFS3_MAXNAMLEN)
392 goto out_nametoolong;
393 p = xdr_inline_decode(xdr, count);
394 if (unlikely(p == NULL))
395 goto out_overflow;
396 *name = (const char *)p;
397 *length = count;
398 return 0;
399out_nametoolong:
400 dprintk("NFS: returned filename too long: %u\n", count);
401 return -ENAMETOOLONG;
402out_overflow:
403 print_overflow_msg(__func__, xdr);
404 return -EIO;
405}
406
25a0866c
CL
407/*
408 * 2.3.8. path
409 *
410 * typedef string path<MAXPATHLEN>;
411 */
412static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
413{
414 __be32 *p;
415
416 BUG_ON(length > NFS2_MAXPATHLEN);
417 p = xdr_reserve_space(xdr, 4);
418 *p = cpu_to_be32(length);
419 xdr_write_pages(xdr, pages, 0, length);
420}
421
f796f8b3
CL
422static int decode_path(struct xdr_stream *xdr)
423{
424 u32 length, recvd;
425 size_t hdrlen;
426 __be32 *p;
427
428 p = xdr_inline_decode(xdr, 4);
429 if (unlikely(p == NULL))
430 goto out_overflow;
431 length = be32_to_cpup(p);
432 if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
433 goto out_size;
434 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
435 recvd = xdr->buf->len - hdrlen;
436 if (unlikely(length > recvd))
437 goto out_cheating;
438
439 xdr_read_pages(xdr, length);
440 xdr_terminate_string(xdr->buf, length);
441 return 0;
442out_size:
443 dprintk("NFS: returned pathname too long: %u\n", length);
444 return -ENAMETOOLONG;
445out_cheating:
446 dprintk("NFS: server cheating in pathname result: "
447 "length %u > received %u\n", length, recvd);
448 return -EIO;
449out_overflow:
450 print_overflow_msg(__func__, xdr);
451 return -EIO;
452}
453
454/*
455 * 2.3.9. attrstat
456 *
457 * union attrstat switch (stat status) {
458 * case NFS_OK:
459 * fattr attributes;
460 * default:
461 * void;
462 * };
463 */
464static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result)
465{
466 enum nfs_stat status;
467 int error;
468
469 error = decode_stat(xdr, &status);
470 if (unlikely(error))
471 goto out;
472 if (status != NFS_OK)
473 goto out_default;
474 error = decode_fattr(xdr, result);
475out:
476 return error;
477out_default:
478 return nfs_stat_to_errno(status);
479}
480
25a0866c
CL
481/*
482 * 2.3.10. diropargs
483 *
484 * struct diropargs {
485 * fhandle dir;
486 * filename name;
487 * };
488 */
489static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
490 const char *name, u32 length)
491{
492 encode_fhandle(xdr, fh);
493 encode_filename(xdr, name, length);
494}
495
f796f8b3
CL
496/*
497 * 2.3.11. diropres
498 *
499 * union diropres switch (stat status) {
500 * case NFS_OK:
501 * struct {
502 * fhandle file;
503 * fattr attributes;
504 * } diropok;
505 * default:
506 * void;
507 * };
508 */
509static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
510{
511 int error;
512
513 error = decode_fhandle(xdr, result->fh);
514 if (unlikely(error))
515 goto out;
516 error = decode_fattr(xdr, result->fattr);
517out:
518 return error;
519}
520
521static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
522{
523 enum nfs_stat status;
524 int error;
525
526 error = decode_stat(xdr, &status);
527 if (unlikely(error))
528 goto out;
529 if (status != NFS_OK)
530 goto out_default;
531 error = decode_diropok(xdr, result);
532out:
533 return error;
534out_default:
535 return nfs_stat_to_errno(status);
536}
537
25a0866c 538
1da177e4 539/*
2d70f533
CL
540 * NFSv2 XDR encode functions
541 *
542 * NFSv2 argument types are defined in section 2.2 of RFC 1094:
543 * "NFS: Network File System Protocol Specification".
1da177e4 544 */
1da177e4 545
25a0866c
CL
546static int nfs2_xdr_enc_fhandle(struct rpc_rqst *req, __be32 *p,
547 const struct nfs_fh *fh)
548{
549 struct xdr_stream xdr;
550
551 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
552 encode_fhandle(&xdr, fh);
553 return 0;
554}
555
25a0866c
CL
556/*
557 * 2.2.3. sattrargs
558 *
559 * struct sattrargs {
560 * fhandle file;
561 * sattr attributes;
562 * };
563 */
564static int nfs2_xdr_enc_sattrargs(struct rpc_rqst *req, __be32 *p,
565 const struct nfs_sattrargs *args)
566{
567 struct xdr_stream xdr;
568
569 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
570 encode_fhandle(&xdr, args->fh);
571 encode_sattr(&xdr, args->sattr);
572 return 0;
573}
574
25a0866c
CL
575static int nfs2_xdr_enc_diropargs(struct rpc_rqst *req, __be32 *p,
576 const struct nfs_diropargs *args)
577{
578 struct xdr_stream xdr;
579
580 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
581 encode_diropargs(&xdr, args->fh, args->name, args->len);
582 return 0;
583}
584
25a0866c
CL
585static int nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req, __be32 *p,
586 const struct nfs_readlinkargs *args)
587{
588 struct xdr_stream xdr;
589
590 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
591 encode_fhandle(&xdr, args->fh);
592 prepare_reply_buffer(req, args->pages, args->pgbase,
593 args->pglen, NFS_readlinkres_sz);
594 return 0;
595}
596
25a0866c
CL
597/*
598 * 2.2.7. readargs
599 *
600 * struct readargs {
601 * fhandle file;
602 * unsigned offset;
603 * unsigned count;
604 * unsigned totalcount;
605 * };
606 */
607static void encode_readargs(struct xdr_stream *xdr,
608 const struct nfs_readargs *args)
609{
610 u32 offset = args->offset;
611 u32 count = args->count;
612 __be32 *p;
613
614 encode_fhandle(xdr, args->fh);
615
616 p = xdr_reserve_space(xdr, 4 + 4 + 4);
617 *p++ = cpu_to_be32(offset);
618 *p++ = cpu_to_be32(count);
619 *p = cpu_to_be32(count);
620}
621
622static int nfs2_xdr_enc_readargs(struct rpc_rqst *req, __be32 *p,
623 const struct nfs_readargs *args)
624{
625 struct xdr_stream xdr;
626
627 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
628 encode_readargs(&xdr, args);
629 prepare_reply_buffer(req, args->pages, args->pgbase,
630 args->count, NFS_readres_sz);
631 req->rq_rcv_buf.flags |= XDRBUF_READ;
632 return 0;
633}
634
25a0866c
CL
635/*
636 * 2.2.9. writeargs
637 *
638 * struct writeargs {
639 * fhandle file;
640 * unsigned beginoffset;
641 * unsigned offset;
642 * unsigned totalcount;
643 * nfsdata data;
644 * };
645 */
646static void encode_writeargs(struct xdr_stream *xdr,
647 const struct nfs_writeargs *args)
648{
649 u32 offset = args->offset;
650 u32 count = args->count;
651 __be32 *p;
652
653 encode_fhandle(xdr, args->fh);
654
655 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
656 *p++ = cpu_to_be32(offset);
657 *p++ = cpu_to_be32(offset);
658 *p++ = cpu_to_be32(count);
659
660 /* nfsdata */
661 *p = cpu_to_be32(count);
662 xdr_write_pages(xdr, args->pages, args->pgbase, count);
663}
664
665static int nfs2_xdr_enc_writeargs(struct rpc_rqst *req, __be32 *p,
666 const struct nfs_writeargs *args)
667{
668 struct xdr_stream xdr;
669
670 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
671 encode_writeargs(&xdr, args);
672 xdr.buf->flags |= XDRBUF_WRITE;
673 return 0;
674}
675
25a0866c
CL
676/*
677 * 2.2.10. createargs
678 *
679 * struct createargs {
680 * diropargs where;
681 * sattr attributes;
682 * };
683 */
684static int nfs2_xdr_enc_createargs(struct rpc_rqst *req, __be32 *p,
685 const struct nfs_createargs *args)
686{
687 struct xdr_stream xdr;
688
689 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
690 encode_diropargs(&xdr, args->fh, args->name, args->len);
691 encode_sattr(&xdr, args->sattr);
692 return 0;
693}
694
695static int nfs2_xdr_enc_removeargs(struct rpc_rqst *req, __be32 *p,
696 const struct nfs_removeargs *args)
697{
698 struct xdr_stream xdr;
699
700 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
701 encode_diropargs(&xdr, args->fh, args->name.name, args->name.len);
702 return 0;
703}
704
25a0866c
CL
705/*
706 * 2.2.12. renameargs
707 *
708 * struct renameargs {
709 * diropargs from;
710 * diropargs to;
711 * };
712 */
713static int nfs2_xdr_enc_renameargs(struct rpc_rqst *req, __be32 *p,
714 const struct nfs_renameargs *args)
715{
716 const struct qstr *old = args->old_name;
717 const struct qstr *new = args->new_name;
718 struct xdr_stream xdr;
719
720 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
721 encode_diropargs(&xdr, args->old_dir, old->name, old->len);
722 encode_diropargs(&xdr, args->new_dir, new->name, new->len);
723 return 0;
724}
725
25a0866c
CL
726/*
727 * 2.2.13. linkargs
728 *
729 * struct linkargs {
730 * fhandle from;
731 * diropargs to;
732 * };
733 */
734static int nfs2_xdr_enc_linkargs(struct rpc_rqst *req, __be32 *p,
735 const struct nfs_linkargs *args)
736{
737 struct xdr_stream xdr;
738
739 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
740 encode_fhandle(&xdr, args->fromfh);
741 encode_diropargs(&xdr, args->tofh, args->toname, args->tolen);
742 return 0;
743}
744
25a0866c
CL
745/*
746 * 2.2.14. symlinkargs
747 *
748 * struct symlinkargs {
749 * diropargs from;
750 * path to;
751 * sattr attributes;
752 * };
753 */
754static int nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req, __be32 *p,
755 const struct nfs_symlinkargs *args)
756{
757 struct xdr_stream xdr;
758
759 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
760 encode_diropargs(&xdr, args->fromfh, args->fromname, args->fromlen);
761 encode_path(&xdr, args->pages, args->pathlen);
762 encode_sattr(&xdr, args->sattr);
763 return 0;
764}
765
25a0866c
CL
766/*
767 * 2.2.17. readdirargs
768 *
769 * struct readdirargs {
770 * fhandle dir;
771 * nfscookie cookie;
772 * unsigned count;
773 * };
774 */
775static void encode_readdirargs(struct xdr_stream *xdr,
776 const struct nfs_readdirargs *args)
777{
778 __be32 *p;
779
780 encode_fhandle(xdr, args->fh);
781
782 p = xdr_reserve_space(xdr, 4 + 4);
783 *p++ = cpu_to_be32(args->cookie);
784 *p = cpu_to_be32(args->count);
785}
786
787static int nfs2_xdr_enc_readdirargs(struct rpc_rqst *req, __be32 *p,
788 const struct nfs_readdirargs *args)
789{
790 struct xdr_stream xdr;
791
792 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
793 encode_readdirargs(&xdr, args);
794 prepare_reply_buffer(req, args->pages, 0,
795 args->count, NFS_readdirres_sz);
796 return 0;
797}
798
1da177e4 799/*
661ad423
CL
800 * NFSv2 XDR decode functions
801 *
802 * NFSv2 result types are defined in section 2.2 of RFC 1094:
803 * "NFS: Network File System Protocol Specification".
1da177e4 804 */
1da177e4 805
f796f8b3
CL
806static int nfs2_xdr_dec_stat(struct rpc_rqst *req, __be32 *p,
807 void *__unused)
808{
809 struct xdr_stream xdr;
810 enum nfs_stat status;
811 int error;
812
813 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
814 error = decode_stat(&xdr, &status);
815 if (unlikely(error))
816 goto out;
817 if (status != NFS_OK)
818 goto out_default;
819out:
820 return error;
821out_default:
822 return nfs_stat_to_errno(status);
823}
824
f796f8b3
CL
825static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, __be32 *p,
826 struct nfs_fattr *result)
827{
828 struct xdr_stream xdr;
829
830 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
831 return decode_attrstat(&xdr, result);
832}
833
f796f8b3
CL
834static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, __be32 *p,
835 struct nfs_diropok *result)
836{
837 struct xdr_stream xdr;
838
839 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
840 return decode_diropres(&xdr, result);
841}
842
f796f8b3
CL
843/*
844 * 2.2.6. readlinkres
845 *
846 * union readlinkres switch (stat status) {
847 * case NFS_OK:
848 * path data;
849 * default:
850 * void;
851 * };
852 */
853static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req, __be32 *p,
854 void *__unused)
855{
856 struct xdr_stream xdr;
857 enum nfs_stat status;
858 int error;
859
860 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
861 error = decode_stat(&xdr, &status);
862 if (unlikely(error))
863 goto out;
864 if (status != NFS_OK)
865 goto out_default;
866 error = decode_path(&xdr);
867out:
868 return error;
869out_default:
870 return nfs_stat_to_errno(status);
871}
872
873/*
874 * 2.2.7. readres
875 *
876 * union readres switch (stat status) {
877 * case NFS_OK:
878 * fattr attributes;
879 * nfsdata data;
880 * default:
881 * void;
882 * };
883 */
884static int nfs2_xdr_dec_readres(struct rpc_rqst *req, __be32 *p,
885 struct nfs_readres *result)
886{
887 struct xdr_stream xdr;
888 enum nfs_stat status;
889 int error;
890
891 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
892 error = decode_stat(&xdr, &status);
893 if (unlikely(error))
894 goto out;
895 if (status != NFS_OK)
896 goto out_default;
897 error = decode_fattr(&xdr, result->fattr);
898 if (unlikely(error))
899 goto out;
900 error = decode_nfsdata(&xdr, result);
901out:
902 return error;
903out_default:
904 return nfs_stat_to_errno(status);
905}
906
f796f8b3
CL
907static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, __be32 *p,
908 struct nfs_writeres *result)
909{
910 struct xdr_stream xdr;
911
912 /* All NFSv2 writes are "file sync" writes */
913 result->verf->committed = NFS_FILE_SYNC;
914
915 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
916 return decode_attrstat(&xdr, result->fattr);
917}
918
919/**
920 * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
921 * the local page cache.
922 * @xdr: XDR stream where entry resides
923 * @entry: buffer to fill in with entry data
924 * @server: nfs_server data for this directory
925 * @plus: boolean indicating whether this should be a readdirplus entry
926 *
927 * Returns the position of the next item in the buffer, or an ERR_PTR.
928 *
929 * This function is not invoked during READDIR reply decoding, but
930 * rather whenever an application invokes the getdents(2) system call
931 * on a directory already in our cache.
932 *
933 * 2.2.17. entry
934 *
935 * struct entry {
936 * unsigned fileid;
937 * filename name;
938 * nfscookie cookie;
939 * entry *nextentry;
940 * };
941 */
942__be32 *nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
943 struct nfs_server *server, int plus)
944{
945 __be32 *p;
946 int error;
947
948 p = xdr_inline_decode(xdr, 4);
949 if (unlikely(p == NULL))
950 goto out_overflow;
951 if (*p++ == xdr_zero) {
952 p = xdr_inline_decode(xdr, 4);
953 if (unlikely(p == NULL))
954 goto out_overflow;
955 if (*p++ == xdr_zero)
956 return ERR_PTR(-EAGAIN);
957 entry->eof = 1;
958 return ERR_PTR(-EBADCOOKIE);
959 }
960
961 p = xdr_inline_decode(xdr, 4);
962 if (unlikely(p == NULL))
963 goto out_overflow;
964 entry->ino = be32_to_cpup(p);
965
966 error = decode_filename_inline(xdr, &entry->name, &entry->len);
967 if (unlikely(error))
968 return ERR_PTR(error);
969
970 /*
971 * The type (size and byte order) of nfscookie isn't defined in
972 * RFC 1094. This implementation assumes that it's an XDR uint32.
973 */
974 entry->prev_cookie = entry->cookie;
975 p = xdr_inline_decode(xdr, 4);
976 if (unlikely(p == NULL))
977 goto out_overflow;
978 entry->cookie = be32_to_cpup(p);
979
980 entry->d_type = DT_UNKNOWN;
981
982 /* Peek at the next entry to see if we're at EOD */
983 p = xdr_inline_peek(xdr, 4 + 4);
984 entry->eof = 0;
985 if (p != NULL)
986 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
987 return p;
988
989out_overflow:
990 print_overflow_msg(__func__, xdr);
991 return ERR_PTR(-EAGAIN);
992}
993
994/*
995 * 2.2.17. readdirres
996 *
997 * union readdirres switch (stat status) {
998 * case NFS_OK:
999 * struct {
1000 * entry *entries;
1001 * bool eof;
1002 * } readdirok;
1003 * default:
1004 * void;
1005 * };
1006 *
1007 * Read the directory contents into the page cache, but don't
1008 * touch them. The actual decoding is done by nfs2_decode_dirent()
1009 * during subsequent nfs_readdir() calls.
1010 */
1011static int decode_readdirok(struct xdr_stream *xdr)
1012{
1013 u32 recvd, pglen;
1014 size_t hdrlen;
1015
1016 pglen = xdr->buf->page_len;
1017 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1018 recvd = xdr->buf->len - hdrlen;
1019 if (unlikely(pglen > recvd))
1020 goto out_cheating;
1021out:
1022 xdr_read_pages(xdr, pglen);
1023 return pglen;
1024out_cheating:
1025 dprintk("NFS: server cheating in readdir result: "
1026 "pglen %u > recvd %u\n", pglen, recvd);
1027 pglen = recvd;
1028 goto out;
1029}
1030
1031static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req, __be32 *p,
1032 void *__unused)
1033{
1034 struct xdr_stream xdr;
1035 enum nfs_stat status;
1036 int error;
1037
1038 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1039 error = decode_stat(&xdr, &status);
1040 if (unlikely(error))
1041 goto out;
1042 if (status != NFS_OK)
1043 goto out_default;
1044 error = decode_readdirok(&xdr);
1045out:
1046 return error;
1047out_default:
1048 return nfs_stat_to_errno(status);
1049}
1050
f796f8b3
CL
1051/*
1052 * 2.2.18. statfsres
1053 *
1054 * union statfsres (stat status) {
1055 * case NFS_OK:
1056 * struct {
1057 * unsigned tsize;
1058 * unsigned bsize;
1059 * unsigned blocks;
1060 * unsigned bfree;
1061 * unsigned bavail;
1062 * } info;
1063 * default:
1064 * void;
1065 * };
1066 */
1067static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1068{
1069 __be32 *p;
1070
1071 p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1072 if (unlikely(p == NULL))
1073 goto out_overflow;
1074 result->tsize = be32_to_cpup(p++);
1075 result->bsize = be32_to_cpup(p++);
1076 result->blocks = be32_to_cpup(p++);
1077 result->bfree = be32_to_cpup(p++);
1078 result->bavail = be32_to_cpup(p);
1079 return 0;
1080out_overflow:
1081 print_overflow_msg(__func__, xdr);
1082 return -EIO;
1083}
1084
1085static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, __be32 *p,
1086 struct nfs2_fsstat *result)
1087{
1088 struct xdr_stream xdr;
1089 enum nfs_stat status;
1090 int error;
1091
1092 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1093 error = decode_stat(&xdr, &status);
1094 if (unlikely(error))
1095 goto out;
1096 if (status != NFS_OK)
1097 goto out_default;
1098 error = decode_info(&xdr, result);
1099out:
1100 return error;
1101out_default:
1102 return nfs_stat_to_errno(status);
1103}
1104
1105
1da177e4
LT
1106/*
1107 * We need to translate between nfs status return values and
1108 * the local errno values which may not be the same.
1109 */
85828493 1110static const struct {
1da177e4
LT
1111 int stat;
1112 int errno;
1113} nfs_errtbl[] = {
1114 { NFS_OK, 0 },
856dff3d
BH
1115 { NFSERR_PERM, -EPERM },
1116 { NFSERR_NOENT, -ENOENT },
1117 { NFSERR_IO, -errno_NFSERR_IO},
1118 { NFSERR_NXIO, -ENXIO },
1119/* { NFSERR_EAGAIN, -EAGAIN }, */
1120 { NFSERR_ACCES, -EACCES },
1121 { NFSERR_EXIST, -EEXIST },
1122 { NFSERR_XDEV, -EXDEV },
1123 { NFSERR_NODEV, -ENODEV },
1124 { NFSERR_NOTDIR, -ENOTDIR },
1125 { NFSERR_ISDIR, -EISDIR },
1126 { NFSERR_INVAL, -EINVAL },
1127 { NFSERR_FBIG, -EFBIG },
1128 { NFSERR_NOSPC, -ENOSPC },
1129 { NFSERR_ROFS, -EROFS },
1130 { NFSERR_MLINK, -EMLINK },
1131 { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
1132 { NFSERR_NOTEMPTY, -ENOTEMPTY },
1133 { NFSERR_DQUOT, -EDQUOT },
1134 { NFSERR_STALE, -ESTALE },
1135 { NFSERR_REMOTE, -EREMOTE },
1da177e4 1136#ifdef EWFLUSH
856dff3d 1137 { NFSERR_WFLUSH, -EWFLUSH },
1da177e4 1138#endif
856dff3d
BH
1139 { NFSERR_BADHANDLE, -EBADHANDLE },
1140 { NFSERR_NOT_SYNC, -ENOTSYNC },
1141 { NFSERR_BAD_COOKIE, -EBADCOOKIE },
1142 { NFSERR_NOTSUPP, -ENOTSUPP },
1143 { NFSERR_TOOSMALL, -ETOOSMALL },
fdcb4577 1144 { NFSERR_SERVERFAULT, -EREMOTEIO },
856dff3d
BH
1145 { NFSERR_BADTYPE, -EBADTYPE },
1146 { NFSERR_JUKEBOX, -EJUKEBOX },
1147 { -1, -EIO }
1da177e4
LT
1148};
1149
85828493
CL
1150/**
1151 * nfs_stat_to_errno - convert an NFS status code to a local errno
1152 * @status: NFS status code to convert
1153 *
1154 * Returns a local errno value, or -EIO if the NFS status code is
1155 * not recognized. This function is used jointly by NFSv2 and NFSv3.
1da177e4 1156 */
85828493 1157int nfs_stat_to_errno(enum nfs_stat status)
1da177e4
LT
1158{
1159 int i;
1160
1161 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
85828493 1162 if (nfs_errtbl[i].stat == (int)status)
1da177e4
LT
1163 return nfs_errtbl[i].errno;
1164 }
85828493 1165 dprintk("NFS: Unrecognized nfs status value: %u\n", status);
1da177e4
LT
1166 return nfs_errtbl[i].errno;
1167}
1168
1da177e4
LT
1169#define PROC(proc, argtype, restype, timer) \
1170[NFSPROC_##proc] = { \
1171 .p_proc = NFSPROC_##proc, \
25a0866c 1172 .p_encode = (kxdrproc_t)nfs2_xdr_enc_##argtype, \
f796f8b3 1173 .p_decode = (kxdrproc_t)nfs2_xdr_dec_##restype, \
2bea90d4
CL
1174 .p_arglen = NFS_##argtype##_sz, \
1175 .p_replen = NFS_##restype##_sz, \
cc0175c1
CL
1176 .p_timer = timer, \
1177 .p_statidx = NFSPROC_##proc, \
1178 .p_name = #proc, \
1da177e4
LT
1179 }
1180struct rpc_procinfo nfs_procedures[] = {
1181 PROC(GETATTR, fhandle, attrstat, 1),
1182 PROC(SETATTR, sattrargs, attrstat, 0),
1183 PROC(LOOKUP, diropargs, diropres, 2),
1184 PROC(READLINK, readlinkargs, readlinkres, 3),
1185 PROC(READ, readargs, readres, 3),
1186 PROC(WRITE, writeargs, writeres, 4),
1187 PROC(CREATE, createargs, diropres, 0),
4fdc17b2 1188 PROC(REMOVE, removeargs, stat, 0),
1da177e4
LT
1189 PROC(RENAME, renameargs, stat, 0),
1190 PROC(LINK, linkargs, stat, 0),
1191 PROC(SYMLINK, symlinkargs, stat, 0),
1192 PROC(MKDIR, createargs, diropres, 0),
1193 PROC(RMDIR, diropargs, stat, 0),
1194 PROC(READDIR, readdirargs, readdirres, 3),
1195 PROC(STATFS, fhandle, statfsres, 0),
1196};
1197
1198struct rpc_version nfs_version2 = {
1199 .number = 2,
e8c96f8c 1200 .nrprocs = ARRAY_SIZE(nfs_procedures),
1da177e4
LT
1201 .procs = nfs_procedures
1202};