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