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