]> git.proxmox.com Git - mirror_ubuntu-focal-kernel.git/blame - fs/nfs/nfs3xdr.c
NFS: Introduce new-style XDR encoding functions for NFSv3
[mirror_ubuntu-focal-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)
1da177e4
LT
41#define NFS3_wcc_attr_sz (6)
42#define NFS3_pre_op_attr_sz (1+NFS3_wcc_attr_sz)
43#define NFS3_post_op_attr_sz (1+NFS3_fattr_sz)
44#define NFS3_wcc_data_sz (NFS3_pre_op_attr_sz+NFS3_post_op_attr_sz)
45#define NFS3_fsstat_sz
46#define NFS3_fsinfo_sz
47#define NFS3_pathconf_sz
48#define NFS3_entry_sz (NFS3_filename_sz+3)
49
50#define NFS3_sattrargs_sz (NFS3_fh_sz+NFS3_sattr_sz+3)
51#define NFS3_diropargs_sz (NFS3_fh_sz+NFS3_filename_sz)
4fdc17b2 52#define NFS3_removeargs_sz (NFS3_fh_sz+NFS3_filename_sz)
1da177e4
LT
53#define NFS3_accessargs_sz (NFS3_fh_sz+1)
54#define NFS3_readlinkargs_sz (NFS3_fh_sz)
55#define NFS3_readargs_sz (NFS3_fh_sz+3)
56#define NFS3_writeargs_sz (NFS3_fh_sz+5)
57#define NFS3_createargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
58#define NFS3_mkdirargs_sz (NFS3_diropargs_sz+NFS3_sattr_sz)
94a6d753 59#define NFS3_symlinkargs_sz (NFS3_diropargs_sz+1+NFS3_sattr_sz)
1da177e4
LT
60#define NFS3_mknodargs_sz (NFS3_diropargs_sz+2+NFS3_sattr_sz)
61#define NFS3_renameargs_sz (NFS3_diropargs_sz+NFS3_diropargs_sz)
62#define NFS3_linkargs_sz (NFS3_fh_sz+NFS3_diropargs_sz)
d9c407b1
CL
63#define NFS3_readdirargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+3)
64#define NFS3_readdirplusargs_sz (NFS3_fh_sz+NFS3_cookieverf_sz+4)
1da177e4
LT
65#define NFS3_commitargs_sz (NFS3_fh_sz+3)
66
67#define NFS3_attrstat_sz (1+NFS3_fattr_sz)
68#define NFS3_wccstat_sz (1+NFS3_wcc_data_sz)
4fdc17b2 69#define NFS3_removeres_sz (NFS3_wccstat_sz)
1da177e4
LT
70#define NFS3_lookupres_sz (1+NFS3_fh_sz+(2 * NFS3_post_op_attr_sz))
71#define NFS3_accessres_sz (1+NFS3_post_op_attr_sz+1)
72#define NFS3_readlinkres_sz (1+NFS3_post_op_attr_sz+1)
73#define NFS3_readres_sz (1+NFS3_post_op_attr_sz+3)
74#define NFS3_writeres_sz (1+NFS3_wcc_data_sz+4)
75#define NFS3_createres_sz (1+NFS3_fh_sz+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
76#define NFS3_renameres_sz (1+(2 * NFS3_wcc_data_sz))
77#define NFS3_linkres_sz (1+NFS3_post_op_attr_sz+NFS3_wcc_data_sz)
78#define NFS3_readdirres_sz (1+NFS3_post_op_attr_sz+2)
79#define NFS3_fsstatres_sz (1+NFS3_post_op_attr_sz+13)
80#define NFS3_fsinfores_sz (1+NFS3_post_op_attr_sz+12)
81#define NFS3_pathconfres_sz (1+NFS3_post_op_attr_sz+6)
82#define NFS3_commitres_sz (1+NFS3_wcc_data_sz+2)
83
b7fa0554 84#define ACL3_getaclargs_sz (NFS3_fh_sz+1)
ae46141f
TM
85#define ACL3_setaclargs_sz (NFS3_fh_sz+1+ \
86 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
87#define ACL3_getaclres_sz (1+NFS3_post_op_attr_sz+1+ \
88 XDR_QUADLEN(NFS_ACL_INLINE_BUFSIZE))
b7fa0554
AG
89#define ACL3_setaclres_sz (1+NFS3_post_op_attr_sz)
90
1da177e4
LT
91/*
92 * Map file type to S_IFMT bits
93 */
bca79478
TM
94static const umode_t nfs_type2fmt[] = {
95 [NF3BAD] = 0,
96 [NF3REG] = S_IFREG,
97 [NF3DIR] = S_IFDIR,
98 [NF3BLK] = S_IFBLK,
99 [NF3CHR] = S_IFCHR,
100 [NF3LNK] = S_IFLNK,
101 [NF3SOCK] = S_IFSOCK,
102 [NF3FIFO] = S_IFIFO,
1da177e4
LT
103};
104
babddc72
BS
105static void print_overflow_msg(const char *func, const struct xdr_stream *xdr)
106{
107 dprintk("nfs: %s: prematurely hit end of receive buffer. "
108 "Remaining buffer length is %tu words.\n",
109 func, xdr->end - xdr->p);
110}
111
d9c407b1
CL
112/*
113 * While encoding arguments, set up the reply buffer in advance to
114 * receive reply data directly into the page cache.
115 */
116static void prepare_reply_buffer(struct rpc_rqst *req, struct page **pages,
117 unsigned int base, unsigned int len,
118 unsigned int bufsize)
119{
120 struct rpc_auth *auth = req->rq_cred->cr_auth;
121 unsigned int replen;
122
123 replen = RPC_REPHDRSIZE + auth->au_rslack + bufsize;
124 xdr_inline_pages(&req->rq_rcv_buf, replen << 2, pages, base, len);
125}
126
127
1da177e4
LT
128/*
129 * Common NFS XDR functions as inlines
130 */
d61005a6 131static inline __be32 *
4fdc17b2 132xdr_encode_fhandle(__be32 *p, const struct nfs_fh *fh)
1da177e4
LT
133{
134 return xdr_encode_array(p, fh->data, fh->size);
135}
136
d61005a6
AV
137static inline __be32 *
138xdr_decode_fhandle(__be32 *p, struct nfs_fh *fh)
1da177e4
LT
139{
140 if ((fh->size = ntohl(*p++)) <= NFS3_FHSIZE) {
141 memcpy(fh->data, p, fh->size);
142 return p + XDR_QUADLEN(fh->size);
143 }
144 return NULL;
145}
146
babddc72
BS
147static inline __be32 *
148xdr_decode_fhandle_stream(struct xdr_stream *xdr, struct nfs_fh *fh)
149{
150 __be32 *p;
151 p = xdr_inline_decode(xdr, 4);
152 if (unlikely(!p))
153 goto out_overflow;
154 fh->size = ntohl(*p++);
155
156 if (fh->size <= NFS3_FHSIZE) {
157 p = xdr_inline_decode(xdr, fh->size);
158 if (unlikely(!p))
159 goto out_overflow;
160 memcpy(fh->data, p, fh->size);
161 return p + XDR_QUADLEN(fh->size);
162 }
163 return NULL;
164
165out_overflow:
166 print_overflow_msg(__func__, xdr);
167 return ERR_PTR(-EIO);
168}
169
1da177e4
LT
170/*
171 * Encode/decode time.
172 */
d61005a6 173static inline __be32 *
d9c407b1 174xdr_encode_time3(__be32 *p, const struct timespec *timep)
1da177e4
LT
175{
176 *p++ = htonl(timep->tv_sec);
177 *p++ = htonl(timep->tv_nsec);
178 return p;
179}
180
d61005a6
AV
181static inline __be32 *
182xdr_decode_time3(__be32 *p, struct timespec *timep)
1da177e4
LT
183{
184 timep->tv_sec = ntohl(*p++);
185 timep->tv_nsec = ntohl(*p++);
186 return p;
187}
188
d61005a6
AV
189static __be32 *
190xdr_decode_fattr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
191{
192 unsigned int type, major, minor;
bca79478 193 umode_t fmode;
1da177e4
LT
194
195 type = ntohl(*p++);
bca79478
TM
196 if (type > NF3FIFO)
197 type = NF3NON;
198 fmode = nfs_type2fmt[type];
1da177e4
LT
199 fattr->mode = (ntohl(*p++) & ~S_IFMT) | fmode;
200 fattr->nlink = ntohl(*p++);
201 fattr->uid = ntohl(*p++);
202 fattr->gid = ntohl(*p++);
203 p = xdr_decode_hyper(p, &fattr->size);
204 p = xdr_decode_hyper(p, &fattr->du.nfs3.used);
205
206 /* Turn remote device info into Linux-specific dev_t */
207 major = ntohl(*p++);
208 minor = ntohl(*p++);
209 fattr->rdev = MKDEV(major, minor);
210 if (MAJOR(fattr->rdev) != major || MINOR(fattr->rdev) != minor)
211 fattr->rdev = 0;
212
8b4bdcf8
TM
213 p = xdr_decode_hyper(p, &fattr->fsid.major);
214 fattr->fsid.minor = 0;
1da177e4
LT
215 p = xdr_decode_hyper(p, &fattr->fileid);
216 p = xdr_decode_time3(p, &fattr->atime);
217 p = xdr_decode_time3(p, &fattr->mtime);
218 p = xdr_decode_time3(p, &fattr->ctime);
219
220 /* Update the mode bits */
9e6e70f8 221 fattr->valid |= NFS_ATTR_FATTR_V3;
1da177e4
LT
222 return p;
223}
224
d61005a6 225static inline __be32 *
d9c407b1 226xdr_encode_sattr(__be32 *p, const struct iattr *attr)
1da177e4
LT
227{
228 if (attr->ia_valid & ATTR_MODE) {
229 *p++ = xdr_one;
cf3fff54 230 *p++ = htonl(attr->ia_mode & S_IALLUGO);
1da177e4
LT
231 } else {
232 *p++ = xdr_zero;
233 }
234 if (attr->ia_valid & ATTR_UID) {
235 *p++ = xdr_one;
236 *p++ = htonl(attr->ia_uid);
237 } else {
238 *p++ = xdr_zero;
239 }
240 if (attr->ia_valid & ATTR_GID) {
241 *p++ = xdr_one;
242 *p++ = htonl(attr->ia_gid);
243 } else {
244 *p++ = xdr_zero;
245 }
246 if (attr->ia_valid & ATTR_SIZE) {
247 *p++ = xdr_one;
248 p = xdr_encode_hyper(p, (__u64) attr->ia_size);
249 } else {
250 *p++ = xdr_zero;
251 }
252 if (attr->ia_valid & ATTR_ATIME_SET) {
253 *p++ = xdr_two;
254 p = xdr_encode_time3(p, &attr->ia_atime);
255 } else if (attr->ia_valid & ATTR_ATIME) {
256 *p++ = xdr_one;
257 } else {
258 *p++ = xdr_zero;
259 }
260 if (attr->ia_valid & ATTR_MTIME_SET) {
261 *p++ = xdr_two;
262 p = xdr_encode_time3(p, &attr->ia_mtime);
263 } else if (attr->ia_valid & ATTR_MTIME) {
264 *p++ = xdr_one;
265 } else {
266 *p++ = xdr_zero;
267 }
268 return p;
269}
270
d61005a6
AV
271static inline __be32 *
272xdr_decode_wcc_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
273{
274 p = xdr_decode_hyper(p, &fattr->pre_size);
275 p = xdr_decode_time3(p, &fattr->pre_mtime);
276 p = xdr_decode_time3(p, &fattr->pre_ctime);
9e6e70f8
TM
277 fattr->valid |= NFS_ATTR_FATTR_PRESIZE
278 | NFS_ATTR_FATTR_PREMTIME
279 | NFS_ATTR_FATTR_PRECTIME;
1da177e4
LT
280 return p;
281}
282
d61005a6
AV
283static inline __be32 *
284xdr_decode_post_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
285{
286 if (*p++)
287 p = xdr_decode_fattr(p, fattr);
288 return p;
289}
290
babddc72
BS
291static inline __be32 *
292xdr_decode_post_op_attr_stream(struct xdr_stream *xdr, struct nfs_fattr *fattr)
293{
294 __be32 *p;
295
296 p = xdr_inline_decode(xdr, 4);
297 if (unlikely(!p))
298 goto out_overflow;
299 if (ntohl(*p++)) {
300 p = xdr_inline_decode(xdr, 84);
301 if (unlikely(!p))
302 goto out_overflow;
303 p = xdr_decode_fattr(p, fattr);
304 }
305 return p;
306out_overflow:
307 print_overflow_msg(__func__, xdr);
308 return ERR_PTR(-EIO);
309}
310
d61005a6
AV
311static inline __be32 *
312xdr_decode_pre_op_attr(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
313{
314 if (*p++)
315 return xdr_decode_wcc_attr(p, fattr);
316 return p;
317}
318
319
d61005a6
AV
320static inline __be32 *
321xdr_decode_wcc_data(__be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
322{
323 p = xdr_decode_pre_op_attr(p, fattr);
324 return xdr_decode_post_op_attr(p, fattr);
325}
326
d9c407b1
CL
327
328/*
329 * Encode/decode NFSv3 basic data types
330 *
331 * Basic NFSv3 data types are defined in section 2.5 of RFC 1813:
332 * "NFS Version 3 Protocol Specification".
333 *
334 * Not all basic data types have their own encoding and decoding
335 * functions. For run-time efficiency, some data types are encoded
336 * or decoded inline.
337 */
338
339static void encode_uint32(struct xdr_stream *xdr, u32 value)
340{
341 __be32 *p = xdr_reserve_space(xdr, 4);
342 *p = cpu_to_be32(value);
343}
344
345/*
346 * filename3
347 *
348 * typedef string filename3<>;
349 */
350static void encode_filename3(struct xdr_stream *xdr,
351 const char *name, u32 length)
352{
353 __be32 *p;
354
355 BUG_ON(length > NFS3_MAXNAMLEN);
356 p = xdr_reserve_space(xdr, 4 + length);
357 xdr_encode_opaque(p, name, length);
358}
359
360/*
361 * nfspath3
362 *
363 * typedef string nfspath3<>;
364 */
365static void encode_nfspath3(struct xdr_stream *xdr, struct page **pages,
366 const u32 length)
367{
368 BUG_ON(length > NFS3_MAXPATHLEN);
369 encode_uint32(xdr, length);
370 xdr_write_pages(xdr, pages, 0, length);
371}
372
373/*
374 * cookie3
375 *
376 * typedef uint64 cookie3
377 */
378static __be32 *xdr_encode_cookie3(__be32 *p, u64 cookie)
379{
380 return xdr_encode_hyper(p, cookie);
381}
382
383/*
384 * cookieverf3
385 *
386 * typedef opaque cookieverf3[NFS3_COOKIEVERFSIZE];
387 */
388static __be32 *xdr_encode_cookieverf3(__be32 *p, const __be32 *verifier)
389{
390 memcpy(p, verifier, NFS3_COOKIEVERFSIZE);
391 return p + XDR_QUADLEN(NFS3_COOKIEVERFSIZE);
392}
393
394/*
395 * createverf3
396 *
397 * typedef opaque createverf3[NFS3_CREATEVERFSIZE];
398 */
399static void encode_createverf3(struct xdr_stream *xdr, const __be32 *verifier)
400{
401 __be32 *p;
402
403 p = xdr_reserve_space(xdr, NFS3_CREATEVERFSIZE);
404 memcpy(p, verifier, NFS3_CREATEVERFSIZE);
405}
406
407/*
408 * ftype3
409 *
410 * enum ftype3 {
411 * NF3REG = 1,
412 * NF3DIR = 2,
413 * NF3BLK = 3,
414 * NF3CHR = 4,
415 * NF3LNK = 5,
416 * NF3SOCK = 6,
417 * NF3FIFO = 7
418 * };
419 */
420static void encode_ftype3(struct xdr_stream *xdr, const u32 type)
421{
422 BUG_ON(type > NF3FIFO);
423 encode_uint32(xdr, type);
424}
425
426/*
427 * specdata3
428 *
429 * struct specdata3 {
430 * uint32 specdata1;
431 * uint32 specdata2;
432 * };
433 */
434static void encode_specdata3(struct xdr_stream *xdr, const dev_t rdev)
435{
436 __be32 *p;
437
438 p = xdr_reserve_space(xdr, 8);
439 *p++ = cpu_to_be32(MAJOR(rdev));
440 *p = cpu_to_be32(MINOR(rdev));
441}
442
443/*
444 * nfs_fh3
445 *
446 * struct nfs_fh3 {
447 * opaque data<NFS3_FHSIZE>;
448 * };
449 */
450static void encode_nfs_fh3(struct xdr_stream *xdr, const struct nfs_fh *fh)
451{
452 __be32 *p;
453
454 BUG_ON(fh->size > NFS3_FHSIZE);
455 p = xdr_reserve_space(xdr, 4 + fh->size);
456 xdr_encode_opaque(p, fh->data, fh->size);
457}
458
459/*
460 * sattr3
461 *
462 * enum time_how {
463 * DONT_CHANGE = 0,
464 * SET_TO_SERVER_TIME = 1,
465 * SET_TO_CLIENT_TIME = 2
466 * };
467 *
468 * union set_mode3 switch (bool set_it) {
469 * case TRUE:
470 * mode3 mode;
471 * default:
472 * void;
473 * };
474 *
475 * union set_uid3 switch (bool set_it) {
476 * case TRUE:
477 * uid3 uid;
478 * default:
479 * void;
480 * };
481 *
482 * union set_gid3 switch (bool set_it) {
483 * case TRUE:
484 * gid3 gid;
485 * default:
486 * void;
487 * };
488 *
489 * union set_size3 switch (bool set_it) {
490 * case TRUE:
491 * size3 size;
492 * default:
493 * void;
494 * };
495 *
496 * union set_atime switch (time_how set_it) {
497 * case SET_TO_CLIENT_TIME:
498 * nfstime3 atime;
499 * default:
500 * void;
501 * };
502 *
503 * union set_mtime switch (time_how set_it) {
504 * case SET_TO_CLIENT_TIME:
505 * nfstime3 mtime;
506 * default:
507 * void;
508 * };
509 *
510 * struct sattr3 {
511 * set_mode3 mode;
512 * set_uid3 uid;
513 * set_gid3 gid;
514 * set_size3 size;
515 * set_atime atime;
516 * set_mtime mtime;
517 * };
518 */
519static void encode_sattr3(struct xdr_stream *xdr, const struct iattr *attr)
520{
521 u32 nbytes;
522 __be32 *p;
523
524 /*
525 * In order to make only a single xdr_reserve_space() call,
526 * pre-compute the total number of bytes to be reserved.
527 * Six boolean values, one for each set_foo field, are always
528 * present in the encoded result, so start there.
529 */
530 nbytes = 6 * 4;
531 if (attr->ia_valid & ATTR_MODE)
532 nbytes += 4;
533 if (attr->ia_valid & ATTR_UID)
534 nbytes += 4;
535 if (attr->ia_valid & ATTR_GID)
536 nbytes += 4;
537 if (attr->ia_valid & ATTR_SIZE)
538 nbytes += 8;
539 if (attr->ia_valid & ATTR_ATIME_SET)
540 nbytes += 8;
541 if (attr->ia_valid & ATTR_MTIME_SET)
542 nbytes += 8;
543 p = xdr_reserve_space(xdr, nbytes);
544
545 xdr_encode_sattr(p, attr);
546}
547
548/*
549 * diropargs3
550 *
551 * struct diropargs3 {
552 * nfs_fh3 dir;
553 * filename3 name;
554 * };
555 */
556static void encode_diropargs3(struct xdr_stream *xdr, const struct nfs_fh *fh,
557 const char *name, u32 length)
558{
559 encode_nfs_fh3(xdr, fh);
560 encode_filename3(xdr, name, length);
561}
562
563
1da177e4
LT
564/*
565 * NFS encode functions
566 */
567
568/*
569 * Encode file handle argument
570 */
571static int
d61005a6 572nfs3_xdr_fhandle(struct rpc_rqst *req, __be32 *p, struct nfs_fh *fh)
1da177e4
LT
573{
574 p = xdr_encode_fhandle(p, fh);
575 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
576 return 0;
577}
578
d9c407b1
CL
579/*
580 * 3.3.1 GETATTR3args
581 *
582 * struct GETATTR3args {
583 * nfs_fh3 object;
584 * };
585 */
586static int nfs3_xdr_enc_getattr3args(struct rpc_rqst *req, __be32 *p,
587 const struct nfs_fh *fh)
588{
589 struct xdr_stream xdr;
590
591 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
592 encode_nfs_fh3(&xdr, fh);
593 return 0;
594}
595
1da177e4
LT
596/*
597 * Encode SETATTR arguments
598 */
599static int
d61005a6 600nfs3_xdr_sattrargs(struct rpc_rqst *req, __be32 *p, struct nfs3_sattrargs *args)
1da177e4
LT
601{
602 p = xdr_encode_fhandle(p, args->fh);
603 p = xdr_encode_sattr(p, args->sattr);
604 *p++ = htonl(args->guard);
605 if (args->guard)
606 p = xdr_encode_time3(p, &args->guardtime);
607 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
608 return 0;
609}
610
d9c407b1
CL
611/*
612 * 3.3.2 SETATTR3args
613 *
614 * union sattrguard3 switch (bool check) {
615 * case TRUE:
616 * nfstime3 obj_ctime;
617 * case FALSE:
618 * void;
619 * };
620 *
621 * struct SETATTR3args {
622 * nfs_fh3 object;
623 * sattr3 new_attributes;
624 * sattrguard3 guard;
625 * };
626 */
627static void encode_sattrguard3(struct xdr_stream *xdr,
628 const struct nfs3_sattrargs *args)
629{
630 __be32 *p;
631
632 if (args->guard) {
633 p = xdr_reserve_space(xdr, 4 + 8);
634 *p++ = xdr_one;
635 xdr_encode_time3(p, &args->guardtime);
636 } else {
637 p = xdr_reserve_space(xdr, 4);
638 *p = xdr_zero;
639 }
640}
641
642static int nfs3_xdr_enc_setattr3args(struct rpc_rqst *req, __be32 *p,
643 const struct nfs3_sattrargs *args)
644{
645 struct xdr_stream xdr;
646
647 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
648 encode_nfs_fh3(&xdr, args->fh);
649 encode_sattr3(&xdr, args->sattr);
650 encode_sattrguard3(&xdr, args);
651 return 0;
652}
653
1da177e4
LT
654/*
655 * Encode directory ops argument
656 */
657static int
d61005a6 658nfs3_xdr_diropargs(struct rpc_rqst *req, __be32 *p, struct nfs3_diropargs *args)
1da177e4
LT
659{
660 p = xdr_encode_fhandle(p, args->fh);
661 p = xdr_encode_array(p, args->name, args->len);
662 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
663 return 0;
664}
665
d9c407b1
CL
666/*
667 * 3.3.3 LOOKUP3args
668 *
669 * struct LOOKUP3args {
670 * diropargs3 what;
671 * };
672 */
673static int nfs3_xdr_enc_lookup3args(struct rpc_rqst *req, __be32 *p,
674 const struct nfs3_diropargs *args)
675{
676 struct xdr_stream xdr;
677
678 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
679 encode_diropargs3(&xdr, args->fh, args->name, args->len);
680 return 0;
681}
682
4fdc17b2
TM
683/*
684 * Encode REMOVE argument
685 */
686static int
687nfs3_xdr_removeargs(struct rpc_rqst *req, __be32 *p, const struct nfs_removeargs *args)
688{
689 p = xdr_encode_fhandle(p, args->fh);
690 p = xdr_encode_array(p, args->name.name, args->name.len);
691 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
692 return 0;
693}
694
1da177e4
LT
695/*
696 * Encode access() argument
697 */
698static int
d61005a6 699nfs3_xdr_accessargs(struct rpc_rqst *req, __be32 *p, struct nfs3_accessargs *args)
1da177e4
LT
700{
701 p = xdr_encode_fhandle(p, args->fh);
702 *p++ = htonl(args->access);
703 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
704 return 0;
705}
706
d9c407b1
CL
707/*
708 * 3.3.4 ACCESS3args
709 *
710 * struct ACCESS3args {
711 * nfs_fh3 object;
712 * uint32 access;
713 * };
714 */
715static void encode_access3args(struct xdr_stream *xdr,
716 const struct nfs3_accessargs *args)
717{
718 encode_nfs_fh3(xdr, args->fh);
719 encode_uint32(xdr, args->access);
720}
721
722static int nfs3_xdr_enc_access3args(struct rpc_rqst *req, __be32 *p,
723 const struct nfs3_accessargs *args)
724{
725 struct xdr_stream xdr;
726
727 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
728 encode_access3args(&xdr, args);
729 return 0;
730}
731
732/*
733 * 3.3.5 READLINK3args
734 *
735 * struct READLINK3args {
736 * nfs_fh3 symlink;
737 * };
738 */
739static int nfs3_xdr_enc_readlink3args(struct rpc_rqst *req, __be32 *p,
740 const struct nfs3_readlinkargs *args)
741{
742 struct xdr_stream xdr;
743
744 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
745 encode_nfs_fh3(&xdr, args->fh);
746 prepare_reply_buffer(req, args->pages, args->pgbase,
747 args->pglen, NFS3_readlinkres_sz);
748 return 0;
749}
750
1da177e4
LT
751/*
752 * Arguments to a READ call. Since we read data directly into the page
753 * cache, we also set up the reply iovec here so that iov[1] points
754 * exactly to the page we want to fetch.
755 */
756static int
d61005a6 757nfs3_xdr_readargs(struct rpc_rqst *req, __be32 *p, struct nfs_readargs *args)
1da177e4 758{
a17c2153 759 struct rpc_auth *auth = req->rq_cred->cr_auth;
1da177e4
LT
760 unsigned int replen;
761 u32 count = args->count;
762
763 p = xdr_encode_fhandle(p, args->fh);
764 p = xdr_encode_hyper(p, args->offset);
765 *p++ = htonl(count);
766 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
767
768 /* Inline the page array */
769 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readres_sz) << 2;
770 xdr_inline_pages(&req->rq_rcv_buf, replen,
771 args->pages, args->pgbase, count);
4f22ccc3 772 req->rq_rcv_buf.flags |= XDRBUF_READ;
1da177e4
LT
773 return 0;
774}
775
d9c407b1
CL
776/*
777 * 3.3.6 READ3args
778 *
779 * struct READ3args {
780 * nfs_fh3 file;
781 * offset3 offset;
782 * count3 count;
783 * };
784 */
785static void encode_read3args(struct xdr_stream *xdr,
786 const struct nfs_readargs *args)
787{
788 __be32 *p;
789
790 encode_nfs_fh3(xdr, args->fh);
791
792 p = xdr_reserve_space(xdr, 8 + 4);
793 p = xdr_encode_hyper(p, args->offset);
794 *p = cpu_to_be32(args->count);
795}
796
797static int nfs3_xdr_enc_read3args(struct rpc_rqst *req, __be32 *p,
798 const struct nfs_readargs *args)
799{
800 struct xdr_stream xdr;
801
802 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
803 encode_read3args(&xdr, args);
804 prepare_reply_buffer(req, args->pages, args->pgbase,
805 args->count, NFS3_readres_sz);
806 req->rq_rcv_buf.flags |= XDRBUF_READ;
807 return 0;
808}
809
1da177e4
LT
810/*
811 * Write arguments. Splice the buffer to be written into the iovec.
812 */
813static int
d61005a6 814nfs3_xdr_writeargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
1da177e4
LT
815{
816 struct xdr_buf *sndbuf = &req->rq_snd_buf;
817 u32 count = args->count;
818
819 p = xdr_encode_fhandle(p, args->fh);
820 p = xdr_encode_hyper(p, args->offset);
821 *p++ = htonl(count);
822 *p++ = htonl(args->stable);
823 *p++ = htonl(count);
824 sndbuf->len = xdr_adjust_iovec(sndbuf->head, p);
825
826 /* Copy the page array */
827 xdr_encode_pages(sndbuf, args->pages, args->pgbase, count);
4f22ccc3 828 sndbuf->flags |= XDRBUF_WRITE;
1da177e4
LT
829 return 0;
830}
831
d9c407b1
CL
832/*
833 * 3.3.7 WRITE3args
834 *
835 * enum stable_how {
836 * UNSTABLE = 0,
837 * DATA_SYNC = 1,
838 * FILE_SYNC = 2
839 * };
840 *
841 * struct WRITE3args {
842 * nfs_fh3 file;
843 * offset3 offset;
844 * count3 count;
845 * stable_how stable;
846 * opaque data<>;
847 * };
848 */
849static void encode_write3args(struct xdr_stream *xdr,
850 const struct nfs_writeargs *args)
851{
852 __be32 *p;
853
854 encode_nfs_fh3(xdr, args->fh);
855
856 p = xdr_reserve_space(xdr, 8 + 4 + 4 + 4);
857 p = xdr_encode_hyper(p, args->offset);
858 *p++ = cpu_to_be32(args->count);
859
860 BUG_ON(args->stable > NFS_FILE_SYNC);
861 *p++ = cpu_to_be32(args->stable);
862
863 *p = cpu_to_be32(args->count);
864 xdr_write_pages(xdr, args->pages, args->pgbase, args->count);
865}
866
867static int nfs3_xdr_enc_write3args(struct rpc_rqst *req, __be32 *p,
868 const struct nfs_writeargs *args)
869{
870 struct xdr_stream xdr;
871
872 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
873 encode_write3args(&xdr, args);
874 xdr.buf->flags |= XDRBUF_WRITE;
875 return 0;
876}
877
1da177e4
LT
878/*
879 * Encode CREATE arguments
880 */
881static int
d61005a6 882nfs3_xdr_createargs(struct rpc_rqst *req, __be32 *p, struct nfs3_createargs *args)
1da177e4
LT
883{
884 p = xdr_encode_fhandle(p, args->fh);
885 p = xdr_encode_array(p, args->name, args->len);
886
887 *p++ = htonl(args->createmode);
888 if (args->createmode == NFS3_CREATE_EXCLUSIVE) {
889 *p++ = args->verifier[0];
890 *p++ = args->verifier[1];
891 } else
892 p = xdr_encode_sattr(p, args->sattr);
893
894 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
895 return 0;
896}
897
d9c407b1
CL
898/*
899 * 3.3.8 CREATE3args
900 *
901 * enum createmode3 {
902 * UNCHECKED = 0,
903 * GUARDED = 1,
904 * EXCLUSIVE = 2
905 * };
906 *
907 * union createhow3 switch (createmode3 mode) {
908 * case UNCHECKED:
909 * case GUARDED:
910 * sattr3 obj_attributes;
911 * case EXCLUSIVE:
912 * createverf3 verf;
913 * };
914 *
915 * struct CREATE3args {
916 * diropargs3 where;
917 * createhow3 how;
918 * };
919 */
920static void encode_createhow3(struct xdr_stream *xdr,
921 const struct nfs3_createargs *args)
922{
923 encode_uint32(xdr, args->createmode);
924 switch (args->createmode) {
925 case NFS3_CREATE_UNCHECKED:
926 case NFS3_CREATE_GUARDED:
927 encode_sattr3(xdr, args->sattr);
928 break;
929 case NFS3_CREATE_EXCLUSIVE:
930 encode_createverf3(xdr, args->verifier);
931 break;
932 default:
933 BUG();
934 }
935}
936
937static int nfs3_xdr_enc_create3args(struct rpc_rqst *req, __be32 *p,
938 const struct nfs3_createargs *args)
939{
940 struct xdr_stream xdr;
941
942 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
943 encode_diropargs3(&xdr, args->fh, args->name, args->len);
944 encode_createhow3(&xdr, args);
945 return 0;
946}
947
1da177e4
LT
948/*
949 * Encode MKDIR arguments
950 */
951static int
d61005a6 952nfs3_xdr_mkdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mkdirargs *args)
1da177e4
LT
953{
954 p = xdr_encode_fhandle(p, args->fh);
955 p = xdr_encode_array(p, args->name, args->len);
956 p = xdr_encode_sattr(p, args->sattr);
957 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
958 return 0;
959}
960
d9c407b1
CL
961/*
962 * 3.3.9 MKDIR3args
963 *
964 * struct MKDIR3args {
965 * diropargs3 where;
966 * sattr3 attributes;
967 * };
968 */
969static int nfs3_xdr_enc_mkdir3args(struct rpc_rqst *req, __be32 *p,
970 const struct nfs3_mkdirargs *args)
971{
972 struct xdr_stream xdr;
973
974 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
975 encode_diropargs3(&xdr, args->fh, args->name, args->len);
976 encode_sattr3(&xdr, args->sattr);
977 return 0;
978}
979
1da177e4
LT
980/*
981 * Encode SYMLINK arguments
982 */
983static int
d61005a6 984nfs3_xdr_symlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_symlinkargs *args)
1da177e4
LT
985{
986 p = xdr_encode_fhandle(p, args->fromfh);
987 p = xdr_encode_array(p, args->fromname, args->fromlen);
988 p = xdr_encode_sattr(p, args->sattr);
94a6d753 989 *p++ = htonl(args->pathlen);
1da177e4 990 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
94a6d753
CL
991
992 /* Copy the page */
993 xdr_encode_pages(&req->rq_snd_buf, args->pages, 0, args->pathlen);
1da177e4
LT
994 return 0;
995}
996
d9c407b1
CL
997/*
998 * 3.3.10 SYMLINK3args
999 *
1000 * struct symlinkdata3 {
1001 * sattr3 symlink_attributes;
1002 * nfspath3 symlink_data;
1003 * };
1004 *
1005 * struct SYMLINK3args {
1006 * diropargs3 where;
1007 * symlinkdata3 symlink;
1008 * };
1009 */
1010static void encode_symlinkdata3(struct xdr_stream *xdr,
1011 const struct nfs3_symlinkargs *args)
1012{
1013 encode_sattr3(xdr, args->sattr);
1014 encode_nfspath3(xdr, args->pages, args->pathlen);
1015}
1016
1017static int nfs3_xdr_enc_symlink3args(struct rpc_rqst *req, __be32 *p,
1018 const struct nfs3_symlinkargs *args)
1019{
1020 struct xdr_stream xdr;
1021
1022 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1023 encode_diropargs3(&xdr, args->fromfh, args->fromname, args->fromlen);
1024 encode_symlinkdata3(&xdr, args);
1025 return 0;
1026}
1027
1da177e4
LT
1028/*
1029 * Encode MKNOD arguments
1030 */
1031static int
d61005a6 1032nfs3_xdr_mknodargs(struct rpc_rqst *req, __be32 *p, struct nfs3_mknodargs *args)
1da177e4
LT
1033{
1034 p = xdr_encode_fhandle(p, args->fh);
1035 p = xdr_encode_array(p, args->name, args->len);
1036 *p++ = htonl(args->type);
1037 p = xdr_encode_sattr(p, args->sattr);
1038 if (args->type == NF3CHR || args->type == NF3BLK) {
1039 *p++ = htonl(MAJOR(args->rdev));
1040 *p++ = htonl(MINOR(args->rdev));
1041 }
1042
1043 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1044 return 0;
1045}
1046
d9c407b1
CL
1047/*
1048 * 3.3.11 MKNOD3args
1049 *
1050 * struct devicedata3 {
1051 * sattr3 dev_attributes;
1052 * specdata3 spec;
1053 * };
1054 *
1055 * union mknoddata3 switch (ftype3 type) {
1056 * case NF3CHR:
1057 * case NF3BLK:
1058 * devicedata3 device;
1059 * case NF3SOCK:
1060 * case NF3FIFO:
1061 * sattr3 pipe_attributes;
1062 * default:
1063 * void;
1064 * };
1065 *
1066 * struct MKNOD3args {
1067 * diropargs3 where;
1068 * mknoddata3 what;
1069 * };
1070 */
1071static void encode_devicedata3(struct xdr_stream *xdr,
1072 const struct nfs3_mknodargs *args)
1073{
1074 encode_sattr3(xdr, args->sattr);
1075 encode_specdata3(xdr, args->rdev);
1076}
1077
1078static void encode_mknoddata3(struct xdr_stream *xdr,
1079 const struct nfs3_mknodargs *args)
1080{
1081 encode_ftype3(xdr, args->type);
1082 switch (args->type) {
1083 case NF3CHR:
1084 case NF3BLK:
1085 encode_devicedata3(xdr, args);
1086 break;
1087 case NF3SOCK:
1088 case NF3FIFO:
1089 encode_sattr3(xdr, args->sattr);
1090 break;
1091 case NF3REG:
1092 case NF3DIR:
1093 break;
1094 default:
1095 BUG();
1096 }
1097}
1098
1099static int nfs3_xdr_enc_mknod3args(struct rpc_rqst *req, __be32 *p,
1100 const struct nfs3_mknodargs *args)
1101{
1102 struct xdr_stream xdr;
1103
1104 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1105 encode_diropargs3(&xdr, args->fh, args->name, args->len);
1106 encode_mknoddata3(&xdr, args);
1107 return 0;
1108}
1109
1110/*
1111 * 3.3.12 REMOVE3args
1112 *
1113 * struct REMOVE3args {
1114 * diropargs3 object;
1115 * };
1116 */
1117static int nfs3_xdr_enc_remove3args(struct rpc_rqst *req, __be32 *p,
1118 const struct nfs_removeargs *args)
1119{
1120 struct xdr_stream xdr;
1121
1122 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1123 encode_diropargs3(&xdr, args->fh, args->name.name, args->name.len);
1124 return 0;
1125}
1126
1da177e4
LT
1127/*
1128 * Encode RENAME arguments
1129 */
1130static int
920769f0 1131nfs3_xdr_renameargs(struct rpc_rqst *req, __be32 *p, struct nfs_renameargs *args)
1da177e4 1132{
920769f0
JL
1133 p = xdr_encode_fhandle(p, args->old_dir);
1134 p = xdr_encode_array(p, args->old_name->name, args->old_name->len);
1135 p = xdr_encode_fhandle(p, args->new_dir);
1136 p = xdr_encode_array(p, args->new_name->name, args->new_name->len);
1da177e4
LT
1137 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1138 return 0;
1139}
1140
d9c407b1
CL
1141/*
1142 * 3.3.14 RENAME3args
1143 *
1144 * struct RENAME3args {
1145 * diropargs3 from;
1146 * diropargs3 to;
1147 * };
1148 */
1149static int nfs3_xdr_enc_rename3args(struct rpc_rqst *req, __be32 *p,
1150 const struct nfs_renameargs *args)
1151{
1152 const struct qstr *old = args->old_name;
1153 const struct qstr *new = args->new_name;
1154 struct xdr_stream xdr;
1155
1156 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1157 encode_diropargs3(&xdr, args->old_dir, old->name, old->len);
1158 encode_diropargs3(&xdr, args->new_dir, new->name, new->len);
1159 return 0;
1160}
1161
1da177e4
LT
1162/*
1163 * Encode LINK arguments
1164 */
1165static int
d61005a6 1166nfs3_xdr_linkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_linkargs *args)
1da177e4
LT
1167{
1168 p = xdr_encode_fhandle(p, args->fromfh);
1169 p = xdr_encode_fhandle(p, args->tofh);
1170 p = xdr_encode_array(p, args->toname, args->tolen);
1171 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1172 return 0;
1173}
1174
d9c407b1
CL
1175/*
1176 * 3.3.15 LINK3args
1177 *
1178 * struct LINK3args {
1179 * nfs_fh3 file;
1180 * diropargs3 link;
1181 * };
1182 */
1183static int nfs3_xdr_enc_link3args(struct rpc_rqst *req, __be32 *p,
1184 const struct nfs3_linkargs *args)
1185{
1186 struct xdr_stream xdr;
1187
1188 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1189 encode_nfs_fh3(&xdr, args->fromfh);
1190 encode_diropargs3(&xdr, args->tofh, args->toname, args->tolen);
1191 return 0;
1192}
1193
1da177e4
LT
1194/*
1195 * Encode arguments to readdir call
1196 */
1197static int
d61005a6 1198nfs3_xdr_readdirargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirargs *args)
1da177e4 1199{
a17c2153 1200 struct rpc_auth *auth = req->rq_cred->cr_auth;
1da177e4
LT
1201 unsigned int replen;
1202 u32 count = args->count;
1203
1204 p = xdr_encode_fhandle(p, args->fh);
1205 p = xdr_encode_hyper(p, args->cookie);
1206 *p++ = args->verf[0];
1207 *p++ = args->verf[1];
1208 if (args->plus) {
1209 /* readdirplus: need dircount + buffer size.
1210 * We just make sure we make dircount big enough */
1211 *p++ = htonl(count >> 3);
1212 }
1213 *p++ = htonl(count);
1214 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1215
1216 /* Inline the page array */
1217 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readdirres_sz) << 2;
1218 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0, count);
1219 return 0;
1220}
1221
d9c407b1
CL
1222/*
1223 * 3.3.16 READDIR3args
1224 *
1225 * struct READDIR3args {
1226 * nfs_fh3 dir;
1227 * cookie3 cookie;
1228 * cookieverf3 cookieverf;
1229 * count3 count;
1230 * };
1231 */
1232static void encode_readdir3args(struct xdr_stream *xdr,
1233 const struct nfs3_readdirargs *args)
1234{
1235 __be32 *p;
1236
1237 encode_nfs_fh3(xdr, args->fh);
1238
1239 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4);
1240 p = xdr_encode_cookie3(p, args->cookie);
1241 p = xdr_encode_cookieverf3(p, args->verf);
1242 *p = cpu_to_be32(args->count);
1243}
1244
1245static int nfs3_xdr_enc_readdir3args(struct rpc_rqst *req, __be32 *p,
1246 const struct nfs3_readdirargs *args)
1247{
1248 struct xdr_stream xdr;
1249
1250 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1251 encode_readdir3args(&xdr, args);
1252 prepare_reply_buffer(req, args->pages, 0,
1253 args->count, NFS3_readdirres_sz);
1254 return 0;
1255}
1256
1257/*
1258 * 3.3.17 READDIRPLUS3args
1259 *
1260 * struct READDIRPLUS3args {
1261 * nfs_fh3 dir;
1262 * cookie3 cookie;
1263 * cookieverf3 cookieverf;
1264 * count3 dircount;
1265 * count3 maxcount;
1266 * };
1267 */
1268static void encode_readdirplus3args(struct xdr_stream *xdr,
1269 const struct nfs3_readdirargs *args)
1270{
1271 __be32 *p;
1272
1273 encode_nfs_fh3(xdr, args->fh);
1274
1275 p = xdr_reserve_space(xdr, 8 + NFS3_COOKIEVERFSIZE + 4 + 4);
1276 p = xdr_encode_cookie3(p, args->cookie);
1277 p = xdr_encode_cookieverf3(p, args->verf);
1278
1279 /*
1280 * readdirplus: need dircount + buffer size.
1281 * We just make sure we make dircount big enough
1282 */
1283 *p++ = cpu_to_be32(args->count >> 3);
1284
1285 *p = cpu_to_be32(args->count);
1286}
1287
1288static int nfs3_xdr_enc_readdirplus3args(struct rpc_rqst *req, __be32 *p,
1289 const struct nfs3_readdirargs *args)
1290{
1291 struct xdr_stream xdr;
1292
1293 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1294 encode_readdirplus3args(&xdr, args);
1295 prepare_reply_buffer(req, args->pages, 0,
1296 args->count, NFS3_readdirres_sz);
1297 return 0;
1298}
1299
1da177e4
LT
1300/*
1301 * Decode the result of a readdir call.
1302 * We just check for syntactical correctness.
1303 */
1304static int
d61005a6 1305nfs3_xdr_readdirres(struct rpc_rqst *req, __be32 *p, struct nfs3_readdirres *res)
1da177e4
LT
1306{
1307 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1308 struct kvec *iov = rcvbuf->head;
1309 struct page **page;
c957c526 1310 size_t hdrlen;
afa8ccc9 1311 u32 recvd, pglen;
ac396128 1312 int status;
1da177e4
LT
1313
1314 status = ntohl(*p++);
1315 /* Decode post_op_attrs */
1316 p = xdr_decode_post_op_attr(p, res->dir_attr);
1317 if (status)
856dff3d 1318 return nfs_stat_to_errno(status);
1da177e4
LT
1319 /* Decode verifier cookie */
1320 if (res->verf) {
1321 res->verf[0] = *p++;
1322 res->verf[1] = *p++;
1323 } else {
1324 p += 2;
1325 }
1326
1327 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1328 if (iov->iov_len < hdrlen) {
fe82a183 1329 dprintk("NFS: READDIR reply header overflowed:"
c957c526 1330 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1331 return -errno_NFSERR_IO;
1332 } else if (iov->iov_len != hdrlen) {
1333 dprintk("NFS: READDIR header is short. iovec will be shifted.\n");
1334 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1335 }
1336
1337 pglen = rcvbuf->page_len;
1338 recvd = rcvbuf->len - hdrlen;
1339 if (pglen > recvd)
1340 pglen = recvd;
1341 page = rcvbuf->pages;
643f8111 1342
ac396128 1343 return pglen;
1da177e4
LT
1344}
1345
0dbb4c67 1346__be32 *
82f2e547 1347nfs3_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, struct nfs_server *server, int plus)
1da177e4 1348{
babddc72 1349 __be32 *p;
1da177e4
LT
1350 struct nfs_entry old = *entry;
1351
babddc72
BS
1352 p = xdr_inline_decode(xdr, 4);
1353 if (unlikely(!p))
1354 goto out_overflow;
1355 if (!ntohl(*p++)) {
1356 p = xdr_inline_decode(xdr, 4);
1357 if (unlikely(!p))
1358 goto out_overflow;
1359 if (!ntohl(*p++))
1da177e4
LT
1360 return ERR_PTR(-EAGAIN);
1361 entry->eof = 1;
1362 return ERR_PTR(-EBADCOOKIE);
1363 }
1364
babddc72
BS
1365 p = xdr_inline_decode(xdr, 12);
1366 if (unlikely(!p))
1367 goto out_overflow;
1da177e4
LT
1368 p = xdr_decode_hyper(p, &entry->ino);
1369 entry->len = ntohl(*p++);
babddc72
BS
1370
1371 p = xdr_inline_decode(xdr, entry->len + 8);
1372 if (unlikely(!p))
1373 goto out_overflow;
1da177e4
LT
1374 entry->name = (const char *) p;
1375 p += XDR_QUADLEN(entry->len);
1376 entry->prev_cookie = entry->cookie;
1377 p = xdr_decode_hyper(p, &entry->cookie);
1378
0b26a0bf 1379 entry->d_type = DT_UNKNOWN;
1da177e4
LT
1380 if (plus) {
1381 entry->fattr->valid = 0;
babddc72
BS
1382 p = xdr_decode_post_op_attr_stream(xdr, entry->fattr);
1383 if (IS_ERR(p))
1384 goto out_overflow_exit;
0b26a0bf 1385 entry->d_type = nfs_umode_to_dtype(entry->fattr->mode);
1da177e4 1386 /* In fact, a post_op_fh3: */
babddc72
BS
1387 p = xdr_inline_decode(xdr, 4);
1388 if (unlikely(!p))
1389 goto out_overflow;
1da177e4 1390 if (*p++) {
babddc72
BS
1391 p = xdr_decode_fhandle_stream(xdr, entry->fh);
1392 if (IS_ERR(p))
1393 goto out_overflow_exit;
1da177e4
LT
1394 /* Ugh -- server reply was truncated */
1395 if (p == NULL) {
1396 dprintk("NFS: FH truncated\n");
1397 *entry = old;
1398 return ERR_PTR(-EAGAIN);
1399 }
1400 } else
1401 memset((u8*)(entry->fh), 0, sizeof(*entry->fh));
1402 }
1403
babddc72
BS
1404 p = xdr_inline_peek(xdr, 8);
1405 if (p != NULL)
1406 entry->eof = !p[0] && p[1];
1407 else
1408 entry->eof = 0;
1409
1da177e4 1410 return p;
babddc72
BS
1411
1412out_overflow:
1413 print_overflow_msg(__func__, xdr);
1414out_overflow_exit:
463a376e 1415 return ERR_PTR(-EAGAIN);
1da177e4
LT
1416}
1417
1418/*
1419 * Encode COMMIT arguments
1420 */
1421static int
d61005a6 1422nfs3_xdr_commitargs(struct rpc_rqst *req, __be32 *p, struct nfs_writeargs *args)
1da177e4
LT
1423{
1424 p = xdr_encode_fhandle(p, args->fh);
1425 p = xdr_encode_hyper(p, args->offset);
1426 *p++ = htonl(args->count);
1427 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1428 return 0;
1429}
1430
d9c407b1
CL
1431/*
1432 * 3.3.21 COMMIT3args
1433 *
1434 * struct COMMIT3args {
1435 * nfs_fh3 file;
1436 * offset3 offset;
1437 * count3 count;
1438 * };
1439 */
1440static void encode_commit3args(struct xdr_stream *xdr,
1441 const struct nfs_writeargs *args)
1442{
1443 __be32 *p;
1444
1445 encode_nfs_fh3(xdr, args->fh);
1446
1447 p = xdr_reserve_space(xdr, 8 + 4);
1448 p = xdr_encode_hyper(p, args->offset);
1449 *p = cpu_to_be32(args->count);
1450}
1451
1452static int nfs3_xdr_enc_commit3args(struct rpc_rqst *req, __be32 *p,
1453 const struct nfs_writeargs *args)
1454{
1455 struct xdr_stream xdr;
1456
1457 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1458 encode_commit3args(&xdr, args);
1459 return 0;
1460}
1461
b7fa0554
AG
1462#ifdef CONFIG_NFS_V3_ACL
1463/*
1464 * Encode GETACL arguments
1465 */
1466static int
d61005a6 1467nfs3_xdr_getaclargs(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
1468 struct nfs3_getaclargs *args)
1469{
a17c2153 1470 struct rpc_auth *auth = req->rq_cred->cr_auth;
b7fa0554
AG
1471 unsigned int replen;
1472
1473 p = xdr_encode_fhandle(p, args->fh);
1474 *p++ = htonl(args->mask);
1475 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1476
1477 if (args->mask & (NFS_ACL | NFS_DFACL)) {
1478 /* Inline the page array */
1479 replen = (RPC_REPHDRSIZE + auth->au_rslack +
1480 ACL3_getaclres_sz) << 2;
1481 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, 0,
1482 NFSACL_MAXPAGES << PAGE_SHIFT);
1483 }
1484 return 0;
1485}
1486
d9c407b1
CL
1487static int nfs3_xdr_enc_getacl3args(struct rpc_rqst *req, __be32 *p,
1488 const struct nfs3_getaclargs *args)
1489{
1490 struct xdr_stream xdr;
1491
1492 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1493 encode_nfs_fh3(&xdr, args->fh);
1494 encode_uint32(&xdr, args->mask);
1495 if (args->mask & (NFS_ACL | NFS_DFACL))
1496 prepare_reply_buffer(req, args->pages, 0,
1497 NFSACL_MAXPAGES << PAGE_SHIFT,
1498 ACL3_getaclres_sz);
1499 return 0;
1500}
1501
b7fa0554
AG
1502/*
1503 * Encode SETACL arguments
1504 */
1505static int
d61005a6 1506nfs3_xdr_setaclargs(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
1507 struct nfs3_setaclargs *args)
1508{
1509 struct xdr_buf *buf = &req->rq_snd_buf;
ae46141f
TM
1510 unsigned int base;
1511 int err;
b7fa0554
AG
1512
1513 p = xdr_encode_fhandle(p, NFS_FH(args->inode));
1514 *p++ = htonl(args->mask);
ae46141f
TM
1515 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1516 base = req->rq_slen;
1517
1518 if (args->npages != 0)
1519 xdr_encode_pages(buf, args->pages, 0, args->len);
1520 else
83404372
TM
1521 req->rq_slen = xdr_adjust_iovec(req->rq_svec,
1522 p + XDR_QUADLEN(args->len));
b7fa0554
AG
1523
1524 err = nfsacl_encode(buf, base, args->inode,
1525 (args->mask & NFS_ACL) ?
1526 args->acl_access : NULL, 1, 0);
1527 if (err > 0)
1528 err = nfsacl_encode(buf, base + err, args->inode,
1529 (args->mask & NFS_DFACL) ?
1530 args->acl_default : NULL, 1,
1531 NFS_ACL_DEFAULT);
1532 return (err > 0) ? 0 : err;
1533}
d9c407b1
CL
1534
1535static int nfs3_xdr_enc_setacl3args(struct rpc_rqst *req, __be32 *p,
1536 const struct nfs3_setaclargs *args)
1537{
1538 struct xdr_stream xdr;
1539 unsigned int base;
1540 int error;
1541
1542 xdr_init_encode(&xdr, &req->rq_snd_buf, p);
1543 encode_nfs_fh3(&xdr, NFS_FH(args->inode));
1544 encode_uint32(&xdr, args->mask);
1545 if (args->npages != 0)
1546 xdr_write_pages(&xdr, args->pages, 0, args->len);
1547
1548 base = req->rq_slen;
1549 error = nfsacl_encode(xdr.buf, base, args->inode,
1550 (args->mask & NFS_ACL) ?
1551 args->acl_access : NULL, 1, 0);
1552 BUG_ON(error < 0);
1553 error = nfsacl_encode(xdr.buf, base + error, args->inode,
1554 (args->mask & NFS_DFACL) ?
1555 args->acl_default : NULL, 1,
1556 NFS_ACL_DEFAULT);
1557 BUG_ON(error < 0);
1558 return 0;
1559}
1560
b7fa0554
AG
1561#endif /* CONFIG_NFS_V3_ACL */
1562
1da177e4
LT
1563/*
1564 * NFS XDR decode functions
1565 */
1566
1567/*
1568 * Decode attrstat reply.
1569 */
1570static int
d61005a6 1571nfs3_xdr_attrstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
1572{
1573 int status;
1574
1575 if ((status = ntohl(*p++)))
856dff3d 1576 return nfs_stat_to_errno(status);
1da177e4
LT
1577 xdr_decode_fattr(p, fattr);
1578 return 0;
1579}
1580
1581/*
1582 * Decode status+wcc_data reply
1583 * SATTR, REMOVE, RMDIR
1584 */
1585static int
d61005a6 1586nfs3_xdr_wccstat(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
1587{
1588 int status;
1589
1590 if ((status = ntohl(*p++)))
856dff3d 1591 status = nfs_stat_to_errno(status);
1da177e4
LT
1592 xdr_decode_wcc_data(p, fattr);
1593 return status;
1594}
1595
4fdc17b2
TM
1596static int
1597nfs3_xdr_removeres(struct rpc_rqst *req, __be32 *p, struct nfs_removeres *res)
1598{
d346890b 1599 return nfs3_xdr_wccstat(req, p, res->dir_attr);
4fdc17b2
TM
1600}
1601
1da177e4
LT
1602/*
1603 * Decode LOOKUP reply
1604 */
1605static int
d61005a6 1606nfs3_xdr_lookupres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
1607{
1608 int status;
1609
1610 if ((status = ntohl(*p++))) {
856dff3d 1611 status = nfs_stat_to_errno(status);
1da177e4
LT
1612 } else {
1613 if (!(p = xdr_decode_fhandle(p, res->fh)))
1614 return -errno_NFSERR_IO;
1615 p = xdr_decode_post_op_attr(p, res->fattr);
1616 }
1617 xdr_decode_post_op_attr(p, res->dir_attr);
1618 return status;
1619}
1620
1621/*
1622 * Decode ACCESS reply
1623 */
1624static int
d61005a6 1625nfs3_xdr_accessres(struct rpc_rqst *req, __be32 *p, struct nfs3_accessres *res)
1da177e4
LT
1626{
1627 int status = ntohl(*p++);
1628
1629 p = xdr_decode_post_op_attr(p, res->fattr);
1630 if (status)
856dff3d 1631 return nfs_stat_to_errno(status);
1da177e4
LT
1632 res->access = ntohl(*p++);
1633 return 0;
1634}
1635
1636static int
d61005a6 1637nfs3_xdr_readlinkargs(struct rpc_rqst *req, __be32 *p, struct nfs3_readlinkargs *args)
1da177e4 1638{
a17c2153 1639 struct rpc_auth *auth = req->rq_cred->cr_auth;
1da177e4
LT
1640 unsigned int replen;
1641
1642 p = xdr_encode_fhandle(p, args->fh);
1643 req->rq_slen = xdr_adjust_iovec(req->rq_svec, p);
1644
1645 /* Inline the page array */
1646 replen = (RPC_REPHDRSIZE + auth->au_rslack + NFS3_readlinkres_sz) << 2;
1647 xdr_inline_pages(&req->rq_rcv_buf, replen, args->pages, args->pgbase, args->pglen);
1648 return 0;
1649}
1650
1651/*
1652 * Decode READLINK reply
1653 */
1654static int
d61005a6 1655nfs3_xdr_readlinkres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
1da177e4
LT
1656{
1657 struct xdr_buf *rcvbuf = &req->rq_rcv_buf;
1658 struct kvec *iov = rcvbuf->head;
c957c526
CL
1659 size_t hdrlen;
1660 u32 len, recvd;
1da177e4
LT
1661 int status;
1662
1663 status = ntohl(*p++);
1664 p = xdr_decode_post_op_attr(p, fattr);
1665
1666 if (status != 0)
856dff3d 1667 return nfs_stat_to_errno(status);
1da177e4
LT
1668
1669 /* Convert length of symlink */
1670 len = ntohl(*p++);
c957c526 1671 if (len >= rcvbuf->page_len) {
fe82a183 1672 dprintk("nfs: server returned giant symlink!\n");
1da177e4
LT
1673 return -ENAMETOOLONG;
1674 }
1675
1676 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1677 if (iov->iov_len < hdrlen) {
fe82a183 1678 dprintk("NFS: READLINK reply header overflowed:"
c957c526 1679 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1680 return -errno_NFSERR_IO;
1681 } else if (iov->iov_len != hdrlen) {
fe82a183
CL
1682 dprintk("NFS: READLINK header is short. "
1683 "iovec will be shifted.\n");
1da177e4
LT
1684 xdr_shift_buf(rcvbuf, iov->iov_len - hdrlen);
1685 }
1686 recvd = req->rq_rcv_buf.len - hdrlen;
1687 if (recvd < len) {
fe82a183 1688 dprintk("NFS: server cheating in readlink reply: "
1da177e4
LT
1689 "count %u > recvd %u\n", len, recvd);
1690 return -EIO;
1691 }
1692
b4687da7 1693 xdr_terminate_string(rcvbuf, len);
1da177e4
LT
1694 return 0;
1695}
1696
1697/*
1698 * Decode READ reply
1699 */
1700static int
d61005a6 1701nfs3_xdr_readres(struct rpc_rqst *req, __be32 *p, struct nfs_readres *res)
1da177e4
LT
1702{
1703 struct kvec *iov = req->rq_rcv_buf.head;
c957c526
CL
1704 size_t hdrlen;
1705 u32 count, ocount, recvd;
1706 int status;
1da177e4
LT
1707
1708 status = ntohl(*p++);
1709 p = xdr_decode_post_op_attr(p, res->fattr);
1710
1711 if (status != 0)
856dff3d 1712 return nfs_stat_to_errno(status);
1da177e4 1713
c957c526 1714 /* Decode reply count and EOF flag. NFSv3 is somewhat redundant
1da177e4
LT
1715 * in that it puts the count both in the res struct and in the
1716 * opaque data count. */
1717 count = ntohl(*p++);
1718 res->eof = ntohl(*p++);
1719 ocount = ntohl(*p++);
1720
1721 if (ocount != count) {
fe82a183 1722 dprintk("NFS: READ count doesn't match RPC opaque count.\n");
1da177e4
LT
1723 return -errno_NFSERR_IO;
1724 }
1725
1726 hdrlen = (u8 *) p - (u8 *) iov->iov_base;
1727 if (iov->iov_len < hdrlen) {
fe82a183 1728 dprintk("NFS: READ reply header overflowed:"
c957c526 1729 "length %Zu > %Zu\n", hdrlen, iov->iov_len);
1da177e4
LT
1730 return -errno_NFSERR_IO;
1731 } else if (iov->iov_len != hdrlen) {
1732 dprintk("NFS: READ header is short. iovec will be shifted.\n");
1733 xdr_shift_buf(&req->rq_rcv_buf, iov->iov_len - hdrlen);
1734 }
1735
1736 recvd = req->rq_rcv_buf.len - hdrlen;
1737 if (count > recvd) {
fe82a183 1738 dprintk("NFS: server cheating in read reply: "
c957c526 1739 "count %u > recvd %u\n", count, recvd);
1da177e4
LT
1740 count = recvd;
1741 res->eof = 0;
1742 }
1743
1744 if (count < res->count)
1745 res->count = count;
1746
1747 return count;
1748}
1749
1750/*
1751 * Decode WRITE response
1752 */
1753static int
d61005a6 1754nfs3_xdr_writeres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
1755{
1756 int status;
1757
1758 status = ntohl(*p++);
1759 p = xdr_decode_wcc_data(p, res->fattr);
1760
1761 if (status != 0)
856dff3d 1762 return nfs_stat_to_errno(status);
1da177e4
LT
1763
1764 res->count = ntohl(*p++);
1765 res->verf->committed = (enum nfs3_stable_how)ntohl(*p++);
1766 res->verf->verifier[0] = *p++;
1767 res->verf->verifier[1] = *p++;
1768
1769 return res->count;
1770}
1771
1772/*
1773 * Decode a CREATE response
1774 */
1775static int
d61005a6 1776nfs3_xdr_createres(struct rpc_rqst *req, __be32 *p, struct nfs3_diropres *res)
1da177e4
LT
1777{
1778 int status;
1779
1780 status = ntohl(*p++);
1781 if (status == 0) {
1782 if (*p++) {
1783 if (!(p = xdr_decode_fhandle(p, res->fh)))
1784 return -errno_NFSERR_IO;
1785 p = xdr_decode_post_op_attr(p, res->fattr);
1786 } else {
1787 memset(res->fh, 0, sizeof(*res->fh));
1788 /* Do decode post_op_attr but set it to NULL */
1789 p = xdr_decode_post_op_attr(p, res->fattr);
1790 res->fattr->valid = 0;
1791 }
1792 } else {
856dff3d 1793 status = nfs_stat_to_errno(status);
1da177e4
LT
1794 }
1795 p = xdr_decode_wcc_data(p, res->dir_attr);
1796 return status;
1797}
1798
1799/*
1800 * Decode RENAME reply
1801 */
1802static int
e8582a8b 1803nfs3_xdr_renameres(struct rpc_rqst *req, __be32 *p, struct nfs_renameres *res)
1da177e4
LT
1804{
1805 int status;
1806
1807 if ((status = ntohl(*p++)) != 0)
856dff3d 1808 status = nfs_stat_to_errno(status);
e8582a8b
JL
1809 p = xdr_decode_wcc_data(p, res->old_fattr);
1810 p = xdr_decode_wcc_data(p, res->new_fattr);
1da177e4
LT
1811 return status;
1812}
1813
1814/*
1815 * Decode LINK reply
1816 */
1817static int
d61005a6 1818nfs3_xdr_linkres(struct rpc_rqst *req, __be32 *p, struct nfs3_linkres *res)
1da177e4
LT
1819{
1820 int status;
1821
1822 if ((status = ntohl(*p++)) != 0)
856dff3d 1823 status = nfs_stat_to_errno(status);
1da177e4
LT
1824 p = xdr_decode_post_op_attr(p, res->fattr);
1825 p = xdr_decode_wcc_data(p, res->dir_attr);
1826 return status;
1827}
1828
1829/*
1830 * Decode FSSTAT reply
1831 */
1832static int
d61005a6 1833nfs3_xdr_fsstatres(struct rpc_rqst *req, __be32 *p, struct nfs_fsstat *res)
1da177e4
LT
1834{
1835 int status;
1836
1837 status = ntohl(*p++);
1838
1839 p = xdr_decode_post_op_attr(p, res->fattr);
1840 if (status != 0)
856dff3d 1841 return nfs_stat_to_errno(status);
1da177e4
LT
1842
1843 p = xdr_decode_hyper(p, &res->tbytes);
1844 p = xdr_decode_hyper(p, &res->fbytes);
1845 p = xdr_decode_hyper(p, &res->abytes);
1846 p = xdr_decode_hyper(p, &res->tfiles);
1847 p = xdr_decode_hyper(p, &res->ffiles);
1848 p = xdr_decode_hyper(p, &res->afiles);
1849
1850 /* ignore invarsec */
1851 return 0;
1852}
1853
1854/*
1855 * Decode FSINFO reply
1856 */
1857static int
d61005a6 1858nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1da177e4
LT
1859{
1860 int status;
1861
1862 status = ntohl(*p++);
1863
1864 p = xdr_decode_post_op_attr(p, res->fattr);
1865 if (status != 0)
856dff3d 1866 return nfs_stat_to_errno(status);
1da177e4
LT
1867
1868 res->rtmax = ntohl(*p++);
1869 res->rtpref = ntohl(*p++);
1870 res->rtmult = ntohl(*p++);
1871 res->wtmax = ntohl(*p++);
1872 res->wtpref = ntohl(*p++);
1873 res->wtmult = ntohl(*p++);
1874 res->dtpref = ntohl(*p++);
1875 p = xdr_decode_hyper(p, &res->maxfilesize);
6b96724e 1876 p = xdr_decode_time3(p, &res->time_delta);
1da177e4 1877
6b96724e 1878 /* ignore properties */
1da177e4
LT
1879 res->lease_time = 0;
1880 return 0;
1881}
1882
1883/*
1884 * Decode PATHCONF reply
1885 */
1886static int
d61005a6 1887nfs3_xdr_pathconfres(struct rpc_rqst *req, __be32 *p, struct nfs_pathconf *res)
1da177e4
LT
1888{
1889 int status;
1890
1891 status = ntohl(*p++);
1892
1893 p = xdr_decode_post_op_attr(p, res->fattr);
1894 if (status != 0)
856dff3d 1895 return nfs_stat_to_errno(status);
1da177e4
LT
1896 res->max_link = ntohl(*p++);
1897 res->max_namelen = ntohl(*p++);
1898
1899 /* ignore remaining fields */
1900 return 0;
1901}
1902
1903/*
1904 * Decode COMMIT reply
1905 */
1906static int
d61005a6 1907nfs3_xdr_commitres(struct rpc_rqst *req, __be32 *p, struct nfs_writeres *res)
1da177e4
LT
1908{
1909 int status;
1910
1911 status = ntohl(*p++);
1912 p = xdr_decode_wcc_data(p, res->fattr);
1913 if (status != 0)
856dff3d 1914 return nfs_stat_to_errno(status);
1da177e4
LT
1915
1916 res->verf->verifier[0] = *p++;
1917 res->verf->verifier[1] = *p++;
1918 return 0;
1919}
1920
b7fa0554
AG
1921#ifdef CONFIG_NFS_V3_ACL
1922/*
1923 * Decode GETACL reply
1924 */
1925static int
d61005a6 1926nfs3_xdr_getaclres(struct rpc_rqst *req, __be32 *p,
b7fa0554
AG
1927 struct nfs3_getaclres *res)
1928{
1929 struct xdr_buf *buf = &req->rq_rcv_buf;
1930 int status = ntohl(*p++);
1931 struct posix_acl **acl;
1932 unsigned int *aclcnt;
1933 int err, base;
1934
1935 if (status != 0)
856dff3d 1936 return nfs_stat_to_errno(status);
b7fa0554
AG
1937 p = xdr_decode_post_op_attr(p, res->fattr);
1938 res->mask = ntohl(*p++);
1939 if (res->mask & ~(NFS_ACL|NFS_ACLCNT|NFS_DFACL|NFS_DFACLCNT))
1940 return -EINVAL;
1941 base = (char *)p - (char *)req->rq_rcv_buf.head->iov_base;
1942
1943 acl = (res->mask & NFS_ACL) ? &res->acl_access : NULL;
1944 aclcnt = (res->mask & NFS_ACLCNT) ? &res->acl_access_count : NULL;
1945 err = nfsacl_decode(buf, base, aclcnt, acl);
1946
1947 acl = (res->mask & NFS_DFACL) ? &res->acl_default : NULL;
1948 aclcnt = (res->mask & NFS_DFACLCNT) ? &res->acl_default_count : NULL;
1949 if (err > 0)
1950 err = nfsacl_decode(buf, base + err, aclcnt, acl);
1951 return (err > 0) ? 0 : err;
1952}
1953
1954/*
1955 * Decode setacl reply.
1956 */
1957static int
d61005a6 1958nfs3_xdr_setaclres(struct rpc_rqst *req, __be32 *p, struct nfs_fattr *fattr)
b7fa0554
AG
1959{
1960 int status = ntohl(*p++);
1961
1962 if (status)
856dff3d 1963 return nfs_stat_to_errno(status);
b7fa0554
AG
1964 xdr_decode_post_op_attr(p, fattr);
1965 return 0;
1966}
1967#endif /* CONFIG_NFS_V3_ACL */
1968
1da177e4
LT
1969#define PROC(proc, argtype, restype, timer) \
1970[NFS3PROC_##proc] = { \
1971 .p_proc = NFS3PROC_##proc, \
1972 .p_encode = (kxdrproc_t) nfs3_xdr_##argtype, \
1973 .p_decode = (kxdrproc_t) nfs3_xdr_##restype, \
2bea90d4
CL
1974 .p_arglen = NFS3_##argtype##_sz, \
1975 .p_replen = NFS3_##restype##_sz, \
cc0175c1
CL
1976 .p_timer = timer, \
1977 .p_statidx = NFS3PROC_##proc, \
1978 .p_name = #proc, \
1da177e4
LT
1979 }
1980
1981struct rpc_procinfo nfs3_procedures[] = {
1982 PROC(GETATTR, fhandle, attrstat, 1),
1983 PROC(SETATTR, sattrargs, wccstat, 0),
1984 PROC(LOOKUP, diropargs, lookupres, 2),
1985 PROC(ACCESS, accessargs, accessres, 1),
1986 PROC(READLINK, readlinkargs, readlinkres, 3),
1987 PROC(READ, readargs, readres, 3),
1988 PROC(WRITE, writeargs, writeres, 4),
1989 PROC(CREATE, createargs, createres, 0),
1990 PROC(MKDIR, mkdirargs, createres, 0),
1991 PROC(SYMLINK, symlinkargs, createres, 0),
1992 PROC(MKNOD, mknodargs, createres, 0),
4fdc17b2 1993 PROC(REMOVE, removeargs, removeres, 0),
1da177e4
LT
1994 PROC(RMDIR, diropargs, wccstat, 0),
1995 PROC(RENAME, renameargs, renameres, 0),
1996 PROC(LINK, linkargs, linkres, 0),
1997 PROC(READDIR, readdirargs, readdirres, 3),
1998 PROC(READDIRPLUS, readdirargs, readdirres, 3),
1999 PROC(FSSTAT, fhandle, fsstatres, 0),
2000 PROC(FSINFO, fhandle, fsinfores, 0),
2001 PROC(PATHCONF, fhandle, pathconfres, 0),
2002 PROC(COMMIT, commitargs, commitres, 5),
2003};
2004
2005struct rpc_version nfs_version3 = {
2006 .number = 3,
e8c96f8c 2007 .nrprocs = ARRAY_SIZE(nfs3_procedures),
1da177e4
LT
2008 .procs = nfs3_procedures
2009};
2010
b7fa0554
AG
2011#ifdef CONFIG_NFS_V3_ACL
2012static struct rpc_procinfo nfs3_acl_procedures[] = {
2013 [ACLPROC3_GETACL] = {
2014 .p_proc = ACLPROC3_GETACL,
2015 .p_encode = (kxdrproc_t) nfs3_xdr_getaclargs,
2016 .p_decode = (kxdrproc_t) nfs3_xdr_getaclres,
2bea90d4
CL
2017 .p_arglen = ACL3_getaclargs_sz,
2018 .p_replen = ACL3_getaclres_sz,
b7fa0554 2019 .p_timer = 1,
cc0175c1 2020 .p_name = "GETACL",
b7fa0554
AG
2021 },
2022 [ACLPROC3_SETACL] = {
2023 .p_proc = ACLPROC3_SETACL,
2024 .p_encode = (kxdrproc_t) nfs3_xdr_setaclargs,
2025 .p_decode = (kxdrproc_t) nfs3_xdr_setaclres,
2bea90d4
CL
2026 .p_arglen = ACL3_setaclargs_sz,
2027 .p_replen = ACL3_setaclres_sz,
b7fa0554 2028 .p_timer = 0,
cc0175c1 2029 .p_name = "SETACL",
b7fa0554
AG
2030 },
2031};
2032
2033struct rpc_version nfsacl_version3 = {
2034 .number = 3,
2035 .nrprocs = sizeof(nfs3_acl_procedures)/
2036 sizeof(nfs3_acl_procedures[0]),
2037 .procs = nfs3_acl_procedures,
2038};
2039#endif /* CONFIG_NFS_V3_ACL */