blob: 06b9df49f7f7773fa62ad1b7215b2ffcdfee852a [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
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>
Linus Torvalds1da177e2005-04-16 15:20:36 -070015#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>
Trond Myklebust816724e2006-06-24 08:41:41 -040024#include "internal.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070025
26#define NFSDBG_FACILITY NFSDBG_XDR
Linus Torvalds1da177e2005-04-16 15:20:36 -070027
Linus Torvalds1da177e2005-04-16 15:20:36 -070028/* 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)
Trond Myklebust4fdc17b2007-07-14 15:39:57 -040044#define NFS_removeargs_sz (NFS_fhandle_sz+NFS_filename_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070045#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)
Chuck Lever94a6d752006-08-22 20:06:23 -040052#define NFS_symlinkargs_sz (NFS_diropargs_sz+1+NFS_sattr_sz)
Linus Torvalds1da177e2005-04-16 15:20:36 -070053#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
Bryan Schumaker5e7e5a02012-05-10 16:47:18 -040064static int nfs_stat_to_errno(enum nfs_stat);
Chuck Lever25a08662010-12-14 14:54:30 +000065
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
Chuck Leverf796f8b2010-12-14 14:55:10 +000081/*
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
Chuck Lever25a08662010-12-14 14:54:30 +000091
Linus Torvalds1da177e2005-04-16 15:20:36 -070092/*
Chuck Lever25a08662010-12-14 14:54:30 +000093 * 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
103/*
Chuck Leverf796f8b2010-12-14 14:55:10 +0000104 * typedef opaque nfsdata<>;
105 */
106static int decode_nfsdata(struct xdr_stream *xdr, struct nfs_readres *result)
107{
108 u32 recvd, count;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000109 __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);
Trond Myklebust64bd5772012-06-20 22:35:05 -0400115 recvd = xdr_read_pages(xdr, count);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000116 if (unlikely(count > recvd))
117 goto out_cheating;
118out:
Chuck Leverf796f8b2010-12-14 14:55:10 +0000119 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
168/*
Chuck Lever5f96e5e2010-12-14 14:55:30 +0000169 * 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
189/*
Chuck Lever25a08662010-12-14 14:54:30 +0000190 * 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
Chuck Lever25a08662010-12-14 14:54:30 +0000198 p = xdr_reserve_space(xdr, NFS2_FHSIZE);
199 memcpy(p, fh->data, NFS2_FHSIZE);
200}
201
Chuck Leverf796f8b2010-12-14 14:55:10 +0000202static 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
Chuck Lever25a08662010-12-14 14:54:30 +0000217/*
Chuck Lever282ac2a2010-12-14 14:54:50 +0000218 * 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
Chuck Lever5f96e5e2010-12-14 14:55:30 +0000250static __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
Chuck Lever282ac2a2010-12-14 14:54:50 +0000257/*
Chuck Leverf796f8b2010-12-14 14:55:10 +0000258 * 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{
Chuck Lever5f96e5e2010-12-14 14:55:30 +0000280 u32 rdev, type;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000281 __be32 *p;
282
283 p = xdr_inline_decode(xdr, NFS_fattr_sz << 2);
284 if (unlikely(p == NULL))
285 goto out_overflow;
Chuck Lever5f96e5e2010-12-14 14:55:30 +0000286
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++);
293 fattr->uid = be32_to_cpup(p++);
294 fattr->gid = be32_to_cpup(p++);
295 fattr->size = be32_to_cpup(p++);
296 fattr->du.nfs2.blocksize = be32_to_cpup(p++);
297
298 rdev = be32_to_cpup(p++);
299 fattr->rdev = new_decode_dev(rdev);
300 if (type == (u32)NFCHR && rdev == (u32)NFS2_FIFO_DEV) {
301 fattr->mode = (fattr->mode & ~S_IFMT) | S_IFIFO;
302 fattr->rdev = 0;
303 }
304
305 fattr->du.nfs2.blocks = be32_to_cpup(p++);
306 fattr->fsid.major = be32_to_cpup(p++);
307 fattr->fsid.minor = 0;
308 fattr->fileid = be32_to_cpup(p++);
309
310 p = xdr_decode_time(p, &fattr->atime);
311 p = xdr_decode_time(p, &fattr->mtime);
312 xdr_decode_time(p, &fattr->ctime);
Trond Myklebust3a1556e2012-04-27 13:48:18 -0400313 fattr->change_attr = nfs_timespec_to_change_attr(&fattr->ctime);
314
Chuck Leverf796f8b2010-12-14 14:55:10 +0000315 return 0;
316out_overflow:
317 print_overflow_msg(__func__, xdr);
318 return -EIO;
319}
320
321/*
Chuck Lever25a08662010-12-14 14:54:30 +0000322 * 2.3.6. sattr
323 *
324 * struct sattr {
325 * unsigned int mode;
326 * unsigned int uid;
327 * unsigned int gid;
328 * unsigned int size;
329 * timeval atime;
330 * timeval mtime;
331 * };
332 */
333
334#define NFS2_SATTR_NOT_SET (0xffffffff)
335
336static __be32 *xdr_time_not_set(__be32 *p)
337{
338 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
339 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
340 return p;
341}
342
343static void encode_sattr(struct xdr_stream *xdr, const struct iattr *attr)
344{
345 __be32 *p;
346
347 p = xdr_reserve_space(xdr, NFS_sattr_sz << 2);
348
349 if (attr->ia_valid & ATTR_MODE)
350 *p++ = cpu_to_be32(attr->ia_mode);
351 else
352 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
353 if (attr->ia_valid & ATTR_UID)
354 *p++ = cpu_to_be32(attr->ia_uid);
355 else
356 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
357 if (attr->ia_valid & ATTR_GID)
358 *p++ = cpu_to_be32(attr->ia_gid);
359 else
360 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
361 if (attr->ia_valid & ATTR_SIZE)
362 *p++ = cpu_to_be32((u32)attr->ia_size);
363 else
364 *p++ = cpu_to_be32(NFS2_SATTR_NOT_SET);
365
366 if (attr->ia_valid & ATTR_ATIME_SET)
367 p = xdr_encode_time(p, &attr->ia_atime);
368 else if (attr->ia_valid & ATTR_ATIME)
369 p = xdr_encode_current_server_time(p, &attr->ia_atime);
370 else
371 p = xdr_time_not_set(p);
372 if (attr->ia_valid & ATTR_MTIME_SET)
373 xdr_encode_time(p, &attr->ia_mtime);
374 else if (attr->ia_valid & ATTR_MTIME)
375 xdr_encode_current_server_time(p, &attr->ia_mtime);
376 else
377 xdr_time_not_set(p);
378}
379
380/*
381 * 2.3.7. filename
382 *
383 * typedef string filename<MAXNAMLEN>;
384 */
385static void encode_filename(struct xdr_stream *xdr,
386 const char *name, u32 length)
387{
388 __be32 *p;
389
Trond Myklebust7fc38842012-10-15 11:51:21 -0400390 WARN_ON_ONCE(length > NFS2_MAXNAMLEN);
Chuck Lever25a08662010-12-14 14:54:30 +0000391 p = xdr_reserve_space(xdr, 4 + length);
392 xdr_encode_opaque(p, name, length);
393}
394
Chuck Leverf796f8b2010-12-14 14:55:10 +0000395static int decode_filename_inline(struct xdr_stream *xdr,
396 const char **name, u32 *length)
397{
398 __be32 *p;
399 u32 count;
400
401 p = xdr_inline_decode(xdr, 4);
402 if (unlikely(p == NULL))
403 goto out_overflow;
404 count = be32_to_cpup(p);
405 if (count > NFS3_MAXNAMLEN)
406 goto out_nametoolong;
407 p = xdr_inline_decode(xdr, count);
408 if (unlikely(p == NULL))
409 goto out_overflow;
410 *name = (const char *)p;
411 *length = count;
412 return 0;
413out_nametoolong:
414 dprintk("NFS: returned filename too long: %u\n", count);
415 return -ENAMETOOLONG;
416out_overflow:
417 print_overflow_msg(__func__, xdr);
418 return -EIO;
419}
420
Chuck Lever25a08662010-12-14 14:54:30 +0000421/*
422 * 2.3.8. path
423 *
424 * typedef string path<MAXPATHLEN>;
425 */
426static void encode_path(struct xdr_stream *xdr, struct page **pages, u32 length)
427{
428 __be32 *p;
429
Chuck Lever25a08662010-12-14 14:54:30 +0000430 p = xdr_reserve_space(xdr, 4);
431 *p = cpu_to_be32(length);
432 xdr_write_pages(xdr, pages, 0, length);
433}
434
Chuck Leverf796f8b2010-12-14 14:55:10 +0000435static int decode_path(struct xdr_stream *xdr)
436{
437 u32 length, recvd;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000438 __be32 *p;
439
440 p = xdr_inline_decode(xdr, 4);
441 if (unlikely(p == NULL))
442 goto out_overflow;
443 length = be32_to_cpup(p);
444 if (unlikely(length >= xdr->buf->page_len || length > NFS_MAXPATHLEN))
445 goto out_size;
Trond Myklebust64bd5772012-06-20 22:35:05 -0400446 recvd = xdr_read_pages(xdr, length);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000447 if (unlikely(length > recvd))
448 goto out_cheating;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000449 xdr_terminate_string(xdr->buf, length);
450 return 0;
451out_size:
452 dprintk("NFS: returned pathname too long: %u\n", length);
453 return -ENAMETOOLONG;
454out_cheating:
455 dprintk("NFS: server cheating in pathname result: "
456 "length %u > received %u\n", length, recvd);
457 return -EIO;
458out_overflow:
459 print_overflow_msg(__func__, xdr);
460 return -EIO;
461}
462
463/*
464 * 2.3.9. attrstat
465 *
466 * union attrstat switch (stat status) {
467 * case NFS_OK:
468 * fattr attributes;
469 * default:
470 * void;
471 * };
472 */
473static int decode_attrstat(struct xdr_stream *xdr, struct nfs_fattr *result)
474{
475 enum nfs_stat status;
476 int error;
477
478 error = decode_stat(xdr, &status);
479 if (unlikely(error))
480 goto out;
481 if (status != NFS_OK)
482 goto out_default;
483 error = decode_fattr(xdr, result);
484out:
485 return error;
486out_default:
487 return nfs_stat_to_errno(status);
488}
489
Chuck Lever25a08662010-12-14 14:54:30 +0000490/*
491 * 2.3.10. diropargs
492 *
493 * struct diropargs {
494 * fhandle dir;
495 * filename name;
496 * };
497 */
498static void encode_diropargs(struct xdr_stream *xdr, const struct nfs_fh *fh,
499 const char *name, u32 length)
500{
501 encode_fhandle(xdr, fh);
502 encode_filename(xdr, name, length);
503}
504
Chuck Leverf796f8b2010-12-14 14:55:10 +0000505/*
506 * 2.3.11. diropres
507 *
508 * union diropres switch (stat status) {
509 * case NFS_OK:
510 * struct {
511 * fhandle file;
512 * fattr attributes;
513 * } diropok;
514 * default:
515 * void;
516 * };
517 */
518static int decode_diropok(struct xdr_stream *xdr, struct nfs_diropok *result)
519{
520 int error;
521
522 error = decode_fhandle(xdr, result->fh);
523 if (unlikely(error))
524 goto out;
525 error = decode_fattr(xdr, result->fattr);
526out:
527 return error;
528}
529
530static int decode_diropres(struct xdr_stream *xdr, struct nfs_diropok *result)
531{
532 enum nfs_stat status;
533 int error;
534
535 error = decode_stat(xdr, &status);
536 if (unlikely(error))
537 goto out;
538 if (status != NFS_OK)
539 goto out_default;
540 error = decode_diropok(xdr, result);
541out:
542 return error;
543out_default:
544 return nfs_stat_to_errno(status);
545}
546
Chuck Lever25a08662010-12-14 14:54:30 +0000547
548/*
Chuck Lever2d70f532010-12-14 14:54:40 +0000549 * NFSv2 XDR encode functions
550 *
551 * NFSv2 argument types are defined in section 2.2 of RFC 1094:
552 * "NFS: Network File System Protocol Specification".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700553 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700554
Chuck Lever9f06c712010-12-14 14:59:18 +0000555static void nfs2_xdr_enc_fhandle(struct rpc_rqst *req,
556 struct xdr_stream *xdr,
557 const struct nfs_fh *fh)
Chuck Lever25a08662010-12-14 14:54:30 +0000558{
Chuck Lever9f06c712010-12-14 14:59:18 +0000559 encode_fhandle(xdr, fh);
Chuck Lever25a08662010-12-14 14:54:30 +0000560}
561
Linus Torvalds1da177e2005-04-16 15:20:36 -0700562/*
Chuck Lever25a08662010-12-14 14:54:30 +0000563 * 2.2.3. sattrargs
564 *
565 * struct sattrargs {
566 * fhandle file;
567 * sattr attributes;
568 * };
569 */
Chuck Lever9f06c712010-12-14 14:59:18 +0000570static void nfs2_xdr_enc_sattrargs(struct rpc_rqst *req,
571 struct xdr_stream *xdr,
572 const struct nfs_sattrargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000573{
Chuck Lever9f06c712010-12-14 14:59:18 +0000574 encode_fhandle(xdr, args->fh);
575 encode_sattr(xdr, args->sattr);
Chuck Lever25a08662010-12-14 14:54:30 +0000576}
577
Chuck Lever9f06c712010-12-14 14:59:18 +0000578static void nfs2_xdr_enc_diropargs(struct rpc_rqst *req,
579 struct xdr_stream *xdr,
580 const struct nfs_diropargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000581{
Chuck Lever9f06c712010-12-14 14:59:18 +0000582 encode_diropargs(xdr, args->fh, args->name, args->len);
Chuck Lever25a08662010-12-14 14:54:30 +0000583}
584
Chuck Lever9f06c712010-12-14 14:59:18 +0000585static void nfs2_xdr_enc_readlinkargs(struct rpc_rqst *req,
586 struct xdr_stream *xdr,
587 const struct nfs_readlinkargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000588{
Chuck Lever9f06c712010-12-14 14:59:18 +0000589 encode_fhandle(xdr, args->fh);
Chuck Lever25a08662010-12-14 14:54:30 +0000590 prepare_reply_buffer(req, args->pages, args->pgbase,
591 args->pglen, NFS_readlinkres_sz);
Chuck Lever25a08662010-12-14 14:54:30 +0000592}
593
Trond Myklebust4fdc17b2007-07-14 15:39:57 -0400594/*
Chuck Lever25a08662010-12-14 14:54:30 +0000595 * 2.2.7. readargs
596 *
597 * struct readargs {
598 * fhandle file;
599 * unsigned offset;
600 * unsigned count;
601 * unsigned totalcount;
602 * };
603 */
604static void encode_readargs(struct xdr_stream *xdr,
605 const struct nfs_readargs *args)
606{
607 u32 offset = args->offset;
608 u32 count = args->count;
609 __be32 *p;
610
611 encode_fhandle(xdr, args->fh);
612
613 p = xdr_reserve_space(xdr, 4 + 4 + 4);
614 *p++ = cpu_to_be32(offset);
615 *p++ = cpu_to_be32(count);
616 *p = cpu_to_be32(count);
617}
618
Chuck Lever9f06c712010-12-14 14:59:18 +0000619static void nfs2_xdr_enc_readargs(struct rpc_rqst *req,
620 struct xdr_stream *xdr,
621 const struct nfs_readargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000622{
Chuck Lever9f06c712010-12-14 14:59:18 +0000623 encode_readargs(xdr, args);
Chuck Lever25a08662010-12-14 14:54:30 +0000624 prepare_reply_buffer(req, args->pages, args->pgbase,
625 args->count, NFS_readres_sz);
626 req->rq_rcv_buf.flags |= XDRBUF_READ;
Chuck Lever25a08662010-12-14 14:54:30 +0000627}
628
629/*
Chuck Lever25a08662010-12-14 14:54:30 +0000630 * 2.2.9. writeargs
631 *
632 * struct writeargs {
633 * fhandle file;
634 * unsigned beginoffset;
635 * unsigned offset;
636 * unsigned totalcount;
637 * nfsdata data;
638 * };
639 */
640static void encode_writeargs(struct xdr_stream *xdr,
641 const struct nfs_writeargs *args)
642{
643 u32 offset = args->offset;
644 u32 count = args->count;
645 __be32 *p;
646
647 encode_fhandle(xdr, args->fh);
648
649 p = xdr_reserve_space(xdr, 4 + 4 + 4 + 4);
650 *p++ = cpu_to_be32(offset);
651 *p++ = cpu_to_be32(offset);
652 *p++ = cpu_to_be32(count);
653
654 /* nfsdata */
655 *p = cpu_to_be32(count);
656 xdr_write_pages(xdr, args->pages, args->pgbase, count);
657}
658
Chuck Lever9f06c712010-12-14 14:59:18 +0000659static void nfs2_xdr_enc_writeargs(struct rpc_rqst *req,
660 struct xdr_stream *xdr,
661 const struct nfs_writeargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000662{
Chuck Lever9f06c712010-12-14 14:59:18 +0000663 encode_writeargs(xdr, args);
664 xdr->buf->flags |= XDRBUF_WRITE;
Chuck Lever25a08662010-12-14 14:54:30 +0000665}
666
667/*
Chuck Lever25a08662010-12-14 14:54:30 +0000668 * 2.2.10. createargs
669 *
670 * struct createargs {
671 * diropargs where;
672 * sattr attributes;
673 * };
674 */
Chuck Lever9f06c712010-12-14 14:59:18 +0000675static void nfs2_xdr_enc_createargs(struct rpc_rqst *req,
676 struct xdr_stream *xdr,
677 const struct nfs_createargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000678{
Chuck Lever9f06c712010-12-14 14:59:18 +0000679 encode_diropargs(xdr, args->fh, args->name, args->len);
680 encode_sattr(xdr, args->sattr);
Chuck Lever25a08662010-12-14 14:54:30 +0000681}
682
Chuck Lever9f06c712010-12-14 14:59:18 +0000683static void nfs2_xdr_enc_removeargs(struct rpc_rqst *req,
684 struct xdr_stream *xdr,
685 const struct nfs_removeargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000686{
Chuck Lever9f06c712010-12-14 14:59:18 +0000687 encode_diropargs(xdr, args->fh, args->name.name, args->name.len);
Chuck Lever25a08662010-12-14 14:54:30 +0000688}
689
690/*
Chuck Lever25a08662010-12-14 14:54:30 +0000691 * 2.2.12. renameargs
692 *
693 * struct renameargs {
694 * diropargs from;
695 * diropargs to;
696 * };
697 */
Chuck Lever9f06c712010-12-14 14:59:18 +0000698static void nfs2_xdr_enc_renameargs(struct rpc_rqst *req,
699 struct xdr_stream *xdr,
700 const struct nfs_renameargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000701{
702 const struct qstr *old = args->old_name;
703 const struct qstr *new = args->new_name;
Chuck Lever25a08662010-12-14 14:54:30 +0000704
Chuck Lever9f06c712010-12-14 14:59:18 +0000705 encode_diropargs(xdr, args->old_dir, old->name, old->len);
706 encode_diropargs(xdr, args->new_dir, new->name, new->len);
Chuck Lever25a08662010-12-14 14:54:30 +0000707}
708
709/*
Chuck Lever25a08662010-12-14 14:54:30 +0000710 * 2.2.13. linkargs
711 *
712 * struct linkargs {
713 * fhandle from;
714 * diropargs to;
715 * };
716 */
Chuck Lever9f06c712010-12-14 14:59:18 +0000717static void nfs2_xdr_enc_linkargs(struct rpc_rqst *req,
718 struct xdr_stream *xdr,
719 const struct nfs_linkargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000720{
Chuck Lever9f06c712010-12-14 14:59:18 +0000721 encode_fhandle(xdr, args->fromfh);
722 encode_diropargs(xdr, args->tofh, args->toname, args->tolen);
Chuck Lever25a08662010-12-14 14:54:30 +0000723}
724
725/*
Chuck Lever25a08662010-12-14 14:54:30 +0000726 * 2.2.14. symlinkargs
727 *
728 * struct symlinkargs {
729 * diropargs from;
730 * path to;
731 * sattr attributes;
732 * };
733 */
Chuck Lever9f06c712010-12-14 14:59:18 +0000734static void nfs2_xdr_enc_symlinkargs(struct rpc_rqst *req,
735 struct xdr_stream *xdr,
736 const struct nfs_symlinkargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000737{
Chuck Lever9f06c712010-12-14 14:59:18 +0000738 encode_diropargs(xdr, args->fromfh, args->fromname, args->fromlen);
739 encode_path(xdr, args->pages, args->pathlen);
740 encode_sattr(xdr, args->sattr);
Chuck Lever25a08662010-12-14 14:54:30 +0000741}
742
743/*
Chuck Lever25a08662010-12-14 14:54:30 +0000744 * 2.2.17. readdirargs
745 *
746 * struct readdirargs {
747 * fhandle dir;
748 * nfscookie cookie;
749 * unsigned count;
750 * };
751 */
752static void encode_readdirargs(struct xdr_stream *xdr,
753 const struct nfs_readdirargs *args)
754{
755 __be32 *p;
756
757 encode_fhandle(xdr, args->fh);
758
759 p = xdr_reserve_space(xdr, 4 + 4);
760 *p++ = cpu_to_be32(args->cookie);
761 *p = cpu_to_be32(args->count);
762}
763
Chuck Lever9f06c712010-12-14 14:59:18 +0000764static void nfs2_xdr_enc_readdirargs(struct rpc_rqst *req,
765 struct xdr_stream *xdr,
766 const struct nfs_readdirargs *args)
Chuck Lever25a08662010-12-14 14:54:30 +0000767{
Chuck Lever9f06c712010-12-14 14:59:18 +0000768 encode_readdirargs(xdr, args);
Chuck Lever25a08662010-12-14 14:54:30 +0000769 prepare_reply_buffer(req, args->pages, 0,
770 args->count, NFS_readdirres_sz);
Chuck Lever25a08662010-12-14 14:54:30 +0000771}
772
773/*
Chuck Lever661ad422010-12-14 14:55:20 +0000774 * NFSv2 XDR decode functions
775 *
776 * NFSv2 result types are defined in section 2.2 of RFC 1094:
777 * "NFS: Network File System Protocol Specification".
Linus Torvalds1da177e2005-04-16 15:20:36 -0700778 */
Linus Torvalds1da177e2005-04-16 15:20:36 -0700779
Chuck Leverbf269552010-12-14 14:59:29 +0000780static int nfs2_xdr_dec_stat(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +0000781 void *__unused)
782{
Chuck Leverf796f8b2010-12-14 14:55:10 +0000783 enum nfs_stat status;
784 int error;
785
Chuck Leverbf269552010-12-14 14:59:29 +0000786 error = decode_stat(xdr, &status);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000787 if (unlikely(error))
788 goto out;
789 if (status != NFS_OK)
790 goto out_default;
791out:
792 return error;
793out_default:
794 return nfs_stat_to_errno(status);
795}
796
Chuck Leverbf269552010-12-14 14:59:29 +0000797static int nfs2_xdr_dec_attrstat(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +0000798 struct nfs_fattr *result)
799{
Chuck Leverbf269552010-12-14 14:59:29 +0000800 return decode_attrstat(xdr, result);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000801}
802
Chuck Leverbf269552010-12-14 14:59:29 +0000803static int nfs2_xdr_dec_diropres(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +0000804 struct nfs_diropok *result)
805{
Chuck Leverbf269552010-12-14 14:59:29 +0000806 return decode_diropres(xdr, result);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000807}
808
Linus Torvalds1da177e2005-04-16 15:20:36 -0700809/*
Chuck Leverf796f8b2010-12-14 14:55:10 +0000810 * 2.2.6. readlinkres
811 *
812 * union readlinkres switch (stat status) {
813 * case NFS_OK:
814 * path data;
815 * default:
816 * void;
817 * };
818 */
Chuck Leverbf269552010-12-14 14:59:29 +0000819static int nfs2_xdr_dec_readlinkres(struct rpc_rqst *req,
820 struct xdr_stream *xdr, void *__unused)
Chuck Leverf796f8b2010-12-14 14:55:10 +0000821{
Chuck Leverf796f8b2010-12-14 14:55:10 +0000822 enum nfs_stat status;
823 int error;
824
Chuck Leverbf269552010-12-14 14:59:29 +0000825 error = decode_stat(xdr, &status);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000826 if (unlikely(error))
827 goto out;
828 if (status != NFS_OK)
829 goto out_default;
Chuck Leverbf269552010-12-14 14:59:29 +0000830 error = decode_path(xdr);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000831out:
832 return error;
833out_default:
834 return nfs_stat_to_errno(status);
835}
836
837/*
838 * 2.2.7. readres
839 *
840 * union readres switch (stat status) {
841 * case NFS_OK:
842 * fattr attributes;
843 * nfsdata data;
844 * default:
845 * void;
846 * };
847 */
Chuck Leverbf269552010-12-14 14:59:29 +0000848static int nfs2_xdr_dec_readres(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +0000849 struct nfs_readres *result)
850{
Chuck Leverf796f8b2010-12-14 14:55:10 +0000851 enum nfs_stat status;
852 int error;
853
Chuck Leverbf269552010-12-14 14:59:29 +0000854 error = decode_stat(xdr, &status);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000855 if (unlikely(error))
856 goto out;
857 if (status != NFS_OK)
858 goto out_default;
Chuck Leverbf269552010-12-14 14:59:29 +0000859 error = decode_fattr(xdr, result->fattr);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000860 if (unlikely(error))
861 goto out;
Chuck Leverbf269552010-12-14 14:59:29 +0000862 error = decode_nfsdata(xdr, result);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000863out:
864 return error;
865out_default:
866 return nfs_stat_to_errno(status);
867}
868
Chuck Leverbf269552010-12-14 14:59:29 +0000869static int nfs2_xdr_dec_writeres(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +0000870 struct nfs_writeres *result)
871{
Chuck Leverf796f8b2010-12-14 14:55:10 +0000872 /* All NFSv2 writes are "file sync" writes */
873 result->verf->committed = NFS_FILE_SYNC;
Chuck Leverbf269552010-12-14 14:59:29 +0000874 return decode_attrstat(xdr, result->fattr);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000875}
876
877/**
878 * nfs2_decode_dirent - Decode a single NFSv2 directory entry stored in
879 * the local page cache.
880 * @xdr: XDR stream where entry resides
881 * @entry: buffer to fill in with entry data
Chuck Leverf796f8b2010-12-14 14:55:10 +0000882 * @plus: boolean indicating whether this should be a readdirplus entry
883 *
Chuck Lever573c4e12010-12-14 14:58:11 +0000884 * Returns zero if successful, otherwise a negative errno value is
885 * returned.
Chuck Leverf796f8b2010-12-14 14:55:10 +0000886 *
887 * This function is not invoked during READDIR reply decoding, but
888 * rather whenever an application invokes the getdents(2) system call
889 * on a directory already in our cache.
890 *
891 * 2.2.17. entry
892 *
893 * struct entry {
894 * unsigned fileid;
895 * filename name;
896 * nfscookie cookie;
897 * entry *nextentry;
898 * };
899 */
Chuck Lever573c4e12010-12-14 14:58:11 +0000900int nfs2_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
901 int plus)
Chuck Leverf796f8b2010-12-14 14:55:10 +0000902{
903 __be32 *p;
904 int error;
905
906 p = xdr_inline_decode(xdr, 4);
907 if (unlikely(p == NULL))
908 goto out_overflow;
909 if (*p++ == xdr_zero) {
910 p = xdr_inline_decode(xdr, 4);
911 if (unlikely(p == NULL))
912 goto out_overflow;
913 if (*p++ == xdr_zero)
Chuck Lever573c4e12010-12-14 14:58:11 +0000914 return -EAGAIN;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000915 entry->eof = 1;
Chuck Lever573c4e12010-12-14 14:58:11 +0000916 return -EBADCOOKIE;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000917 }
918
919 p = xdr_inline_decode(xdr, 4);
920 if (unlikely(p == NULL))
921 goto out_overflow;
922 entry->ino = be32_to_cpup(p);
923
924 error = decode_filename_inline(xdr, &entry->name, &entry->len);
925 if (unlikely(error))
Chuck Lever573c4e12010-12-14 14:58:11 +0000926 return error;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000927
928 /*
929 * The type (size and byte order) of nfscookie isn't defined in
930 * RFC 1094. This implementation assumes that it's an XDR uint32.
931 */
932 entry->prev_cookie = entry->cookie;
933 p = xdr_inline_decode(xdr, 4);
934 if (unlikely(p == NULL))
935 goto out_overflow;
936 entry->cookie = be32_to_cpup(p);
937
938 entry->d_type = DT_UNKNOWN;
939
Chuck Lever573c4e12010-12-14 14:58:11 +0000940 return 0;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000941
942out_overflow:
943 print_overflow_msg(__func__, xdr);
Chuck Lever573c4e12010-12-14 14:58:11 +0000944 return -EAGAIN;
Chuck Leverf796f8b2010-12-14 14:55:10 +0000945}
946
947/*
948 * 2.2.17. readdirres
949 *
950 * union readdirres switch (stat status) {
951 * case NFS_OK:
952 * struct {
953 * entry *entries;
954 * bool eof;
955 * } readdirok;
956 * default:
957 * void;
958 * };
959 *
960 * Read the directory contents into the page cache, but don't
961 * touch them. The actual decoding is done by nfs2_decode_dirent()
962 * during subsequent nfs_readdir() calls.
963 */
964static int decode_readdirok(struct xdr_stream *xdr)
965{
Trond Myklebust64bd5772012-06-20 22:35:05 -0400966 return xdr_read_pages(xdr, xdr->buf->page_len);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000967}
968
Chuck Leverbf269552010-12-14 14:59:29 +0000969static int nfs2_xdr_dec_readdirres(struct rpc_rqst *req,
970 struct xdr_stream *xdr, void *__unused)
Chuck Leverf796f8b2010-12-14 14:55:10 +0000971{
Chuck Leverf796f8b2010-12-14 14:55:10 +0000972 enum nfs_stat status;
973 int error;
974
Chuck Leverbf269552010-12-14 14:59:29 +0000975 error = decode_stat(xdr, &status);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000976 if (unlikely(error))
977 goto out;
978 if (status != NFS_OK)
979 goto out_default;
Chuck Leverbf269552010-12-14 14:59:29 +0000980 error = decode_readdirok(xdr);
Chuck Leverf796f8b2010-12-14 14:55:10 +0000981out:
982 return error;
983out_default:
984 return nfs_stat_to_errno(status);
985}
986
Linus Torvalds1da177e2005-04-16 15:20:36 -0700987/*
Chuck Leverf796f8b2010-12-14 14:55:10 +0000988 * 2.2.18. statfsres
989 *
990 * union statfsres (stat status) {
991 * case NFS_OK:
992 * struct {
993 * unsigned tsize;
994 * unsigned bsize;
995 * unsigned blocks;
996 * unsigned bfree;
997 * unsigned bavail;
998 * } info;
999 * default:
1000 * void;
1001 * };
1002 */
1003static int decode_info(struct xdr_stream *xdr, struct nfs2_fsstat *result)
1004{
1005 __be32 *p;
1006
1007 p = xdr_inline_decode(xdr, NFS_info_sz << 2);
1008 if (unlikely(p == NULL))
1009 goto out_overflow;
1010 result->tsize = be32_to_cpup(p++);
1011 result->bsize = be32_to_cpup(p++);
1012 result->blocks = be32_to_cpup(p++);
1013 result->bfree = be32_to_cpup(p++);
1014 result->bavail = be32_to_cpup(p);
1015 return 0;
1016out_overflow:
1017 print_overflow_msg(__func__, xdr);
1018 return -EIO;
1019}
1020
Chuck Leverbf269552010-12-14 14:59:29 +00001021static int nfs2_xdr_dec_statfsres(struct rpc_rqst *req, struct xdr_stream *xdr,
Chuck Leverf796f8b2010-12-14 14:55:10 +00001022 struct nfs2_fsstat *result)
1023{
Chuck Leverf796f8b2010-12-14 14:55:10 +00001024 enum nfs_stat status;
1025 int error;
1026
Chuck Leverbf269552010-12-14 14:59:29 +00001027 error = decode_stat(xdr, &status);
Chuck Leverf796f8b2010-12-14 14:55:10 +00001028 if (unlikely(error))
1029 goto out;
1030 if (status != NFS_OK)
1031 goto out_default;
Chuck Leverbf269552010-12-14 14:59:29 +00001032 error = decode_info(xdr, result);
Chuck Leverf796f8b2010-12-14 14:55:10 +00001033out:
1034 return error;
1035out_default:
1036 return nfs_stat_to_errno(status);
1037}
1038
1039
1040/*
Linus Torvalds1da177e2005-04-16 15:20:36 -07001041 * We need to translate between nfs status return values and
1042 * the local errno values which may not be the same.
1043 */
Chuck Lever85828492010-12-14 14:55:00 +00001044static const struct {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001045 int stat;
1046 int errno;
1047} nfs_errtbl[] = {
1048 { NFS_OK, 0 },
Benny Halevy856dff32008-03-31 17:39:06 +03001049 { NFSERR_PERM, -EPERM },
1050 { NFSERR_NOENT, -ENOENT },
1051 { NFSERR_IO, -errno_NFSERR_IO},
1052 { NFSERR_NXIO, -ENXIO },
1053/* { NFSERR_EAGAIN, -EAGAIN }, */
1054 { NFSERR_ACCES, -EACCES },
1055 { NFSERR_EXIST, -EEXIST },
1056 { NFSERR_XDEV, -EXDEV },
1057 { NFSERR_NODEV, -ENODEV },
1058 { NFSERR_NOTDIR, -ENOTDIR },
1059 { NFSERR_ISDIR, -EISDIR },
1060 { NFSERR_INVAL, -EINVAL },
1061 { NFSERR_FBIG, -EFBIG },
1062 { NFSERR_NOSPC, -ENOSPC },
1063 { NFSERR_ROFS, -EROFS },
1064 { NFSERR_MLINK, -EMLINK },
1065 { NFSERR_NAMETOOLONG, -ENAMETOOLONG },
1066 { NFSERR_NOTEMPTY, -ENOTEMPTY },
1067 { NFSERR_DQUOT, -EDQUOT },
1068 { NFSERR_STALE, -ESTALE },
1069 { NFSERR_REMOTE, -EREMOTE },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001070#ifdef EWFLUSH
Benny Halevy856dff32008-03-31 17:39:06 +03001071 { NFSERR_WFLUSH, -EWFLUSH },
Linus Torvalds1da177e2005-04-16 15:20:36 -07001072#endif
Benny Halevy856dff32008-03-31 17:39:06 +03001073 { NFSERR_BADHANDLE, -EBADHANDLE },
1074 { NFSERR_NOT_SYNC, -ENOTSYNC },
1075 { NFSERR_BAD_COOKIE, -EBADCOOKIE },
1076 { NFSERR_NOTSUPP, -ENOTSUPP },
1077 { NFSERR_TOOSMALL, -ETOOSMALL },
Trond Myklebustfdcb4572010-02-08 09:32:40 -05001078 { NFSERR_SERVERFAULT, -EREMOTEIO },
Benny Halevy856dff32008-03-31 17:39:06 +03001079 { NFSERR_BADTYPE, -EBADTYPE },
1080 { NFSERR_JUKEBOX, -EJUKEBOX },
1081 { -1, -EIO }
Linus Torvalds1da177e2005-04-16 15:20:36 -07001082};
1083
Chuck Lever85828492010-12-14 14:55:00 +00001084/**
1085 * nfs_stat_to_errno - convert an NFS status code to a local errno
1086 * @status: NFS status code to convert
1087 *
1088 * Returns a local errno value, or -EIO if the NFS status code is
1089 * not recognized. This function is used jointly by NFSv2 and NFSv3.
Linus Torvalds1da177e2005-04-16 15:20:36 -07001090 */
Bryan Schumaker5e7e5a02012-05-10 16:47:18 -04001091static int nfs_stat_to_errno(enum nfs_stat status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001092{
1093 int i;
1094
1095 for (i = 0; nfs_errtbl[i].stat != -1; i++) {
Chuck Lever85828492010-12-14 14:55:00 +00001096 if (nfs_errtbl[i].stat == (int)status)
Linus Torvalds1da177e2005-04-16 15:20:36 -07001097 return nfs_errtbl[i].errno;
1098 }
Chuck Lever85828492010-12-14 14:55:00 +00001099 dprintk("NFS: Unrecognized nfs status value: %u\n", status);
Linus Torvalds1da177e2005-04-16 15:20:36 -07001100 return nfs_errtbl[i].errno;
1101}
1102
Linus Torvalds1da177e2005-04-16 15:20:36 -07001103#define PROC(proc, argtype, restype, timer) \
1104[NFSPROC_##proc] = { \
1105 .p_proc = NFSPROC_##proc, \
Chuck Lever9f06c712010-12-14 14:59:18 +00001106 .p_encode = (kxdreproc_t)nfs2_xdr_enc_##argtype, \
Chuck Leverbf269552010-12-14 14:59:29 +00001107 .p_decode = (kxdrdproc_t)nfs2_xdr_dec_##restype, \
Chuck Lever2bea90d2007-03-29 16:47:53 -04001108 .p_arglen = NFS_##argtype##_sz, \
1109 .p_replen = NFS_##restype##_sz, \
Chuck Levercc0175c2006-03-20 13:44:22 -05001110 .p_timer = timer, \
1111 .p_statidx = NFSPROC_##proc, \
1112 .p_name = #proc, \
Linus Torvalds1da177e2005-04-16 15:20:36 -07001113 }
1114struct rpc_procinfo nfs_procedures[] = {
Chuck Lever7d93bd712010-12-14 14:57:42 +00001115 PROC(GETATTR, fhandle, attrstat, 1),
1116 PROC(SETATTR, sattrargs, attrstat, 0),
1117 PROC(LOOKUP, diropargs, diropres, 2),
1118 PROC(READLINK, readlinkargs, readlinkres, 3),
1119 PROC(READ, readargs, readres, 3),
1120 PROC(WRITE, writeargs, writeres, 4),
1121 PROC(CREATE, createargs, diropres, 0),
1122 PROC(REMOVE, removeargs, stat, 0),
1123 PROC(RENAME, renameargs, stat, 0),
1124 PROC(LINK, linkargs, stat, 0),
1125 PROC(SYMLINK, symlinkargs, stat, 0),
1126 PROC(MKDIR, createargs, diropres, 0),
1127 PROC(RMDIR, diropargs, stat, 0),
1128 PROC(READDIR, readdirargs, readdirres, 3),
1129 PROC(STATFS, fhandle, statfsres, 0),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001130};
1131
Trond Myklebusta613fa12012-01-20 13:53:56 -05001132const struct rpc_version nfs_version2 = {
Linus Torvalds1da177e2005-04-16 15:20:36 -07001133 .number = 2,
Tobias Klausere8c96f82006-03-24 03:15:34 -08001134 .nrprocs = ARRAY_SIZE(nfs_procedures),
Linus Torvalds1da177e2005-04-16 15:20:36 -07001135 .procs = nfs_procedures
1136};