]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - fs/nfs/nfs3xdr.c
NFS: Switch in new NFSv3 decoder functions
[mirror_ubuntu-artful-kernel.git] / fs / nfs / nfs3xdr.c
CommitLineData
1da177e4
LT
1/*
2 * linux/fs/nfs/nfs3xdr.c
3 *
4 * XDR functions to encode/decode NFSv3 RPC arguments and results.
5 *
6 * Copyright (C) 1996, 1997 Olaf Kirch
7 */
8
9#include <linux/param.h>
10#include <linux/time.h>
11#include <linux/mm.h>
1da177e4
LT
12#include <linux/errno.h>
13#include <linux/string.h>
14#include <linux/in.h>
15#include <linux/pagemap.h>
16#include <linux/proc_fs.h>
17#include <linux/kdev_t.h>
18#include <linux/sunrpc/clnt.h>
19#include <linux/nfs.h>
20#include <linux/nfs3.h>
21#include <linux/nfs_fs.h>
b7fa0554 22#include <linux/nfsacl.h>
f7b422b1 23#include "internal.h"
1da177e4
LT
24
25#define NFSDBG_FACILITY NFSDBG_XDR
26
27/* Mapping from NFS error code to "errno" error code. */
28#define errno_NFSERR_IO EIO
29
1da177e4
LT
30/*
31 * Declare the space requirements for NFS arguments and replies as
32 * number of 32bit-words
33 */
34#define NFS3_fhandle_sz (1+16)
35#define NFS3_fh_sz (NFS3_fhandle_sz) /* shorthand */
36#define NFS3_sattr_sz (15)
37#define NFS3_filename_sz (1+(NFS3_MAXNAMLEN>>2))
38#define NFS3_path_sz (1+(NFS3_MAXPATHLEN>>2))
39#define NFS3_fattr_sz (21)
d9c407b1 40#define NFS3_cookieverf_sz (NFS3_COOKIEVERFSIZE>>2)
f5fc3c50 41#define NFS3_wcc_attr_sz (6)
1da177e4
LT
42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
f5fc3c50 44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
1da177e4 45#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
ad96b5b5
CL
46
47#define NFS3_getattrargs_sz (NFS3_fh_sz)
48#define NFS3_setattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
49#define NFS3_lookupargs_sz (NFS3_fh_sz+NFS3_filename_sz)
1da177e4
LT
50#define NFS3_accessargs_sz (NFS3_fh_sz+1)
51#define NFS3_readlinkargs_sz (NFS3_fh_sz)
52#define NFS3_readargs_sz (NFS3_fh_sz+3)
53#define NFS3_writeargs_sz (NFS3_fh_sz+5)
54#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
55#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
94a6d753 56#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
1da177e4 57#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
ad96b5b5 58#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
1da177e4
LT
59#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
60#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
d9c407b1
CL
61#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
62#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
1da177e4
LT
63#define NFS3_commitargs_sz (NFS3_fh_sz+3)
64
f5fc3c50
CL
65#define NFS3_getattrres_sz (1+NFS3_fattr_sz)
66#define NFS3_setattrres_sz (1+NFS3_wcc_data_sz)
67#define NFS3_removeres_sz (NFS3_setattrres_sz)
1da177e4
LT
68#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
69#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
70#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
71#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
72#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
73#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
74#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
75#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
77#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
78#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
79#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
80#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
81
b7fa0554 82#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
ae46141f
TM
83#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
84 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
85#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
b7fa0554
AG
87#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
88
1da177e4
LT
89/*
90 * Map file type to S_IFMT bits
91 */
bca79478
TM
92static const umode_t nfs_type2fmt[] = {
93 [NF3BAD] = 0,
94 [NF3REG] = S_IFREG,
95 [NF3DIR] = S_IFDIR,
96 [NF3BLK] = S_IFBLK,
97 [NF3CHR] = S_IFCHR,
98 [NF3LNK] = S_IFLNK,
99 [NF3SOCK] = S_IFSOCK,
100 [NF3FIFO] = S_IFIFO,
1da177e4
LT
101};
102
d9c407b1
CL
103/*
104 * While encoding arguments, set up the reply buffer in advance to
105 * receive reply data directly into the page cache.
106 */
107static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
108 unsigned int base, unsigned int len,
109 unsigned int bufsize)
110{
111 struct rpc_auth *auth = req->rq_cred->cr_auth;
112 unsigned int replen;
113
114 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
115 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
116}
117
e4f93234
CL
118/*
119 * Handle decode buffer overflows out-of-line.
120 */
121static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
122{
123 dprintk("NFS: %s prematurely hit the end of our receive buffer. "
124 "Remaining buffer length is %tu words.\n",
125 func, xdr->end - xdr->p);
126}
127
d9c407b1 128
1da177e4
LT
129/*
130 * Common NFS XDR functions as inlines
131 */
d61005a6
AV
132static inline __be32 *
133xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
1da177e4
LT
134{
135 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
136 memcpy(fh->data, p, fh->size);
137 return p + XDR_QUADLEN(fh->size);
138 }
139 return NULL;
140}
141
babddc72
BS
142static inline __be32 *
143xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
144{
145 __be32 *p;
146 p = xdr_inline_decode(xdr, 4);
147 if (unlikely(!p))
148 goto out_overflow;
149 fh->size = ntohl(*p++);
150
151 if (fh->size <= NFS3_FHSIZE) {
152 p = xdr_inline_decode(xdr, fh->size);
153 if (unlikely(!p))
154 goto out_overflow;
155 memcpy(fh->data, p, fh->size);
156 return p + XDR_QUADLEN(fh->size);
157 }
158 return NULL;
159
160out_overflow:
161 print_overflow_msg(__func__, xdr);
162 return ERR_PTR(-EIO);
163}
164
1da177e4
LT
165/*
166 * Encode/decode time.
167 */
d61005a6
AV
168static inline __be32 *
169xdr_decode_time3(__be32 *p, struct timespec *timep)
1da177e4
LT
170{
171 timep->tv_sec = ntohl(*p++);
172 timep->tv_nsec = ntohl(*p++);
173 return p;
174}
175
d61005a6
AV
176static __be32 *
177xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
178{
179 unsigned int type, major, minor;
bca79478 180 umode_t fmode;
1da177e4
LT
181
182 type = ntohl(*p++);
bca79478
TM
183 if (type > NF3FIFO)
184 type = NF3NON;
185 fmode = nfs_type2fmt[type];
1da177e4
LT
186 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
187 fattr->nlink = ntohl(*p++);
188 fattr->uid = ntohl(*p++);
189 fattr->gid = ntohl(*p++);
190 p = xdr_decode_hyper(p, &fattr->size);
191 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
192
193 /* Turn remote device info into Linux-specific dev_t */
194 major = ntohl(*p++);
195 minor = ntohl(*p++);
196 fattr->rdev = MKDEV(major, minor);
197 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
198 fattr->rdev = 0;
199
8b4bdcf8
TM
200 p = xdr_decode_hyper(p, &fattr->fsid.major);
201 fattr->fsid.minor = 0;
1da177e4
LT
202 p = xdr_decode_hyper(p, &fattr->fileid);
203 p = xdr_decode_time3(p, &fattr->atime);
204 p = xdr_decode_time3(p, &fattr->mtime);
205 p = xdr_decode_time3(p, &fattr->ctime);
206
207 /* Update the mode bits */
9e6e70f8 208 fattr->valid |= NFS_ATTR_FATTR_V3;
1da177e4
LT
209 return p;
210}
211
d61005a6
AV
212static inline __be32 *
213xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
214{
215 p = xdr_decode_hyper(p, &fattr->pre_size);
216 p = xdr_decode_time3(p, &fattr->pre_mtime);
217 p = xdr_decode_time3(p, &fattr->pre_ctime);
9e6e70f8
TM
218 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
219 | NFS_ATTR_FATTR_PREMTIME
220 | NFS_ATTR_FATTR_PRECTIME;
1da177e4
LT
221 return p;
222}
223
d61005a6
AV
224static inline __be32 *
225xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
226{
227 if (*p++)
228 p = xdr_decode_fattr(p, fattr);
229 return p;
230}
231
babddc72
BS
232static inline __be32 *
233xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
234{
235 __be32 *p;
236
237 p = xdr_inline_decode(xdr, 4);
238 if (unlikely(!p))
239 goto out_overflow;
240 if (ntohl(*p++)) {
241 p = xdr_inline_decode(xdr, 84);
242 if (unlikely(!p))
243 goto out_overflow;
244 p = xdr_decode_fattr(p, fattr);
245 }
246 return p;
247out_overflow:
248 print_overflow_msg(__func__, xdr);
249 return ERR_PTR(-EIO);
250}
251
d61005a6
AV
252static inline __be32 *
253xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
254{
255 if (*p++)
256 return xdr_decode_wcc_attr(p, fattr);
257 return p;
258}
259
260
d61005a6
AV
261static inline __be32 *
262xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
263{
264 p = xdr_decode_pre_op_attr(p, fattr);
265 return xdr_decode_post_op_attr(p, fattr);
266}
267
d9c407b1
CL
268
269/*
270 * Encode/decode NFSv3 basic data types
271 *
272 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
273 * "NFS Version 3 Protocol Specification".
274 *
275 * Not all basic data types have their own encoding and decoding
276 * functions. For run-time efficiency, some data types are encoded
277 * or decoded inline.
278 */
279
280static void encode_uint32(struct xdr_stream *xdr, u32 value)
281{
282 __be32 *p = xdr_reserve_space(xdr, 4);
283 *p = cpu_to_be32(value);
284}
285
e4f93234
CL
286static int decode_uint32(struct xdr_stream *xdr, u32 *value)
287{
288 __be32 *p;
289
290 p = xdr_inline_decode(xdr, 4);
291 if (unlikely(p == NULL))
292 goto out_overflow;
293 *value = be32_to_cpup(p);
294 return 0;
295out_overflow:
296 print_overflow_msg(__func__, xdr);
297 return -EIO;
298}
299
300static int decode_uint64(struct xdr_stream *xdr, u64 *value)
301{
302 __be32 *p;
303
304 p = xdr_inline_decode(xdr, 8);
305 if (unlikely(p == NULL))
306 goto out_overflow;
307 xdr_decode_hyper(p, value);
308 return 0;
309out_overflow:
310 print_overflow_msg(__func__, xdr);
311 return -EIO;
312}
313
314/*
315 * fileid3
316 *
317 * typedef uint64 fileid3;
318 */
319static int decode_fileid3(struct xdr_stream *xdr, u64 *fileid)
320{
321 return decode_uint64(xdr, fileid);
322}
323
d9c407b1
CL
324/*
325 * filename3
326 *
327 * typedef string filename3<>;
328 */
329static void encode_filename3(struct xdr_stream *xdr,
330 const char *name, u32 length)
331{
332 __be32 *p;
333
334 BUG_ON(length > NFS3_MAXNAMLEN);
335 p = xdr_reserve_space(xdr, 4 + length);
336 xdr_encode_opaque(p, name, length);
337}
338
e4f93234
CL
339static int decode_inline_filename3(struct xdr_stream *xdr,
340 const char **name, u32 *length)
341{
342 __be32 *p;
343 u32 count;
344
345 p = xdr_inline_decode(xdr, 4);
346 if (unlikely(p == NULL))
347 goto out_overflow;
348 count = be32_to_cpup(p);
349 if (count > NFS3_MAXNAMLEN)
350 goto out_nametoolong;
351 p = xdr_inline_decode(xdr, count);
352 if (unlikely(p == NULL))
353 goto out_overflow;
354 *name = (const char *)p;
355 *length = count;
356 return 0;
357
358out_nametoolong:
359 dprintk("NFS: returned filename too long: %u\n", count);
360 return -ENAMETOOLONG;
361out_overflow:
362 print_overflow_msg(__func__, xdr);
363 return -EIO;
364}
365
d9c407b1
CL
366/*
367 * nfspath3
368 *
369 * typedef string nfspath3<>;
370 */
371static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
372 const u32 length)
373{
374 BUG_ON(length > NFS3_MAXPATHLEN);
375 encode_uint32(xdr, length);
376 xdr_write_pages(xdr, pages, 0, length);
377}
378
e4f93234
CL
379static int decode_nfspath3(struct xdr_stream *xdr)
380{
381 u32 recvd, count;
382 size_t hdrlen;
383 __be32 *p;
384
385 p = xdr_inline_decode(xdr, 4);
386 if (unlikely(p == NULL))
387 goto out_overflow;
388 count = be32_to_cpup(p);
389 if (unlikely(count >= xdr->buf->page_len || count > NFS3_MAXPATHLEN))
390 goto out_nametoolong;
391 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
392 recvd = xdr->buf->len - hdrlen;
393 if (unlikely(count > recvd))
394 goto out_cheating;
395
396 xdr_read_pages(xdr, count);
397 xdr_terminate_string(xdr->buf, count);
398 return 0;
399
400out_nametoolong:
401 dprintk("NFS: returned pathname too long: %u\n", count);
402 return -ENAMETOOLONG;
403out_cheating:
404 dprintk("NFS: server cheating in pathname result: "
405 "count %u > recvd %u\n", count, recvd);
406 return -EIO;
407out_overflow:
408 print_overflow_msg(__func__, xdr);
409 return -EIO;
410}
411
d9c407b1
CL
412/*
413 * cookie3
414 *
415 * typedef uint64 cookie3
416 */
417static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
418{
419 return xdr_encode_hyper(p, cookie);
420}
421
e4f93234
CL
422static int decode_cookie3(struct xdr_stream *xdr, u64 *cookie)
423{
424 return decode_uint64(xdr, cookie);
425}
426
d9c407b1
CL
427/*
428 * cookieverf3
429 *
430 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
431 */
432static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
433{
434 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
435 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
436}
437
e4f93234
CL
438static int decode_cookieverf3(struct xdr_stream *xdr, __be32 *verifier)
439{
440 __be32 *p;
441
442 p = xdr_inline_decode(xdr, NFS3_COOKIEVERFSIZE);
443 if (unlikely(p == NULL))
444 goto out_overflow;
445 memcpy(verifier, p, NFS3_COOKIEVERFSIZE);
446 return 0;
447out_overflow:
448 print_overflow_msg(__func__, xdr);
449 return -EIO;
450}
451
d9c407b1
CL
452/*
453 * createverf3
454 *
455 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
456 */
457static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
458{
459 __be32 *p;
460
461 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
462 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
463}
464
e4f93234
CL
465static int decode_writeverf3(struct xdr_stream *xdr, __be32 *verifier)
466{
467 __be32 *p;
468
469 p = xdr_inline_decode(xdr, NFS3_WRITEVERFSIZE);
470 if (unlikely(p == NULL))
471 goto out_overflow;
472 memcpy(verifier, p, NFS3_WRITEVERFSIZE);
473 return 0;
474out_overflow:
475 print_overflow_msg(__func__, xdr);
476 return -EIO;
477}
478
479/*
480 * size3
481 *
482 * typedef uint64 size3;
483 */
484static __be32 *xdr_decode_size3(__be32 *p, u64 *size)
485{
486 return xdr_decode_hyper(p, size);
487}
488
489/*
490 * nfsstat3
491 *
492 * enum nfsstat3 {
493 * NFS3_OK = 0,
494 * ...
495 * }
496 */
497#define NFS3_OK NFS_OK
498
499static int decode_nfsstat3(struct xdr_stream *xdr, enum nfs_stat *status)
500{
501 __be32 *p;
502
503 p = xdr_inline_decode(xdr, 4);
504 if (unlikely(p == NULL))
505 goto out_overflow;
506 *status = be32_to_cpup(p);
507 return 0;
508out_overflow:
509 print_overflow_msg(__func__, xdr);
510 return -EIO;
511}
512
d9c407b1
CL
513/*
514 * ftype3
515 *
516 * enum ftype3 {
517 * NF3REG = 1,
518 * NF3DIR = 2,
519 * NF3BLK = 3,
520 * NF3CHR = 4,
521 * NF3LNK = 5,
522 * NF3SOCK = 6,
523 * NF3FIFO = 7
524 * };
525 */
526static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
527{
528 BUG_ON(type > NF3FIFO);
529 encode_uint32(xdr, type);
530}
531
532/*
533 * specdata3
534 *
535 * struct specdata3 {
536 * uint32 specdata1;
537 * uint32 specdata2;
538 * };
539 */
540static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
541{
542 __be32 *p;
543
544 p = xdr_reserve_space(xdr, 8);
545 *p++ = cpu_to_be32(MAJOR(rdev));
546 *p = cpu_to_be32(MINOR(rdev));
547}
548
549/*
550 * nfs_fh3
551 *
552 * struct nfs_fh3 {
553 * opaque data<NFS3_FHSIZE>;
554 * };
555 */
556static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
557{
558 __be32 *p;
559
560 BUG_ON(fh->size > NFS3_FHSIZE);
561 p = xdr_reserve_space(xdr, 4 + fh->size);
562 xdr_encode_opaque(p, fh->data, fh->size);
563}
564
e4f93234
CL
565static int decode_nfs_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
566{
567 u32 length;
568 __be32 *p;
569
570 p = xdr_inline_decode(xdr, 4);
571 if (unlikely(p == NULL))
572 goto out_overflow;
573 length = be32_to_cpup(p++);
574 if (unlikely(length > NFS3_FHSIZE))
575 goto out_toobig;
576 p = xdr_inline_decode(xdr, length);
577 if (unlikely(p == NULL))
578 goto out_overflow;
579 fh->size = length;
580 memcpy(fh->data, p, length);
581 return 0;
582out_toobig:
583 dprintk("NFS: file handle size (%u) too big\n", length);
584 return -E2BIG;
585out_overflow:
586 print_overflow_msg(__func__, xdr);
587 return -EIO;
588}
589
590static void zero_nfs_fh3(struct nfs_fh *fh)
591{
592 memset(fh, 0, sizeof(*fh));
593}
594
9d5a6434
CL
595/*
596 * nfstime3
597 *
598 * struct nfstime3 {
599 * uint32 seconds;
600 * uint32 nseconds;
601 * };
602 */
603static __be32 *xdr_encode_nfstime3(__be32 *p, const struct timespec *timep)
604{
605 *p++ = cpu_to_be32(timep->tv_sec);
606 *p++ = cpu_to_be32(timep->tv_nsec);
607 return p;
608}
609
d9c407b1
CL
610/*
611 * sattr3
612 *
613 * enum time_how {
614 * DONT_CHANGE = 0,
615 * SET_TO_SERVER_TIME = 1,
616 * SET_TO_CLIENT_TIME = 2
617 * };
618 *
619 * union set_mode3 switch (bool set_it) {
620 * case TRUE:
621 * mode3 mode;
622 * default:
623 * void;
624 * };
625 *
626 * union set_uid3 switch (bool set_it) {
627 * case TRUE:
628 * uid3 uid;
629 * default:
630 * void;
631 * };
632 *
633 * union set_gid3 switch (bool set_it) {
634 * case TRUE:
635 * gid3 gid;
636 * default:
637 * void;
638 * };
639 *
640 * union set_size3 switch (bool set_it) {
641 * case TRUE:
642 * size3 size;
643 * default:
644 * void;
645 * };
646 *
647 * union set_atime switch (time_how set_it) {
648 * case SET_TO_CLIENT_TIME:
649 * nfstime3 atime;
650 * default:
651 * void;
652 * };
653 *
654 * union set_mtime switch (time_how set_it) {
655 * case SET_TO_CLIENT_TIME:
656 * nfstime3 mtime;
657 * default:
658 * void;
659 * };
660 *
661 * struct sattr3 {
662 * set_mode3 mode;
663 * set_uid3 uid;
664 * set_gid3 gid;
665 * set_size3 size;
666 * set_atime atime;
667 * set_mtime mtime;
668 * };
669 */
670static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
671{
672 u32 nbytes;
673 __be32 *p;
674
675 /*
676 * In order to make only a single xdr_reserve_space() call,
677 * pre-compute the total number of bytes to be reserved.
678 * Six boolean values, one for each set_foo field, are always
679 * present in the encoded result, so start there.
680 */
681 nbytes = 6 * 4;
682 if (attr->ia_valid & ATTR_MODE)
683 nbytes += 4;
684 if (attr->ia_valid & ATTR_UID)
685 nbytes += 4;
686 if (attr->ia_valid & ATTR_GID)
687 nbytes += 4;
688 if (attr->ia_valid & ATTR_SIZE)
689 nbytes += 8;
690 if (attr->ia_valid & ATTR_ATIME_SET)
691 nbytes += 8;
692 if (attr->ia_valid & ATTR_MTIME_SET)
693 nbytes += 8;
694 p = xdr_reserve_space(xdr, nbytes);
695
9d5a6434
CL
696 if (attr->ia_valid & ATTR_MODE) {
697 *p++ = xdr_one;
698 *p++ = cpu_to_be32(attr->ia_mode & S_IALLUGO);
699 } else
700 *p++ = xdr_zero;
701
702 if (attr->ia_valid & ATTR_UID) {
703 *p++ = xdr_one;
704 *p++ = cpu_to_be32(attr->ia_uid);
705 } else
706 *p++ = xdr_zero;
707
708 if (attr->ia_valid & ATTR_GID) {
709 *p++ = xdr_one;
710 *p++ = cpu_to_be32(attr->ia_gid);
711 } else
712 *p++ = xdr_zero;
713
714 if (attr->ia_valid & ATTR_SIZE) {
715 *p++ = xdr_one;
716 p = xdr_encode_hyper(p, (u64)attr->ia_size);
717 } else
718 *p++ = xdr_zero;
719
720 if (attr->ia_valid & ATTR_ATIME_SET) {
721 *p++ = xdr_two;
722 p = xdr_encode_nfstime3(p, &attr->ia_atime);
723 } else if (attr->ia_valid & ATTR_ATIME) {
724 *p++ = xdr_one;
725 } else
726 *p++ = xdr_zero;
727
728 if (attr->ia_valid & ATTR_MTIME_SET) {
729 *p++ = xdr_two;
730 xdr_encode_nfstime3(p, &attr->ia_mtime);
731 } else if (attr->ia_valid & ATTR_MTIME) {
732 *p = xdr_one;
733 } else
734 *p = xdr_zero;
d9c407b1
CL
735}
736
e4f93234
CL
737/*
738 * fattr3
739 *
740 * struct fattr3 {
741 * ftype3 type;
742 * mode3 mode;
743 * uint32 nlink;
744 * uid3 uid;
745 * gid3 gid;
746 * size3 size;
747 * size3 used;
748 * specdata3 rdev;
749 * uint64 fsid;
750 * fileid3 fileid;
751 * nfstime3 atime;
752 * nfstime3 mtime;
753 * nfstime3 ctime;
754 * };
755 */
756static int decode_fattr3(struct xdr_stream *xdr, struct nfs_fattr *fattr)
757{
758 __be32 *p;
759
760 p = xdr_inline_decode(xdr, NFS3_fattr_sz << 2);
761 if (unlikely(p == NULL))
762 goto out_overflow;
763 xdr_decode_fattr(p, fattr);
764 return 0;
765out_overflow:
766 print_overflow_msg(__func__, xdr);
767 return -EIO;
768}
769
770/*
771 * post_op_attr
772 *
773 * union post_op_attr switch (bool attributes_follow) {
774 * case TRUE:
775 * fattr3 attributes;
776 * case FALSE:
777 * void;
778 * };
779 */
780static int decode_post_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
781{
782 __be32 *p;
783
784 p = xdr_inline_decode(xdr, 4);
785 if (unlikely(p == NULL))
786 goto out_overflow;
787 if (*p != xdr_zero)
788 return decode_fattr3(xdr, fattr);
789 return 0;
790out_overflow:
791 print_overflow_msg(__func__, xdr);
792 return -EIO;
793}
794
795/*
796 * wcc_attr
797 * struct wcc_attr {
798 * size3 size;
799 * nfstime3 mtime;
800 * nfstime3 ctime;
801 * };
802 */
803static int decode_wcc_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
804{
805 __be32 *p;
806
807 p = xdr_inline_decode(xdr, NFS3_wcc_attr_sz << 2);
808 if (unlikely(p == NULL))
809 goto out_overflow;
810 xdr_decode_wcc_attr(p, fattr);
811 return 0;
812out_overflow:
813 print_overflow_msg(__func__, xdr);
814 return -EIO;
815}
816
817/*
818 * pre_op_attr
819 * union pre_op_attr switch (bool attributes_follow) {
820 * case TRUE:
821 * wcc_attr attributes;
822 * case FALSE:
823 * void;
824 * };
825 *
826 * wcc_data
827 *
828 * struct wcc_data {
829 * pre_op_attr before;
830 * post_op_attr after;
831 * };
832 */
833static int decode_pre_op_attr(struct xdr_stream *xdr, struct nfs_fattr *fattr)
834{
835 __be32 *p;
836
837 p = xdr_inline_decode(xdr, 4);
838 if (unlikely(p == NULL))
839 goto out_overflow;
840 if (*p != xdr_zero)
841 return decode_wcc_attr(xdr, fattr);
842 return 0;
843out_overflow:
844 print_overflow_msg(__func__, xdr);
845 return -EIO;
846}
847
848static int decode_wcc_data(struct xdr_stream *xdr, struct nfs_fattr *fattr)
849{
850 int error;
851
852 error = decode_pre_op_attr(xdr, fattr);
853 if (unlikely(error))
854 goto out;
855 error = decode_post_op_attr(xdr, fattr);
856out:
857 return error;
858}
859
860/*
861 * post_op_fh3
862 *
863 * union post_op_fh3 switch (bool handle_follows) {
864 * case TRUE:
865 * nfs_fh3 handle;
866 * case FALSE:
867 * void;
868 * };
869 */
870static int decode_post_op_fh3(struct xdr_stream *xdr, struct nfs_fh *fh)
871{
872 __be32 *p = xdr_inline_decode(xdr, 4);
873 if (unlikely(p == NULL))
874 goto out_overflow;
875 if (*p != xdr_zero)
876 return decode_nfs_fh3(xdr, fh);
877 zero_nfs_fh3(fh);
878 return 0;
879out_overflow:
880 print_overflow_msg(__func__, xdr);
881 return -EIO;
882}
883
d9c407b1
CL
884/*
885 * diropargs3
886 *
887 * struct diropargs3 {
888 * nfs_fh3 dir;
889 * filename3 name;
890 * };
891 */
892static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
893 const char *name, u32 length)
894{
895 encode_nfs_fh3(xdr, fh);
896 encode_filename3(xdr, name, length);
897}
898
899
1da177e4 900/*
499ff710
CL
901 * NFSv3 XDR encode functions
902 *
903 * NFSv3 argument types are defined in section 3.3 of RFC 1813:
904 * "NFS Version 3 Protocol Specification".
1da177e4
LT
905 */
906
d9c407b1
CL
907/*
908 * 3.3.1 GETATTR3args
909 *
910 * struct GETATTR3args {
911 * nfs_fh3 object;
912 * };
913 */
914static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
915 const struct nfs_fh *fh)
916{
917 struct xdr_stream xdr;
918
919 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
920 encode_nfs_fh3(&xdr, fh);
921 return 0;
922}
923
d9c407b1
CL
924/*
925 * 3.3.2 SETATTR3args
926 *
927 * union sattrguard3 switch (bool check) {
928 * case TRUE:
929 * nfstime3 obj_ctime;
930 * case FALSE:
931 * void;
932 * };
933 *
934 * struct SETATTR3args {
935 * nfs_fh3 object;
936 * sattr3 new_attributes;
937 * sattrguard3 guard;
938 * };
939 */
940static void encode_sattrguard3(struct xdr_stream *xdr,
941 const struct nfs3_sattrargs *args)
942{
943 __be32 *p;
944
945 if (args->guard) {
946 p = xdr_reserve_space(xdr, 4 + 8);
947 *p++ = xdr_one;
9d5a6434 948 xdr_encode_nfstime3(p, &args->guardtime);
d9c407b1
CL
949 } else {
950 p = xdr_reserve_space(xdr, 4);
951 *p = xdr_zero;
952 }
953}
954
955static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
956 const struct nfs3_sattrargs *args)
957{
958 struct xdr_stream xdr;
959
960 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
961 encode_nfs_fh3(&xdr, args->fh);
962 encode_sattr3(&xdr, args->sattr);
963 encode_sattrguard3(&xdr, args);
964 return 0;
965}
966
d9c407b1
CL
967/*
968 * 3.3.3 LOOKUP3args
969 *
970 * struct LOOKUP3args {
971 * diropargs3 what;
972 * };
973 */
974static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
975 const struct nfs3_diropargs *args)
976{
977 struct xdr_stream xdr;
978
979 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
980 encode_diropargs3(&xdr, args->fh, args->name, args->len);
981 return 0;
982}
983
d9c407b1
CL
984/*
985 * 3.3.4 ACCESS3args
986 *
987 * struct ACCESS3args {
988 * nfs_fh3 object;
989 * uint32 access;
990 * };
991 */
992static void encode_access3args(struct xdr_stream *xdr,
993 const struct nfs3_accessargs *args)
994{
995 encode_nfs_fh3(xdr, args->fh);
996 encode_uint32(xdr, args->access);
997}
998
999static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
1000 const struct nfs3_accessargs *args)
1001{
1002 struct xdr_stream xdr;
1003
1004 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1005 encode_access3args(&xdr, args);
1006 return 0;
1007}
1008
1009/*
1010 * 3.3.5 READLINK3args
1011 *
1012 * struct READLINK3args {
1013 * nfs_fh3 symlink;
1014 * };
1015 */
1016static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
1017 const struct nfs3_readlinkargs *args)
1018{
1019 struct xdr_stream xdr;
1020
1021 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1022 encode_nfs_fh3(&xdr, args->fh);
1023 prepare_reply_buffer(req, args->pages, args->pgbase,
1024 args->pglen, NFS3_readlinkres_sz);
1025 return 0;
1026}
1027
d9c407b1
CL
1028/*
1029 * 3.3.6 READ3args
1030 *
1031 * struct READ3args {
1032 * nfs_fh3 file;
1033 * offset3 offset;
1034 * count3 count;
1035 * };
1036 */
1037static void encode_read3args(struct xdr_stream *xdr,
1038 const struct nfs_readargs *args)
1039{
1040 __be32 *p;
1041
1042 encode_nfs_fh3(xdr, args->fh);
1043
1044 p = xdr_reserve_space(xdr, 8 + 4);
1045 p = xdr_encode_hyper(p, args->offset);
1046 *p = cpu_to_be32(args->count);
1047}
1048
1049static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
1050 const struct nfs_readargs *args)
1051{
1052 struct xdr_stream xdr;
1053
1054 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1055 encode_read3args(&xdr, args);
1056 prepare_reply_buffer(req, args->pages, args->pgbase,
1057 args->count, NFS3_readres_sz);
1058 req->rq_rcv_buf.flags |= XDRBUF_READ;
1059 return 0;
1060}
1061
d9c407b1
CL
1062/*
1063 * 3.3.7 WRITE3args
1064 *
1065 * enum stable_how {
1066 * UNSTABLE = 0,
1067 * DATA_SYNC = 1,
1068 * FILE_SYNC = 2
1069 * };
1070 *
1071 * struct WRITE3args {
1072 * nfs_fh3 file;
1073 * offset3 offset;
1074 * count3 count;
1075 * stable_how stable;
1076 * opaque data<>;
1077 * };
1078 */
1079static void encode_write3args(struct xdr_stream *xdr,
1080 const struct nfs_writeargs *args)
1081{
1082 __be32 *p;
1083
1084 encode_nfs_fh3(xdr, args->fh);
1085
1086 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
1087 p = xdr_encode_hyper(p, args->offset);
1088 *p++ = cpu_to_be32(args->count);
1089
1090 BUG_ON(args->stable > NFS_FILE_SYNC);
1091 *p++ = cpu_to_be32(args->stable);
1092
1093 *p = cpu_to_be32(args->count);
1094 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
1095}
1096
1097static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
1098 const struct nfs_writeargs *args)
1099{
1100 struct xdr_stream xdr;
1101
1102 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1103 encode_write3args(&xdr, args);
1104 xdr.buf->flags |= XDRBUF_WRITE;
1105 return 0;
1106}
1107
d9c407b1
CL
1108/*
1109 * 3.3.8 CREATE3args
1110 *
1111 * enum createmode3 {
1112 * UNCHECKED = 0,
1113 * GUARDED = 1,
1114 * EXCLUSIVE = 2
1115 * };
1116 *
1117 * union createhow3 switch (createmode3 mode) {
1118 * case UNCHECKED:
1119 * case GUARDED:
1120 * sattr3 obj_attributes;
1121 * case EXCLUSIVE:
1122 * createverf3 verf;
1123 * };
1124 *
1125 * struct CREATE3args {
1126 * diropargs3 where;
1127 * createhow3 how;
1128 * };
1129 */
1130static void encode_createhow3(struct xdr_stream *xdr,
1131 const struct nfs3_createargs *args)
1132{
1133 encode_uint32(xdr, args->createmode);
1134 switch (args->createmode) {
1135 case NFS3_CREATE_UNCHECKED:
1136 case NFS3_CREATE_GUARDED:
1137 encode_sattr3(xdr, args->sattr);
1138 break;
1139 case NFS3_CREATE_EXCLUSIVE:
1140 encode_createverf3(xdr, args->verifier);
1141 break;
1142 default:
1143 BUG();
1144 }
1145}
1146
1147static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
1148 const struct nfs3_createargs *args)
1149{
1150 struct xdr_stream xdr;
1151
1152 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1153 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1154 encode_createhow3(&xdr, args);
1155 return 0;
1156}
1157
d9c407b1
CL
1158/*
1159 * 3.3.9 MKDIR3args
1160 *
1161 * struct MKDIR3args {
1162 * diropargs3 where;
1163 * sattr3 attributes;
1164 * };
1165 */
1166static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
1167 const struct nfs3_mkdirargs *args)
1168{
1169 struct xdr_stream xdr;
1170
1171 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1172 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1173 encode_sattr3(&xdr, args->sattr);
1174 return 0;
1175}
1176
d9c407b1
CL
1177/*
1178 * 3.3.10 SYMLINK3args
1179 *
1180 * struct symlinkdata3 {
1181 * sattr3 symlink_attributes;
1182 * nfspath3 symlink_data;
1183 * };
1184 *
1185 * struct SYMLINK3args {
1186 * diropargs3 where;
1187 * symlinkdata3 symlink;
1188 * };
1189 */
1190static void encode_symlinkdata3(struct xdr_stream *xdr,
1191 const struct nfs3_symlinkargs *args)
1192{
1193 encode_sattr3(xdr, args->sattr);
1194 encode_nfspath3(xdr, args->pages, args->pathlen);
1195}
1196
1197static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
1198 const struct nfs3_symlinkargs *args)
1199{
1200 struct xdr_stream xdr;
1201
1202 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1203 encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
1204 encode_symlinkdata3(&xdr, args);
1205 return 0;
1206}
1207
d9c407b1
CL
1208/*
1209 * 3.3.11 MKNOD3args
1210 *
1211 * struct devicedata3 {
1212 * sattr3 dev_attributes;
1213 * specdata3 spec;
1214 * };
1215 *
1216 * union mknoddata3 switch (ftype3 type) {
1217 * case NF3CHR:
1218 * case NF3BLK:
1219 * devicedata3 device;
1220 * case NF3SOCK:
1221 * case NF3FIFO:
1222 * sattr3 pipe_attributes;
1223 * default:
1224 * void;
1225 * };
1226 *
1227 * struct MKNOD3args {
1228 * diropargs3 where;
1229 * mknoddata3 what;
1230 * };
1231 */
1232static void encode_devicedata3(struct xdr_stream *xdr,
1233 const struct nfs3_mknodargs *args)
1234{
1235 encode_sattr3(xdr, args->sattr);
1236 encode_specdata3(xdr, args->rdev);
1237}
1238
1239static void encode_mknoddata3(struct xdr_stream *xdr,
1240 const struct nfs3_mknodargs *args)
1241{
1242 encode_ftype3(xdr, args->type);
1243 switch (args->type) {
1244 case NF3CHR:
1245 case NF3BLK:
1246 encode_devicedata3(xdr, args);
1247 break;
1248 case NF3SOCK:
1249 case NF3FIFO:
1250 encode_sattr3(xdr, args->sattr);
1251 break;
1252 case NF3REG:
1253 case NF3DIR:
1254 break;
1255 default:
1256 BUG();
1257 }
1258}
1259
1260static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
1261 const struct nfs3_mknodargs *args)
1262{
1263 struct xdr_stream xdr;
1264
1265 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1266 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1267 encode_mknoddata3(&xdr, args);
1268 return 0;
1269}
1270
1271/*
1272 * 3.3.12 REMOVE3args
1273 *
1274 * struct REMOVE3args {
1275 * diropargs3 object;
1276 * };
1277 */
1278static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
1279 const struct nfs_removeargs *args)
1280{
1281 struct xdr_stream xdr;
1282
1283 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1284 encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
1285 return 0;
1286}
1287
d9c407b1
CL
1288/*
1289 * 3.3.14 RENAME3args
1290 *
1291 * struct RENAME3args {
1292 * diropargs3 from;
1293 * diropargs3 to;
1294 * };
1295 */
1296static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
1297 const struct nfs_renameargs *args)
1298{
1299 const struct qstr *old = args->old_name;
1300 const struct qstr *new = args->new_name;
1301 struct xdr_stream xdr;
1302
1303 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1304 encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
1305 encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
1306 return 0;
1307}
1308
d9c407b1
CL
1309/*
1310 * 3.3.15 LINK3args
1311 *
1312 * struct LINK3args {
1313 * nfs_fh3 file;
1314 * diropargs3 link;
1315 * };
1316 */
1317static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
1318 const struct nfs3_linkargs *args)
1319{
1320 struct xdr_stream xdr;
1321
1322 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1323 encode_nfs_fh3(&xdr, args->fromfh);
1324 encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
1325 return 0;
1326}
1327
d9c407b1
CL
1328/*
1329 * 3.3.16 READDIR3args
1330 *
1331 * struct READDIR3args {
1332 * nfs_fh3 dir;
1333 * cookie3 cookie;
1334 * cookieverf3 cookieverf;
1335 * count3 count;
1336 * };
1337 */
1338static void encode_readdir3args(struct xdr_stream *xdr,
1339 const struct nfs3_readdirargs *args)
1340{
1341 __be32 *p;
1342
1343 encode_nfs_fh3(xdr, args->fh);
1344
1345 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1346 p = xdr_encode_cookie3(p, args->cookie);
1347 p = xdr_encode_cookieverf3(p, args->verf);
1348 *p = cpu_to_be32(args->count);
1349}
1350
1351static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1352 const struct nfs3_readdirargs *args)
1353{
1354 struct xdr_stream xdr;
1355
1356 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1357 encode_readdir3args(&xdr, args);
1358 prepare_reply_buffer(req, args->pages, 0,
1359 args->count, NFS3_readdirres_sz);
1360 return 0;
1361}
1362
1363/*
1364 * 3.3.17 READDIRPLUS3args
1365 *
1366 * struct READDIRPLUS3args {
1367 * nfs_fh3 dir;
1368 * cookie3 cookie;
1369 * cookieverf3 cookieverf;
1370 * count3 dircount;
1371 * count3 maxcount;
1372 * };
1373 */
1374static void encode_readdirplus3args(struct xdr_stream *xdr,
1375 const struct nfs3_readdirargs *args)
1376{
1377 __be32 *p;
1378
1379 encode_nfs_fh3(xdr, args->fh);
1380
1381 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1382 p = xdr_encode_cookie3(p, args->cookie);
1383 p = xdr_encode_cookieverf3(p, args->verf);
1384
1385 /*
1386 * readdirplus: need dircount + buffer size.
1387 * We just make sure we make dircount big enough
1388 */
1389 *p++ = cpu_to_be32(args->count >> 3);
1390
1391 *p = cpu_to_be32(args->count);
1392}
1393
1394static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1395 const struct nfs3_readdirargs *args)
1396{
1397 struct xdr_stream xdr;
1398
1399 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1400 encode_readdirplus3args(&xdr, args);
1401 prepare_reply_buffer(req, args->pages, 0,
1402 args->count, NFS3_readdirres_sz);
1403 return 0;
1404}
1405
1da177e4
LT
1406/*
1407 * Decode the result of a readdir call.
1408 * We just check for syntactical correctness.
1409 */
1410static int
d61005a6 1411nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1da177e4
LT
1412{
1413 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1414 struct kvec *iov = rcvbuf->head;
1415 struct page **page;
c957c526 1416 size_t hdrlen;
afa8ccc9 1417 u32 recvd, pglen;
ac396128 1418 int status;
1da177e4
LT
1419
1420 status = ntohl(*p++);
1421 /* Decode post_op_attrs */
1422 p = xdr_decode_post_op_attr(p, res->dir_attr);
1423 if (status)
856dff3d 1424 return nfs_stat_to_errno(status);
1da177e4
LT
1425 /* Decode verifier cookie */
1426 if (res->verf) {
1427 res->verf[0] = *p++;
1428 res->verf[1] = *p++;
1429 } else {
1430 p += 2;
1431 }
1432
1433 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1434 if (iov->iov_len < hdrlen) {
fe82a183 1435 dprintk("NFS: READDIR reply header overflowed:"
c957c526 1436 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1437 return -errno_NFSERR_IO;
1438 } else if (iov->iov_len != hdrlen) {
1439 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
1440 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1441 }
1442
1443 pglen = rcvbuf->page_len;
1444 recvd = rcvbuf->len - hdrlen;
1445 if (pglen > recvd)
1446 pglen = recvd;
1447 page = rcvbuf->pages;
643f8111 1448
ac396128 1449 return pglen;
1da177e4
LT
1450}
1451
d9c407b1
CL
1452/*
1453 * 3.3.21 COMMIT3args
1454 *
1455 * struct COMMIT3args {
1456 * nfs_fh3 file;
1457 * offset3 offset;
1458 * count3 count;
1459 * };
1460 */
1461static void encode_commit3args(struct xdr_stream *xdr,
1462 const struct nfs_writeargs *args)
1463{
1464 __be32 *p;
1465
1466 encode_nfs_fh3(xdr, args->fh);
1467
1468 p = xdr_reserve_space(xdr, 8 + 4);
1469 p = xdr_encode_hyper(p, args->offset);
1470 *p = cpu_to_be32(args->count);
1471}
1472
1473static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1474 const struct nfs_writeargs *args)
1475{
1476 struct xdr_stream xdr;
1477
1478 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1479 encode_commit3args(&xdr, args);
1480 return 0;
1481}
1482
b7fa0554 1483#ifdef CONFIG_NFS_V3_ACL
b7fa0554 1484
d9c407b1
CL
1485static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1486 const struct nfs3_getaclargs *args)
1487{
1488 struct xdr_stream xdr;
1489
1490 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1491 encode_nfs_fh3(&xdr, args->fh);
1492 encode_uint32(&xdr, args->mask);
1493 if (args->mask & (NFS_ACL | NFS_DFACL))
1494 prepare_reply_buffer(req, args->pages, 0,
1495 NFSACL_MAXPAGES << PAGE_SHIFT,
1496 ACL3_getaclres_sz);
1497 return 0;
1498}
1499
d9c407b1
CL
1500static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1501 const struct nfs3_setaclargs *args)
1502{
1503 struct xdr_stream xdr;
1504 unsigned int base;
1505 int error;
1506
1507 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1508 encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1509 encode_uint32(&xdr, args->mask);
1510 if (args->npages != 0)
1511 xdr_write_pages(&xdr, args->pages, 0, args->len);
1512
1513 base = req->rq_slen;
1514 error = nfsacl_encode(xdr.buf, base, args->inode,
1515 (args->mask & NFS_ACL) ?
1516 args->acl_access : NULL, 1, 0);
1517 BUG_ON(error < 0);
1518 error = nfsacl_encode(xdr.buf, base + error, args->inode,
1519 (args->mask & NFS_DFACL) ?
1520 args->acl_default : NULL, 1,
1521 NFS_ACL_DEFAULT);
1522 BUG_ON(error < 0);
1523 return 0;
1524}
1525
b7fa0554
AG
1526#endif /* CONFIG_NFS_V3_ACL */
1527
1da177e4
LT
1528/*
1529 * NFS XDR decode functions
1530 */
1531
1532/*
1533 * Decode attrstat reply.
1534 */
1535static int
d61005a6 1536nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
1537{
1538 int status;
1539
1540 if ((status = ntohl(*p++)))
856dff3d 1541 return nfs_stat_to_errno(status);
1da177e4
LT
1542 xdr_decode_fattr(p, fattr);
1543 return 0;
1544}
1545
1546/*
e4f93234
CL
1547 * 3.3.1 GETATTR3res
1548 *
1549 * struct GETATTR3resok {
1550 * fattr3 obj_attributes;
1551 * };
1552 *
1553 * union GETATTR3res switch (nfsstat3 status) {
1554 * case NFS3_OK:
1555 * GETATTR3resok resok;
1556 * default:
1557 * void;
1558 * };
1da177e4 1559 */
e4f93234
CL
1560static int nfs3_xdr_dec_getattr3res(struct rpc_rqst *req, __be32 *p,
1561 struct nfs_fattr *result)
1da177e4 1562{
e4f93234
CL
1563 struct xdr_stream xdr;
1564 enum nfs_stat status;
1565 int error;
1566
1567 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1568 error = decode_nfsstat3(&xdr, &status);
1569 if (unlikely(error))
1570 goto out;
1571 if (status != NFS3_OK)
1572 goto out_default;
1573 error = decode_fattr3(&xdr, result);
1574out:
1575 return error;
1576out_default:
1577 return nfs_stat_to_errno(status);
1578}
1579
1580/*
1581 * Decode status+wcc_data reply
1582 * SATTR, REMOVE, RMDIR
1583 */
1584static int
1585nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1586{
1587 int status;
1da177e4
LT
1588
1589 if ((status = ntohl(*p++)))
856dff3d 1590 status = nfs_stat_to_errno(status);
1da177e4
LT
1591 xdr_decode_wcc_data(p, fattr);
1592 return status;
1593}
1594
e4f93234
CL
1595/*
1596 * 3.3.2 SETATTR3res
1597 *
1598 * struct SETATTR3resok {
1599 * wcc_data obj_wcc;
1600 * };
1601 *
1602 * struct SETATTR3resfail {
1603 * wcc_data obj_wcc;
1604 * };
1605 *
1606 * union SETATTR3res switch (nfsstat3 status) {
1607 * case NFS3_OK:
1608 * SETATTR3resok resok;
1609 * default:
1610 * SETATTR3resfail resfail;
1611 * };
1612 */
1613static int nfs3_xdr_dec_setattr3res(struct rpc_rqst *req, __be32 *p,
1614 struct nfs_fattr *result)
1615{
1616 struct xdr_stream xdr;
1617 enum nfs_stat status;
1618 int error;
1619
1620 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1621 error = decode_nfsstat3(&xdr, &status);
1622 if (unlikely(error))
1623 goto out;
1624 error = decode_wcc_data(&xdr, result);
1625 if (unlikely(error))
1626 goto out;
1627 if (status != NFS3_OK)
1628 goto out_status;
1629out:
1630 return error;
1631out_status:
1632 return nfs_stat_to_errno(status);
1633}
1634
4fdc17b2
TM
1635static int
1636nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1637{
d346890b 1638 return nfs3_xdr_wccstat(req, p, res->dir_attr);
4fdc17b2
TM
1639}
1640
1da177e4
LT
1641/*
1642 * Decode LOOKUP reply
1643 */
1644static int
d61005a6 1645nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
1646{
1647 int status;
1648
1649 if ((status = ntohl(*p++))) {
856dff3d 1650 status = nfs_stat_to_errno(status);
1da177e4
LT
1651 } else {
1652 if (!(p = xdr_decode_fhandle(p, res->fh)))
1653 return -errno_NFSERR_IO;
1654 p = xdr_decode_post_op_attr(p, res->fattr);
1655 }
1656 xdr_decode_post_op_attr(p, res->dir_attr);
1657 return status;
1658}
1659
e4f93234
CL
1660/*
1661 * 3.3.3 LOOKUP3res
1662 *
1663 * struct LOOKUP3resok {
1664 * nfs_fh3 object;
1665 * post_op_attr obj_attributes;
1666 * post_op_attr dir_attributes;
1667 * };
1668 *
1669 * struct LOOKUP3resfail {
1670 * post_op_attr dir_attributes;
1671 * };
1672 *
1673 * union LOOKUP3res switch (nfsstat3 status) {
1674 * case NFS3_OK:
1675 * LOOKUP3resok resok;
1676 * default:
1677 * LOOKUP3resfail resfail;
1678 * };
1679 */
1680static int nfs3_xdr_dec_lookup3res(struct rpc_rqst *req, __be32 *p,
1681 struct nfs3_diropres *result)
1682{
1683 struct xdr_stream xdr;
1684 enum nfs_stat status;
1685 int error;
1686
1687 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1688 error = decode_nfsstat3(&xdr, &status);
1689 if (unlikely(error))
1690 goto out;
1691 if (status != NFS3_OK)
1692 goto out_default;
1693 error = decode_nfs_fh3(&xdr, result->fh);
1694 if (unlikely(error))
1695 goto out;
1696 error = decode_post_op_attr(&xdr, result->fattr);
1697 if (unlikely(error))
1698 goto out;
1699 error = decode_post_op_attr(&xdr, result->dir_attr);
1700out:
1701 return error;
1702out_default:
1703 error = decode_post_op_attr(&xdr, result->dir_attr);
1704 if (unlikely(error))
1705 goto out;
1706 return nfs_stat_to_errno(status);
1707}
1708
1da177e4
LT
1709/*
1710 * Decode ACCESS reply
1711 */
1712static int
d61005a6 1713nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1da177e4
LT
1714{
1715 int status = ntohl(*p++);
1716
1717 p = xdr_decode_post_op_attr(p, res->fattr);
1718 if (status)
856dff3d 1719 return nfs_stat_to_errno(status);
1da177e4
LT
1720 res->access = ntohl(*p++);
1721 return 0;
1722}
1723
e4f93234
CL
1724/*
1725 * 3.3.4 ACCESS3res
1726 *
1727 * struct ACCESS3resok {
1728 * post_op_attr obj_attributes;
1729 * uint32 access;
1730 * };
1731 *
1732 * struct ACCESS3resfail {
1733 * post_op_attr obj_attributes;
1734 * };
1735 *
1736 * union ACCESS3res switch (nfsstat3 status) {
1737 * case NFS3_OK:
1738 * ACCESS3resok resok;
1739 * default:
1740 * ACCESS3resfail resfail;
1741 * };
1742 */
1743static int nfs3_xdr_dec_access3res(struct rpc_rqst *req, __be32 *p,
1744 struct nfs3_accessres *result)
1745{
1746 struct xdr_stream xdr;
1747 enum nfs_stat status;
1748 int error;
1749
1750 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1751 error = decode_nfsstat3(&xdr, &status);
1752 if (unlikely(error))
1753 goto out;
1754 error = decode_post_op_attr(&xdr, result->fattr);
1755 if (unlikely(error))
1756 goto out;
1757 if (status != NFS3_OK)
1758 goto out_default;
1759 error = decode_uint32(&xdr, &result->access);
1760out:
1761 return error;
1762out_default:
1763 return nfs_stat_to_errno(status);
1764}
1765
1da177e4
LT
1766/*
1767 * Decode READLINK reply
1768 */
1769static int
d61005a6 1770nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
1771{
1772 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1773 struct kvec *iov = rcvbuf->head;
c957c526
CL
1774 size_t hdrlen;
1775 u32 len, recvd;
1da177e4
LT
1776 int status;
1777
1778 status = ntohl(*p++);
1779 p = xdr_decode_post_op_attr(p, fattr);
1780
1781 if (status != 0)
856dff3d 1782 return nfs_stat_to_errno(status);
1da177e4
LT
1783
1784 /* Convert length of symlink */
1785 len = ntohl(*p++);
c957c526 1786 if (len >= rcvbuf->page_len) {
fe82a183 1787 dprintk("nfs: server returned giant symlink!\n");
1da177e4
LT
1788 return -ENAMETOOLONG;
1789 }
1790
1791 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1792 if (iov->iov_len < hdrlen) {
fe82a183 1793 dprintk("NFS: READLINK reply header overflowed:"
c957c526 1794 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1795 return -errno_NFSERR_IO;
1796 } else if (iov->iov_len != hdrlen) {
fe82a183
CL
1797 dprintk("NFS: READLINK header is short. "
1798 "iovec will be shifted.\n");
1da177e4
LT
1799 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1800 }
1801 recvd = req->rq_rcv_buf.len - hdrlen;
1802 if (recvd < len) {
fe82a183 1803 dprintk("NFS: server cheating in readlink reply: "
1da177e4
LT
1804 "count %u > recvd %u\n", len, recvd);
1805 return -EIO;
1806 }
1807
b4687da7 1808 xdr_terminate_string(rcvbuf, len);
1da177e4
LT
1809 return 0;
1810}
1811
e4f93234
CL
1812/*
1813 * 3.3.5 READLINK3res
1814 *
1815 * struct READLINK3resok {
1816 * post_op_attr symlink_attributes;
1817 * nfspath3 data;
1818 * };
1819 *
1820 * struct READLINK3resfail {
1821 * post_op_attr symlink_attributes;
1822 * };
1823 *
1824 * union READLINK3res switch (nfsstat3 status) {
1825 * case NFS3_OK:
1826 * READLINK3resok resok;
1827 * default:
1828 * READLINK3resfail resfail;
1829 * };
1830 */
1831static int nfs3_xdr_dec_readlink3res(struct rpc_rqst *req, __be32 *p,
1832 struct nfs_fattr *result)
1833{
1834 struct xdr_stream xdr;
1835 enum nfs_stat status;
1836 int error;
1837
1838 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1839 error = decode_nfsstat3(&xdr, &status);
1840 if (unlikely(error))
1841 goto out;
1842 error = decode_post_op_attr(&xdr, result);
1843 if (unlikely(error))
1844 goto out;
1845 if (status != NFS3_OK)
1846 goto out_default;
1847 error = decode_nfspath3(&xdr);
1848out:
1849 return error;
1850out_default:
1851 return nfs_stat_to_errno(status);
1852}
1853
1da177e4
LT
1854/*
1855 * Decode READ reply
1856 */
1857static int
d61005a6 1858nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1da177e4
LT
1859{
1860 struct kvec *iov = req->rq_rcv_buf.head;
c957c526
CL
1861 size_t hdrlen;
1862 u32 count, ocount, recvd;
1863 int status;
1da177e4
LT
1864
1865 status = ntohl(*p++);
1866 p = xdr_decode_post_op_attr(p, res->fattr);
1867
1868 if (status != 0)
856dff3d 1869 return nfs_stat_to_errno(status);
1da177e4 1870
c957c526 1871 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1da177e4
LT
1872 * in that it puts the count both in the res struct and in the
1873 * opaque data count. */
1874 count = ntohl(*p++);
1875 res->eof = ntohl(*p++);
1876 ocount = ntohl(*p++);
1877
1878 if (ocount != count) {
fe82a183 1879 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1da177e4
LT
1880 return -errno_NFSERR_IO;
1881 }
1882
1883 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1884 if (iov->iov_len < hdrlen) {
fe82a183 1885 dprintk("NFS: READ reply header overflowed:"
c957c526 1886 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1887 return -errno_NFSERR_IO;
1888 } else if (iov->iov_len != hdrlen) {
1889 dprintk("NFS: READ header is short. iovec will be shifted.\n");
1890 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
1891 }
1892
1893 recvd = req->rq_rcv_buf.len - hdrlen;
1894 if (count > recvd) {
fe82a183 1895 dprintk("NFS: server cheating in read reply: "
c957c526 1896 "count %u > recvd %u\n", count, recvd);
1da177e4
LT
1897 count = recvd;
1898 res->eof = 0;
1899 }
1900
1901 if (count < res->count)
1902 res->count = count;
1903
1904 return count;
1905}
1906
e4f93234
CL
1907/*
1908 * 3.3.6 READ3res
1909 *
1910 * struct READ3resok {
1911 * post_op_attr file_attributes;
1912 * count3 count;
1913 * bool eof;
1914 * opaque data<>;
1915 * };
1916 *
1917 * struct READ3resfail {
1918 * post_op_attr file_attributes;
1919 * };
1920 *
1921 * union READ3res switch (nfsstat3 status) {
1922 * case NFS3_OK:
1923 * READ3resok resok;
1924 * default:
1925 * READ3resfail resfail;
1926 * };
1927 */
1928static int decode_read3resok(struct xdr_stream *xdr,
1929 struct nfs_readres *result)
1930{
1931 u32 eof, count, ocount, recvd;
1932 size_t hdrlen;
1933 __be32 *p;
1934
1935 p = xdr_inline_decode(xdr, 4 + 4 + 4);
1936 if (unlikely(p == NULL))
1937 goto out_overflow;
1938 count = be32_to_cpup(p++);
1939 eof = be32_to_cpup(p++);
1940 ocount = be32_to_cpup(p++);
1941 if (unlikely(ocount != count))
1942 goto out_mismatch;
1943 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
1944 recvd = xdr->buf->len - hdrlen;
1945 if (unlikely(count > recvd))
1946 goto out_cheating;
1947
1948out:
1949 xdr_read_pages(xdr, count);
1950 result->eof = eof;
1951 result->count = count;
1952 return count;
1953out_mismatch:
1954 dprintk("NFS: READ count doesn't match length of opaque: "
1955 "count %u != ocount %u\n", count, ocount);
1956 return -EIO;
1957out_cheating:
1958 dprintk("NFS: server cheating in read result: "
1959 "count %u > recvd %u\n", count, recvd);
1960 count = recvd;
1961 eof = 0;
1962 goto out;
1963out_overflow:
1964 print_overflow_msg(__func__, xdr);
1965 return -EIO;
1966}
1967
1968static int nfs3_xdr_dec_read3res(struct rpc_rqst *req, __be32 *p,
1969 struct nfs_readres *result)
1970{
1971 struct xdr_stream xdr;
1972 enum nfs_stat status;
1973 int error;
1974
1975 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
1976 error = decode_nfsstat3(&xdr, &status);
1977 if (unlikely(error))
1978 goto out;
1979 error = decode_post_op_attr(&xdr, result->fattr);
1980 if (unlikely(error))
1981 goto out;
1982 if (status != NFS3_OK)
1983 goto out_status;
1984 error = decode_read3resok(&xdr, result);
1985out:
1986 return error;
1987out_status:
1988 return nfs_stat_to_errno(status);
1989}
1990
1da177e4
LT
1991/*
1992 * Decode WRITE response
1993 */
1994static int
d61005a6 1995nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
1996{
1997 int status;
1998
1999 status = ntohl(*p++);
2000 p = xdr_decode_wcc_data(p, res->fattr);
2001
2002 if (status != 0)
856dff3d 2003 return nfs_stat_to_errno(status);
1da177e4
LT
2004
2005 res->count = ntohl(*p++);
2006 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
2007 res->verf->verifier[0] = *p++;
2008 res->verf->verifier[1] = *p++;
2009
2010 return res->count;
2011}
2012
e4f93234
CL
2013/*
2014 * 3.3.7 WRITE3res
2015 *
2016 * enum stable_how {
2017 * UNSTABLE = 0,
2018 * DATA_SYNC = 1,
2019 * FILE_SYNC = 2
2020 * };
2021 *
2022 * struct WRITE3resok {
2023 * wcc_data file_wcc;
2024 * count3 count;
2025 * stable_how committed;
2026 * writeverf3 verf;
2027 * };
2028 *
2029 * struct WRITE3resfail {
2030 * wcc_data file_wcc;
2031 * };
2032 *
2033 * union WRITE3res switch (nfsstat3 status) {
2034 * case NFS3_OK:
2035 * WRITE3resok resok;
2036 * default:
2037 * WRITE3resfail resfail;
2038 * };
2039 */
2040static int decode_write3resok(struct xdr_stream *xdr,
2041 struct nfs_writeres *result)
2042{
2043 __be32 *p;
2044
2045 p = xdr_inline_decode(xdr, 4 + 4 + NFS3_WRITEVERFSIZE);
2046 if (unlikely(p == NULL))
2047 goto out_overflow;
2048 result->count = be32_to_cpup(p++);
2049 result->verf->committed = be32_to_cpup(p++);
2050 if (unlikely(result->verf->committed > NFS_FILE_SYNC))
2051 goto out_badvalue;
2052 memcpy(result->verf->verifier, p, NFS3_WRITEVERFSIZE);
2053 return result->count;
2054out_badvalue:
2055 dprintk("NFS: bad stable_how value: %u\n", result->verf->committed);
2056 return -EIO;
2057out_overflow:
2058 print_overflow_msg(__func__, xdr);
2059 return -EIO;
2060}
2061
2062static int nfs3_xdr_dec_write3res(struct rpc_rqst *req, __be32 *p,
2063 struct nfs_writeres *result)
2064{
2065 struct xdr_stream xdr;
2066 enum nfs_stat status;
2067 int error;
2068
2069 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2070 error = decode_nfsstat3(&xdr, &status);
2071 if (unlikely(error))
2072 goto out;
2073 error = decode_wcc_data(&xdr, result->fattr);
2074 if (unlikely(error))
2075 goto out;
2076 if (status != NFS3_OK)
2077 goto out_status;
2078 error = decode_write3resok(&xdr, result);
2079out:
2080 return error;
2081out_status:
2082 return nfs_stat_to_errno(status);
2083}
2084
1da177e4
LT
2085/*
2086 * Decode a CREATE response
2087 */
2088static int
d61005a6 2089nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
2090{
2091 int status;
2092
2093 status = ntohl(*p++);
2094 if (status == 0) {
2095 if (*p++) {
2096 if (!(p = xdr_decode_fhandle(p, res->fh)))
2097 return -errno_NFSERR_IO;
2098 p = xdr_decode_post_op_attr(p, res->fattr);
2099 } else {
2100 memset(res->fh, 0, sizeof(*res->fh));
2101 /* Do decode post_op_attr but set it to NULL */
2102 p = xdr_decode_post_op_attr(p, res->fattr);
2103 res->fattr->valid = 0;
2104 }
2105 } else {
856dff3d 2106 status = nfs_stat_to_errno(status);
1da177e4
LT
2107 }
2108 p = xdr_decode_wcc_data(p, res->dir_attr);
2109 return status;
2110}
2111
e4f93234
CL
2112/*
2113 * 3.3.8 CREATE3res
2114 *
2115 * struct CREATE3resok {
2116 * post_op_fh3 obj;
2117 * post_op_attr obj_attributes;
2118 * wcc_data dir_wcc;
2119 * };
2120 *
2121 * struct CREATE3resfail {
2122 * wcc_data dir_wcc;
2123 * };
2124 *
2125 * union CREATE3res switch (nfsstat3 status) {
2126 * case NFS3_OK:
2127 * CREATE3resok resok;
2128 * default:
2129 * CREATE3resfail resfail;
2130 * };
2131 */
2132static int decode_create3resok(struct xdr_stream *xdr,
2133 struct nfs3_diropres *result)
2134{
2135 int error;
2136
2137 error = decode_post_op_fh3(xdr, result->fh);
2138 if (unlikely(error))
2139 goto out;
2140 error = decode_post_op_attr(xdr, result->fattr);
2141 if (unlikely(error))
2142 goto out;
2143 /* The server isn't required to return a file handle.
2144 * If it didn't, force the client to perform a LOOKUP
2145 * to determine the correct file handle and attribute
2146 * values for the new object. */
2147 if (result->fh->size == 0)
2148 result->fattr->valid = 0;
2149 error = decode_wcc_data(xdr, result->dir_attr);
2150out:
2151 return error;
2152}
2153
2154static int nfs3_xdr_dec_create3res(struct rpc_rqst *req, __be32 *p,
2155 struct nfs3_diropres *result)
2156{
2157 struct xdr_stream xdr;
2158 enum nfs_stat status;
2159 int error;
2160
2161 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2162 error = decode_nfsstat3(&xdr, &status);
2163 if (unlikely(error))
2164 goto out;
2165 if (status != NFS3_OK)
2166 goto out_default;
2167 error = decode_create3resok(&xdr, result);
2168out:
2169 return error;
2170out_default:
2171 error = decode_wcc_data(&xdr, result->dir_attr);
2172 if (unlikely(error))
2173 goto out;
2174 return nfs_stat_to_errno(status);
2175}
2176
2177/*
2178 * 3.3.12 REMOVE3res
2179 *
2180 * struct REMOVE3resok {
2181 * wcc_data dir_wcc;
2182 * };
2183 *
2184 * struct REMOVE3resfail {
2185 * wcc_data dir_wcc;
2186 * };
2187 *
2188 * union REMOVE3res switch (nfsstat3 status) {
2189 * case NFS3_OK:
2190 * REMOVE3resok resok;
2191 * default:
2192 * REMOVE3resfail resfail;
2193 * };
2194 */
2195static int nfs3_xdr_dec_remove3res(struct rpc_rqst *req, __be32 *p,
2196 struct nfs_removeres *result)
2197{
2198 struct xdr_stream xdr;
2199 enum nfs_stat status;
2200 int error;
2201
2202 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2203 error = decode_nfsstat3(&xdr, &status);
2204 if (unlikely(error))
2205 goto out;
2206 error = decode_wcc_data(&xdr, result->dir_attr);
2207 if (unlikely(error))
2208 goto out;
2209 if (status != NFS3_OK)
2210 goto out_status;
2211out:
2212 return error;
2213out_status:
2214 return nfs_stat_to_errno(status);
2215}
2216
1da177e4
LT
2217/*
2218 * Decode RENAME reply
2219 */
2220static int
e8582a8b 2221nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
1da177e4
LT
2222{
2223 int status;
2224
2225 if ((status = ntohl(*p++)) != 0)
856dff3d 2226 status = nfs_stat_to_errno(status);
e8582a8b
JL
2227 p = xdr_decode_wcc_data(p, res->old_fattr);
2228 p = xdr_decode_wcc_data(p, res->new_fattr);
1da177e4
LT
2229 return status;
2230}
2231
e4f93234
CL
2232/*
2233 * 3.3.14 RENAME3res
2234 *
2235 * struct RENAME3resok {
2236 * wcc_data fromdir_wcc;
2237 * wcc_data todir_wcc;
2238 * };
2239 *
2240 * struct RENAME3resfail {
2241 * wcc_data fromdir_wcc;
2242 * wcc_data todir_wcc;
2243 * };
2244 *
2245 * union RENAME3res switch (nfsstat3 status) {
2246 * case NFS3_OK:
2247 * RENAME3resok resok;
2248 * default:
2249 * RENAME3resfail resfail;
2250 * };
2251 */
2252static int nfs3_xdr_dec_rename3res(struct rpc_rqst *req, __be32 *p,
2253 struct nfs_renameres *result)
2254{
2255 struct xdr_stream xdr;
2256 enum nfs_stat status;
2257 int error;
2258
2259 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2260 error = decode_nfsstat3(&xdr, &status);
2261 if (unlikely(error))
2262 goto out;
2263 error = decode_wcc_data(&xdr, result->old_fattr);
2264 if (unlikely(error))
2265 goto out;
2266 error = decode_wcc_data(&xdr, result->new_fattr);
2267 if (unlikely(error))
2268 goto out;
2269 if (status != NFS3_OK)
2270 goto out_status;
2271out:
2272 return error;
2273out_status:
2274 return nfs_stat_to_errno(status);
2275}
2276
1da177e4
LT
2277/*
2278 * Decode LINK reply
2279 */
2280static int
d61005a6 2281nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1da177e4
LT
2282{
2283 int status;
2284
2285 if ((status = ntohl(*p++)) != 0)
856dff3d 2286 status = nfs_stat_to_errno(status);
1da177e4
LT
2287 p = xdr_decode_post_op_attr(p, res->fattr);
2288 p = xdr_decode_wcc_data(p, res->dir_attr);
2289 return status;
2290}
2291
e4f93234
CL
2292/*
2293 * 3.3.15 LINK3res
2294 *
2295 * struct LINK3resok {
2296 * post_op_attr file_attributes;
2297 * wcc_data linkdir_wcc;
2298 * };
2299 *
2300 * struct LINK3resfail {
2301 * post_op_attr file_attributes;
2302 * wcc_data linkdir_wcc;
2303 * };
2304 *
2305 * union LINK3res switch (nfsstat3 status) {
2306 * case NFS3_OK:
2307 * LINK3resok resok;
2308 * default:
2309 * LINK3resfail resfail;
2310 * };
2311 */
2312static int nfs3_xdr_dec_link3res(struct rpc_rqst *req, __be32 *p,
2313 struct nfs3_linkres *result)
2314{
2315 struct xdr_stream xdr;
2316 enum nfs_stat status;
2317 int error;
2318
2319 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2320 error = decode_nfsstat3(&xdr, &status);
2321 if (unlikely(error))
2322 goto out;
2323 error = decode_post_op_attr(&xdr, result->fattr);
2324 if (unlikely(error))
2325 goto out;
2326 error = decode_wcc_data(&xdr, result->dir_attr);
2327 if (unlikely(error))
2328 goto out;
2329 if (status != NFS3_OK)
2330 goto out_status;
2331out:
2332 return error;
2333out_status:
2334 return nfs_stat_to_errno(status);
2335}
2336
2337/**
2338 * nfs3_decode_dirent - Decode a single NFSv3 directory entry stored in
2339 * the local page cache
2340 * @xdr: XDR stream where entry resides
2341 * @entry: buffer to fill in with entry data
2342 * @server: nfs_server data for this directory
2343 * @plus: boolean indicating whether this should be a readdirplus entry
2344 *
2345 * Returns the position of the next item in the buffer, or an ERR_PTR.
2346 *
2347 * This function is not invoked during READDIR reply decoding, but
2348 * rather whenever an application invokes the getdents(2) system call
2349 * on a directory already in our cache.
2350 *
2351 * 3.3.16 entry3
2352 *
2353 * struct entry3 {
2354 * fileid3 fileid;
2355 * filename3 name;
2356 * cookie3 cookie;
2357 * fhandle3 filehandle;
2358 * post_op_attr3 attributes;
2359 * entry3 *nextentry;
2360 * };
2361 *
2362 * 3.3.17 entryplus3
2363 * struct entryplus3 {
2364 * fileid3 fileid;
2365 * filename3 name;
2366 * cookie3 cookie;
2367 * post_op_attr name_attributes;
2368 * post_op_fh3 name_handle;
2369 * entryplus3 *nextentry;
2370 * };
2371 */
2372__be32 *nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry,
2373 struct nfs_server *server, int plus)
2374{
2375 struct nfs_entry old = *entry;
2376 __be32 *p;
2377 int error;
2378
2379 p = xdr_inline_decode(xdr, 4);
2380 if (unlikely(p == NULL))
2381 goto out_overflow;
2382 if (*p == xdr_zero) {
2383 p = xdr_inline_decode(xdr, 4);
2384 if (unlikely(p == NULL))
2385 goto out_overflow;
2386 if (*p == xdr_zero)
2387 return ERR_PTR(-EAGAIN);
2388 entry->eof = 1;
2389 return ERR_PTR(-EBADCOOKIE);
2390 }
2391
2392 error = decode_fileid3(xdr, &entry->ino);
2393 if (unlikely(error))
2394 return ERR_PTR(error);
2395
2396 error = decode_inline_filename3(xdr, &entry->name, &entry->len);
2397 if (unlikely(error))
2398 return ERR_PTR(error);
2399
2400 entry->prev_cookie = entry->cookie;
2401 error = decode_cookie3(xdr, &entry->cookie);
2402 if (unlikely(error))
2403 return ERR_PTR(error);
2404
2405 entry->d_type = DT_UNKNOWN;
2406
2407 if (plus) {
2408 entry->fattr->valid = 0;
2409 error = decode_post_op_attr(xdr, entry->fattr);
2410 if (unlikely(error))
2411 return ERR_PTR(error);
2412 if (entry->fattr->valid & NFS_ATTR_FATTR_V3)
2413 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
2414
2415 /* In fact, a post_op_fh3: */
2416 p = xdr_inline_decode(xdr, 4);
2417 if (unlikely(p == NULL))
2418 goto out_overflow;
2419 if (*p != xdr_zero) {
2420 error = decode_nfs_fh3(xdr, entry->fh);
2421 if (unlikely(error)) {
2422 if (error == -E2BIG)
2423 goto out_truncated;
2424 return ERR_PTR(error);
2425 }
2426 } else
2427 zero_nfs_fh3(entry->fh);
2428 }
2429
2430 /* Peek at the next entry to see if we're at EOD */
2431 p = xdr_inline_peek(xdr, 4 + 4);
2432 entry->eof = 0;
2433 if (p != NULL)
2434 entry->eof = (p[0] == xdr_zero) && (p[1] != xdr_zero);
2435 return p;
2436
2437out_overflow:
2438 print_overflow_msg(__func__, xdr);
2439 return ERR_PTR(-EAGAIN);
2440out_truncated:
2441 dprintk("NFS: directory entry contains invalid file handle\n");
2442 *entry = old;
2443 return ERR_PTR(-EAGAIN);
2444}
2445
2446/*
2447 * 3.3.16 READDIR3res
2448 *
2449 * struct dirlist3 {
2450 * entry3 *entries;
2451 * bool eof;
2452 * };
2453 *
2454 * struct READDIR3resok {
2455 * post_op_attr dir_attributes;
2456 * cookieverf3 cookieverf;
2457 * dirlist3 reply;
2458 * };
2459 *
2460 * struct READDIR3resfail {
2461 * post_op_attr dir_attributes;
2462 * };
2463 *
2464 * union READDIR3res switch (nfsstat3 status) {
2465 * case NFS3_OK:
2466 * READDIR3resok resok;
2467 * default:
2468 * READDIR3resfail resfail;
2469 * };
2470 *
2471 * Read the directory contents into the page cache, but otherwise
2472 * don't touch them. The actual decoding is done by nfs3_decode_entry()
2473 * during subsequent nfs_readdir() calls.
2474 */
2475static int decode_dirlist3(struct xdr_stream *xdr)
2476{
2477 u32 recvd, pglen;
2478 size_t hdrlen;
2479
2480 pglen = xdr->buf->page_len;
2481 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2482 recvd = xdr->buf->len - hdrlen;
2483 if (unlikely(pglen > recvd))
2484 goto out_cheating;
2485out:
2486 xdr_read_pages(xdr, pglen);
2487 return pglen;
2488out_cheating:
2489 dprintk("NFS: server cheating in readdir result: "
2490 "pglen %u > recvd %u\n", pglen, recvd);
2491 pglen = recvd;
2492 goto out;
2493}
2494
2495static int decode_readdir3resok(struct xdr_stream *xdr,
2496 struct nfs3_readdirres *result)
2497{
2498 int error;
2499
2500 error = decode_post_op_attr(xdr, result->dir_attr);
2501 if (unlikely(error))
2502 goto out;
2503 /* XXX: do we need to check if result->verf != NULL ? */
2504 error = decode_cookieverf3(xdr, result->verf);
2505 if (unlikely(error))
2506 goto out;
2507 error = decode_dirlist3(xdr);
2508out:
2509 return error;
2510}
2511
2512static int nfs3_xdr_dec_readdir3res(struct rpc_rqst *req, __be32 *p,
2513 struct nfs3_readdirres *result)
2514{
2515 struct xdr_stream xdr;
2516 enum nfs_stat status;
2517 int error;
2518
2519 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2520 error = decode_nfsstat3(&xdr, &status);
2521 if (unlikely(error))
2522 goto out;
2523 if (status != NFS3_OK)
2524 goto out_default;
2525 error = decode_readdir3resok(&xdr, result);
2526out:
2527 return error;
2528out_default:
2529 error = decode_post_op_attr(&xdr, result->dir_attr);
2530 if (unlikely(error))
2531 goto out;
2532 return nfs_stat_to_errno(status);
2533}
2534
1da177e4
LT
2535/*
2536 * Decode FSSTAT reply
2537 */
2538static int
d61005a6 2539nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1da177e4
LT
2540{
2541 int status;
2542
2543 status = ntohl(*p++);
2544
2545 p = xdr_decode_post_op_attr(p, res->fattr);
2546 if (status != 0)
856dff3d 2547 return nfs_stat_to_errno(status);
1da177e4
LT
2548
2549 p = xdr_decode_hyper(p, &res->tbytes);
2550 p = xdr_decode_hyper(p, &res->fbytes);
2551 p = xdr_decode_hyper(p, &res->abytes);
2552 p = xdr_decode_hyper(p, &res->tfiles);
2553 p = xdr_decode_hyper(p, &res->ffiles);
2554 p = xdr_decode_hyper(p, &res->afiles);
2555
2556 /* ignore invarsec */
2557 return 0;
2558}
2559
e4f93234
CL
2560/*
2561 * 3.3.18 FSSTAT3res
2562 *
2563 * struct FSSTAT3resok {
2564 * post_op_attr obj_attributes;
2565 * size3 tbytes;
2566 * size3 fbytes;
2567 * size3 abytes;
2568 * size3 tfiles;
2569 * size3 ffiles;
2570 * size3 afiles;
2571 * uint32 invarsec;
2572 * };
2573 *
2574 * struct FSSTAT3resfail {
2575 * post_op_attr obj_attributes;
2576 * };
2577 *
2578 * union FSSTAT3res switch (nfsstat3 status) {
2579 * case NFS3_OK:
2580 * FSSTAT3resok resok;
2581 * default:
2582 * FSSTAT3resfail resfail;
2583 * };
2584 */
2585static int decode_fsstat3resok(struct xdr_stream *xdr,
2586 struct nfs_fsstat *result)
2587{
2588 __be32 *p;
2589
2590 p = xdr_inline_decode(xdr, 8 * 6 + 4);
2591 if (unlikely(p == NULL))
2592 goto out_overflow;
2593 p = xdr_decode_size3(p, &result->tbytes);
2594 p = xdr_decode_size3(p, &result->fbytes);
2595 p = xdr_decode_size3(p, &result->abytes);
2596 p = xdr_decode_size3(p, &result->tfiles);
2597 p = xdr_decode_size3(p, &result->ffiles);
2598 xdr_decode_size3(p, &result->afiles);
2599 /* ignore invarsec */
2600 return 0;
2601out_overflow:
2602 print_overflow_msg(__func__, xdr);
2603 return -EIO;
2604}
2605
2606static int nfs3_xdr_dec_fsstat3res(struct rpc_rqst *req, __be32 *p,
2607 struct nfs_fsstat *result)
2608{
2609 struct xdr_stream xdr;
2610 enum nfs_stat status;
2611 int error;
2612
2613 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2614 error = decode_nfsstat3(&xdr, &status);
2615 if (unlikely(error))
2616 goto out;
2617 error = decode_post_op_attr(&xdr, result->fattr);
2618 if (unlikely(error))
2619 goto out;
2620 if (status != NFS3_OK)
2621 goto out_status;
2622 error = decode_fsstat3resok(&xdr, result);
2623out:
2624 return error;
2625out_status:
2626 return nfs_stat_to_errno(status);
2627}
2628
1da177e4
LT
2629/*
2630 * Decode FSINFO reply
2631 */
2632static int
d61005a6 2633nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1da177e4
LT
2634{
2635 int status;
2636
2637 status = ntohl(*p++);
2638
2639 p = xdr_decode_post_op_attr(p, res->fattr);
2640 if (status != 0)
856dff3d 2641 return nfs_stat_to_errno(status);
1da177e4
LT
2642
2643 res->rtmax = ntohl(*p++);
2644 res->rtpref = ntohl(*p++);
2645 res->rtmult = ntohl(*p++);
2646 res->wtmax = ntohl(*p++);
2647 res->wtpref = ntohl(*p++);
2648 res->wtmult = ntohl(*p++);
2649 res->dtpref = ntohl(*p++);
2650 p = xdr_decode_hyper(p, &res->maxfilesize);
6b96724e 2651 p = xdr_decode_time3(p, &res->time_delta);
1da177e4 2652
6b96724e 2653 /* ignore properties */
1da177e4
LT
2654 res->lease_time = 0;
2655 return 0;
2656}
2657
e4f93234
CL
2658/*
2659 * 3.3.19 FSINFO3res
2660 *
2661 * struct FSINFO3resok {
2662 * post_op_attr obj_attributes;
2663 * uint32 rtmax;
2664 * uint32 rtpref;
2665 * uint32 rtmult;
2666 * uint32 wtmax;
2667 * uint32 wtpref;
2668 * uint32 wtmult;
2669 * uint32 dtpref;
2670 * size3 maxfilesize;
2671 * nfstime3 time_delta;
2672 * uint32 properties;
2673 * };
2674 *
2675 * struct FSINFO3resfail {
2676 * post_op_attr obj_attributes;
2677 * };
2678 *
2679 * union FSINFO3res switch (nfsstat3 status) {
2680 * case NFS3_OK:
2681 * FSINFO3resok resok;
2682 * default:
2683 * FSINFO3resfail resfail;
2684 * };
2685 */
2686static int decode_fsinfo3resok(struct xdr_stream *xdr,
2687 struct nfs_fsinfo *result)
2688{
2689 __be32 *p;
2690
2691 p = xdr_inline_decode(xdr, 4 * 7 + 8 + 8 + 4);
2692 if (unlikely(p == NULL))
2693 goto out_overflow;
2694 result->rtmax = be32_to_cpup(p++);
2695 result->rtpref = be32_to_cpup(p++);
2696 result->rtmult = be32_to_cpup(p++);
2697 result->wtmax = be32_to_cpup(p++);
2698 result->wtpref = be32_to_cpup(p++);
2699 result->wtmult = be32_to_cpup(p++);
2700 result->dtpref = be32_to_cpup(p++);
2701 p = xdr_decode_size3(p, &result->maxfilesize);
2702 xdr_decode_time3(p, &result->time_delta);
2703
2704 /* ignore properties */
2705 result->lease_time = 0;
2706 return 0;
2707out_overflow:
2708 print_overflow_msg(__func__, xdr);
2709 return -EIO;
2710}
2711
2712static int nfs3_xdr_dec_fsinfo3res(struct rpc_rqst *req, __be32 *p,
2713 struct nfs_fsinfo *result)
2714{
2715 struct xdr_stream xdr;
2716 enum nfs_stat status;
2717 int error;
2718
2719 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2720 error = decode_nfsstat3(&xdr, &status);
2721 if (unlikely(error))
2722 goto out;
2723 error = decode_post_op_attr(&xdr, result->fattr);
2724 if (unlikely(error))
2725 goto out;
2726 if (status != NFS3_OK)
2727 goto out_status;
2728 error = decode_fsinfo3resok(&xdr, result);
2729out:
2730 return error;
2731out_status:
2732 return nfs_stat_to_errno(status);
2733}
2734
1da177e4
LT
2735/*
2736 * Decode PATHCONF reply
2737 */
2738static int
d61005a6 2739nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1da177e4
LT
2740{
2741 int status;
2742
2743 status = ntohl(*p++);
2744
2745 p = xdr_decode_post_op_attr(p, res->fattr);
2746 if (status != 0)
856dff3d 2747 return nfs_stat_to_errno(status);
1da177e4
LT
2748 res->max_link = ntohl(*p++);
2749 res->max_namelen = ntohl(*p++);
2750
2751 /* ignore remaining fields */
2752 return 0;
2753}
2754
e4f93234
CL
2755/*
2756 * 3.3.20 PATHCONF3res
2757 *
2758 * struct PATHCONF3resok {
2759 * post_op_attr obj_attributes;
2760 * uint32 linkmax;
2761 * uint32 name_max;
2762 * bool no_trunc;
2763 * bool chown_restricted;
2764 * bool case_insensitive;
2765 * bool case_preserving;
2766 * };
2767 *
2768 * struct PATHCONF3resfail {
2769 * post_op_attr obj_attributes;
2770 * };
2771 *
2772 * union PATHCONF3res switch (nfsstat3 status) {
2773 * case NFS3_OK:
2774 * PATHCONF3resok resok;
2775 * default:
2776 * PATHCONF3resfail resfail;
2777 * };
2778 */
2779static int decode_pathconf3resok(struct xdr_stream *xdr,
2780 struct nfs_pathconf *result)
2781{
2782 __be32 *p;
2783
2784 p = xdr_inline_decode(xdr, 4 * 6);
2785 if (unlikely(p == NULL))
2786 goto out_overflow;
2787 result->max_link = be32_to_cpup(p++);
2788 result->max_namelen = be32_to_cpup(p);
2789 /* ignore remaining fields */
2790 return 0;
2791out_overflow:
2792 print_overflow_msg(__func__, xdr);
2793 return -EIO;
2794}
2795
2796static int nfs3_xdr_dec_pathconf3res(struct rpc_rqst *req, __be32 *p,
2797 struct nfs_pathconf *result)
2798{
2799 struct xdr_stream xdr;
2800 enum nfs_stat status;
2801 int error;
2802
2803 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2804 error = decode_nfsstat3(&xdr, &status);
2805 if (unlikely(error))
2806 goto out;
2807 error = decode_post_op_attr(&xdr, result->fattr);
2808 if (unlikely(error))
2809 goto out;
2810 if (status != NFS3_OK)
2811 goto out_status;
2812 error = decode_pathconf3resok(&xdr, result);
2813out:
2814 return error;
2815out_status:
2816 return nfs_stat_to_errno(status);
2817}
2818
1da177e4
LT
2819/*
2820 * Decode COMMIT reply
2821 */
2822static int
d61005a6 2823nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
2824{
2825 int status;
2826
2827 status = ntohl(*p++);
2828 p = xdr_decode_wcc_data(p, res->fattr);
2829 if (status != 0)
856dff3d 2830 return nfs_stat_to_errno(status);
1da177e4
LT
2831
2832 res->verf->verifier[0] = *p++;
2833 res->verf->verifier[1] = *p++;
2834 return 0;
2835}
2836
e4f93234
CL
2837/*
2838 * 3.3.21 COMMIT3res
2839 *
2840 * struct COMMIT3resok {
2841 * wcc_data file_wcc;
2842 * writeverf3 verf;
2843 * };
2844 *
2845 * struct COMMIT3resfail {
2846 * wcc_data file_wcc;
2847 * };
2848 *
2849 * union COMMIT3res switch (nfsstat3 status) {
2850 * case NFS3_OK:
2851 * COMMIT3resok resok;
2852 * default:
2853 * COMMIT3resfail resfail;
2854 * };
2855 */
2856static int nfs3_xdr_dec_commit3res(struct rpc_rqst *req, __be32 *p,
2857 struct nfs_writeres *result)
2858{
2859 struct xdr_stream xdr;
2860 enum nfs_stat status;
2861 int error;
2862
2863 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2864 error = decode_nfsstat3(&xdr, &status);
2865 if (unlikely(error))
2866 goto out;
2867 error = decode_wcc_data(&xdr, result->fattr);
2868 if (unlikely(error))
2869 goto out;
2870 if (status != NFS3_OK)
2871 goto out_status;
2872 error = decode_writeverf3(&xdr, result->verf->verifier);
2873out:
2874 return error;
2875out_status:
2876 return nfs_stat_to_errno(status);
2877}
2878
b7fa0554
AG
2879#ifdef CONFIG_NFS_V3_ACL
2880/*
2881 * Decode GETACL reply
2882 */
2883static int
d61005a6 2884nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
2885 struct nfs3_getaclres *res)
2886{
2887 struct xdr_buf *buf = &req->rq_rcv_buf;
2888 int status = ntohl(*p++);
2889 struct posix_acl **acl;
2890 unsigned int *aclcnt;
2891 int err, base;
2892
2893 if (status != 0)
856dff3d 2894 return nfs_stat_to_errno(status);
b7fa0554
AG
2895 p = xdr_decode_post_op_attr(p, res->fattr);
2896 res->mask = ntohl(*p++);
2897 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2898 return -EINVAL;
2899 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
2900
2901 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
2902 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
2903 err = nfsacl_decode(buf, base, aclcnt, acl);
2904
2905 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
2906 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
2907 if (err > 0)
2908 err = nfsacl_decode(buf, base + err, aclcnt, acl);
2909 return (err > 0) ? 0 : err;
2910}
2911
e4f93234
CL
2912static inline int decode_getacl3resok(struct xdr_stream *xdr,
2913 struct nfs3_getaclres *result)
2914{
2915 struct posix_acl **acl;
2916 unsigned int *aclcnt;
2917 size_t hdrlen;
2918 int error;
2919
2920 error = decode_post_op_attr(xdr, result->fattr);
2921 if (unlikely(error))
2922 goto out;
2923 error = decode_uint32(xdr, &result->mask);
2924 if (unlikely(error))
2925 goto out;
2926 error = -EINVAL;
2927 if (result->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
2928 goto out;
2929
2930 hdrlen = (u8 *)xdr->p - (u8 *)xdr->iov->iov_base;
2931
2932 acl = NULL;
2933 if (result->mask & NFS_ACL)
2934 acl = &result->acl_access;
2935 aclcnt = NULL;
2936 if (result->mask & NFS_ACLCNT)
2937 aclcnt = &result->acl_access_count;
2938 error = nfsacl_decode(xdr->buf, hdrlen, aclcnt, acl);
2939 if (unlikely(error <= 0))
2940 goto out;
2941
2942 acl = NULL;
2943 if (result->mask & NFS_DFACL)
2944 acl = &result->acl_default;
2945 aclcnt = NULL;
2946 if (result->mask & NFS_DFACLCNT)
2947 aclcnt = &result->acl_default_count;
2948 error = nfsacl_decode(xdr->buf, hdrlen + error, aclcnt, acl);
2949 if (unlikely(error <= 0))
2950 return error;
2951 error = 0;
2952out:
2953 return error;
2954}
2955
2956static int nfs3_xdr_dec_getacl3res(struct rpc_rqst *req, __be32 *p,
2957 struct nfs3_getaclres *result)
2958{
2959 struct xdr_stream xdr;
2960 enum nfs_stat status;
2961 int error;
2962
2963 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2964 error = decode_nfsstat3(&xdr, &status);
2965 if (unlikely(error))
2966 goto out;
2967 if (status != NFS3_OK)
2968 goto out_default;
2969 error = decode_getacl3resok(&xdr, result);
2970out:
2971 return error;
2972out_default:
2973 return nfs_stat_to_errno(status);
2974}
2975
b7fa0554
AG
2976/*
2977 * Decode setacl reply.
2978 */
2979static int
d61005a6 2980nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
b7fa0554
AG
2981{
2982 int status = ntohl(*p++);
2983
2984 if (status)
856dff3d 2985 return nfs_stat_to_errno(status);
b7fa0554
AG
2986 xdr_decode_post_op_attr(p, fattr);
2987 return 0;
2988}
e4f93234
CL
2989
2990static int nfs3_xdr_dec_setacl3res(struct rpc_rqst *req, __be32 *p,
2991 struct nfs_fattr *result)
2992{
2993 struct xdr_stream xdr;
2994 enum nfs_stat status;
2995 int error;
2996
2997 xdr_init_decode(&xdr, &req->rq_rcv_buf, p);
2998 error = decode_nfsstat3(&xdr, &status);
2999 if (unlikely(error))
3000 goto out;
3001 if (status != NFS3_OK)
3002 goto out_default;
3003 error = decode_post_op_attr(&xdr, result);
3004out:
3005 return error;
3006out_default:
3007 return nfs_stat_to_errno(status);
3008}
3009
b7fa0554
AG
3010#endif /* CONFIG_NFS_V3_ACL */
3011
1da177e4
LT
3012#define PROC(proc, argtype, restype, timer) \
3013[NFS3PROC_##proc] = { \
3014 .p_proc = NFS3PROC_##proc, \
ad96b5b5 3015 .p_encode = (kxdrproc_t)nfs3_xdr_enc_##argtype##3args, \
f5fc3c50 3016 .p_decode = (kxdrproc_t)nfs3_xdr_dec_##restype##3res, \
ad96b5b5 3017 .p_arglen = NFS3_##argtype##args_sz, \
f5fc3c50 3018 .p_replen = NFS3_##restype##res_sz, \
cc0175c1
CL
3019 .p_timer = timer, \
3020 .p_statidx = NFS3PROC_##proc, \
3021 .p_name = #proc, \
1da177e4
LT
3022 }
3023
3024struct rpc_procinfo nfs3_procedures[] = {
f5fc3c50
CL
3025 PROC(GETATTR, getattr, getattr, 1),
3026 PROC(SETATTR, setattr, setattr, 0),
3027 PROC(LOOKUP, lookup, lookup, 2),
3028 PROC(ACCESS, access, access, 1),
3029 PROC(READLINK, readlink, readlink, 3),
3030 PROC(READ, read, read, 3),
3031 PROC(WRITE, write, write, 4),
3032 PROC(CREATE, create, create, 0),
3033 PROC(MKDIR, mkdir, create, 0),
3034 PROC(SYMLINK, symlink, create, 0),
3035 PROC(MKNOD, mknod, create, 0),
3036 PROC(REMOVE, remove, remove, 0),
3037 PROC(RMDIR, lookup, setattr, 0),
3038 PROC(RENAME, rename, rename, 0),
3039 PROC(LINK, link, link, 0),
3040 PROC(READDIR, readdir, readdir, 3),
3041 PROC(READDIRPLUS, readdirplus, readdir, 3),
3042 PROC(FSSTAT, getattr, fsstat, 0),
3043 PROC(FSINFO, getattr, fsinfo, 0),
3044 PROC(PATHCONF, getattr, pathconf, 0),
3045 PROC(COMMIT, commit, commit, 5),
1da177e4
LT
3046};
3047
3048struct rpc_version nfs_version3 = {
3049 .number = 3,
e8c96f8c 3050 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1da177e4
LT
3051 .procs = nfs3_procedures
3052};
3053
b7fa0554
AG
3054#ifdef CONFIG_NFS_V3_ACL
3055static struct rpc_procinfo nfs3_acl_procedures[] = {
3056 [ACLPROC3_GETACL] = {
3057 .p_proc = ACLPROC3_GETACL,
ad96b5b5 3058 .p_encode = (kxdrproc_t)nfs3_xdr_enc_getacl3args,
f5fc3c50 3059 .p_decode = (kxdrproc_t)nfs3_xdr_dec_getacl3res,
2bea90d4
CL
3060 .p_arglen = ACL3_getaclargs_sz,
3061 .p_replen = ACL3_getaclres_sz,
b7fa0554 3062 .p_timer = 1,
cc0175c1 3063 .p_name = "GETACL",
b7fa0554
AG
3064 },
3065 [ACLPROC3_SETACL] = {
3066 .p_proc = ACLPROC3_SETACL,
ad96b5b5 3067 .p_encode = (kxdrproc_t)nfs3_xdr_enc_setacl3args,
f5fc3c50 3068 .p_decode = (kxdrproc_t)nfs3_xdr_dec_setacl3res,
2bea90d4
CL
3069 .p_arglen = ACL3_setaclargs_sz,
3070 .p_replen = ACL3_setaclres_sz,
b7fa0554 3071 .p_timer = 0,
cc0175c1 3072 .p_name = "SETACL",
b7fa0554
AG
3073 },
3074};
3075
3076struct rpc_version nfsacl_version3 = {
3077 .number = 3,
3078 .nrprocs = sizeof(nfs3_acl_procedures)/
3079 sizeof(nfs3_acl_procedures[0]),
3080 .procs = nfs3_acl_procedures,
3081};
3082#endif /* CONFIG_NFS_V3_ACL */