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