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