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