NFS: Add COPY nfs operation
[deliverable/linux.git] / fs / nfs / nfs42xdr.c
1 /*
2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
3 */
4 #ifndef __LINUX_FS_NFS_NFS4_2XDR_H
5 #define __LINUX_FS_NFS_NFS4_2XDR_H
6
7 #include "nfs42.h"
8
9 #define encode_fallocate_maxsz (encode_stateid_maxsz + \
10 2 /* offset */ + \
11 2 /* length */)
12 #define NFS42_WRITE_RES_SIZE (1 /* wr_callback_id size */ +\
13 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
14 2 /* wr_count */ + \
15 1 /* wr_committed */ + \
16 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
17 #define encode_allocate_maxsz (op_encode_hdr_maxsz + \
18 encode_fallocate_maxsz)
19 #define decode_allocate_maxsz (op_decode_hdr_maxsz)
20 #define encode_copy_maxsz (op_encode_hdr_maxsz + \
21 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
22 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
23 2 + 2 + 2 + 1 + 1 + 1)
24 #define decode_copy_maxsz (op_decode_hdr_maxsz + \
25 NFS42_WRITE_RES_SIZE + \
26 1 /* cr_consecutive */ + \
27 1 /* cr_synchronous */)
28 #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
29 encode_fallocate_maxsz)
30 #define decode_deallocate_maxsz (op_decode_hdr_maxsz)
31 #define encode_seek_maxsz (op_encode_hdr_maxsz + \
32 encode_stateid_maxsz + \
33 2 /* offset */ + \
34 1 /* whence */)
35 #define decode_seek_maxsz (op_decode_hdr_maxsz + \
36 1 /* eof */ + \
37 1 /* whence */ + \
38 2 /* offset */ + \
39 2 /* length */)
40 #define encode_io_info_maxsz 4
41 #define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \
42 2 /* offset */ + \
43 2 /* length */ + \
44 encode_stateid_maxsz + \
45 encode_io_info_maxsz + \
46 encode_io_info_maxsz + \
47 1 /* opaque devaddr4 length */ + \
48 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
49 #define decode_layoutstats_maxsz (op_decode_hdr_maxsz)
50 #define encode_clone_maxsz (encode_stateid_maxsz + \
51 encode_stateid_maxsz + \
52 2 /* src offset */ + \
53 2 /* dst offset */ + \
54 2 /* count */)
55 #define decode_clone_maxsz (op_decode_hdr_maxsz)
56
57 #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \
58 encode_putfh_maxsz + \
59 encode_allocate_maxsz + \
60 encode_getattr_maxsz)
61 #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \
62 decode_putfh_maxsz + \
63 decode_allocate_maxsz + \
64 decode_getattr_maxsz)
65 #define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \
66 encode_putfh_maxsz + \
67 encode_savefh_maxsz + \
68 encode_putfh_maxsz + \
69 encode_copy_maxsz)
70 #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \
71 decode_putfh_maxsz + \
72 decode_savefh_maxsz + \
73 decode_putfh_maxsz + \
74 decode_copy_maxsz)
75 #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \
76 encode_putfh_maxsz + \
77 encode_deallocate_maxsz + \
78 encode_getattr_maxsz)
79 #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \
80 decode_putfh_maxsz + \
81 decode_deallocate_maxsz + \
82 decode_getattr_maxsz)
83 #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
84 encode_putfh_maxsz + \
85 encode_seek_maxsz)
86 #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \
87 decode_putfh_maxsz + \
88 decode_seek_maxsz)
89 #define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \
90 encode_sequence_maxsz + \
91 encode_putfh_maxsz + \
92 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
93 #define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \
94 decode_sequence_maxsz + \
95 decode_putfh_maxsz + \
96 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
97 #define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \
98 encode_sequence_maxsz + \
99 encode_putfh_maxsz + \
100 encode_savefh_maxsz + \
101 encode_putfh_maxsz + \
102 encode_clone_maxsz + \
103 encode_getattr_maxsz)
104 #define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \
105 decode_sequence_maxsz + \
106 decode_putfh_maxsz + \
107 decode_savefh_maxsz + \
108 decode_putfh_maxsz + \
109 decode_clone_maxsz + \
110 decode_getattr_maxsz)
111
112 static void encode_fallocate(struct xdr_stream *xdr,
113 struct nfs42_falloc_args *args)
114 {
115 encode_nfs4_stateid(xdr, &args->falloc_stateid);
116 encode_uint64(xdr, args->falloc_offset);
117 encode_uint64(xdr, args->falloc_length);
118 }
119
120 static void encode_allocate(struct xdr_stream *xdr,
121 struct nfs42_falloc_args *args,
122 struct compound_hdr *hdr)
123 {
124 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
125 encode_fallocate(xdr, args);
126 }
127
128 static void encode_copy(struct xdr_stream *xdr,
129 struct nfs42_copy_args *args,
130 struct compound_hdr *hdr)
131 {
132 encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
133 encode_nfs4_stateid(xdr, &args->src_stateid);
134 encode_nfs4_stateid(xdr, &args->dst_stateid);
135
136 encode_uint64(xdr, args->src_pos);
137 encode_uint64(xdr, args->dst_pos);
138 encode_uint64(xdr, args->count);
139
140 encode_uint32(xdr, 1); /* consecutive = true */
141 encode_uint32(xdr, 1); /* synchronous = true */
142 encode_uint32(xdr, 0); /* src server list */
143 }
144
145 static void encode_deallocate(struct xdr_stream *xdr,
146 struct nfs42_falloc_args *args,
147 struct compound_hdr *hdr)
148 {
149 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
150 encode_fallocate(xdr, args);
151 }
152
153 static void encode_seek(struct xdr_stream *xdr,
154 struct nfs42_seek_args *args,
155 struct compound_hdr *hdr)
156 {
157 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
158 encode_nfs4_stateid(xdr, &args->sa_stateid);
159 encode_uint64(xdr, args->sa_offset);
160 encode_uint32(xdr, args->sa_what);
161 }
162
163 static void encode_layoutstats(struct xdr_stream *xdr,
164 struct nfs42_layoutstat_args *args,
165 struct nfs42_layoutstat_devinfo *devinfo,
166 struct compound_hdr *hdr)
167 {
168 __be32 *p;
169
170 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
171 p = reserve_space(xdr, 8 + 8);
172 p = xdr_encode_hyper(p, devinfo->offset);
173 p = xdr_encode_hyper(p, devinfo->length);
174 encode_nfs4_stateid(xdr, &args->stateid);
175 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
176 p = xdr_encode_hyper(p, devinfo->read_count);
177 p = xdr_encode_hyper(p, devinfo->read_bytes);
178 p = xdr_encode_hyper(p, devinfo->write_count);
179 p = xdr_encode_hyper(p, devinfo->write_bytes);
180 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
181 NFS4_DEVICEID4_SIZE);
182 /* Encode layoutupdate4 */
183 *p++ = cpu_to_be32(devinfo->layout_type);
184 if (devinfo->layoutstats_encode != NULL)
185 devinfo->layoutstats_encode(xdr, args, devinfo);
186 else
187 encode_uint32(xdr, 0);
188 }
189
190 static void encode_clone(struct xdr_stream *xdr,
191 struct nfs42_clone_args *args,
192 struct compound_hdr *hdr)
193 {
194 __be32 *p;
195
196 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
197 encode_nfs4_stateid(xdr, &args->src_stateid);
198 encode_nfs4_stateid(xdr, &args->dst_stateid);
199 p = reserve_space(xdr, 3*8);
200 p = xdr_encode_hyper(p, args->src_offset);
201 p = xdr_encode_hyper(p, args->dst_offset);
202 xdr_encode_hyper(p, args->count);
203 }
204
205 /*
206 * Encode ALLOCATE request
207 */
208 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
209 struct xdr_stream *xdr,
210 struct nfs42_falloc_args *args)
211 {
212 struct compound_hdr hdr = {
213 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
214 };
215
216 encode_compound_hdr(xdr, req, &hdr);
217 encode_sequence(xdr, &args->seq_args, &hdr);
218 encode_putfh(xdr, args->falloc_fh, &hdr);
219 encode_allocate(xdr, args, &hdr);
220 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
221 encode_nops(&hdr);
222 }
223
224 /*
225 * Encode COPY request
226 */
227 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
228 struct xdr_stream *xdr,
229 struct nfs42_copy_args *args)
230 {
231 struct compound_hdr hdr = {
232 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
233 };
234
235 encode_compound_hdr(xdr, req, &hdr);
236 encode_sequence(xdr, &args->seq_args, &hdr);
237 encode_putfh(xdr, args->src_fh, &hdr);
238 encode_savefh(xdr, &hdr);
239 encode_putfh(xdr, args->dst_fh, &hdr);
240 encode_copy(xdr, args, &hdr);
241 encode_nops(&hdr);
242 }
243
244 /*
245 * Encode DEALLOCATE request
246 */
247 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
248 struct xdr_stream *xdr,
249 struct nfs42_falloc_args *args)
250 {
251 struct compound_hdr hdr = {
252 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
253 };
254
255 encode_compound_hdr(xdr, req, &hdr);
256 encode_sequence(xdr, &args->seq_args, &hdr);
257 encode_putfh(xdr, args->falloc_fh, &hdr);
258 encode_deallocate(xdr, args, &hdr);
259 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
260 encode_nops(&hdr);
261 }
262
263 /*
264 * Encode SEEK request
265 */
266 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
267 struct xdr_stream *xdr,
268 struct nfs42_seek_args *args)
269 {
270 struct compound_hdr hdr = {
271 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
272 };
273
274 encode_compound_hdr(xdr, req, &hdr);
275 encode_sequence(xdr, &args->seq_args, &hdr);
276 encode_putfh(xdr, args->sa_fh, &hdr);
277 encode_seek(xdr, args, &hdr);
278 encode_nops(&hdr);
279 }
280
281 /*
282 * Encode LAYOUTSTATS request
283 */
284 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
285 struct xdr_stream *xdr,
286 struct nfs42_layoutstat_args *args)
287 {
288 int i;
289
290 struct compound_hdr hdr = {
291 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
292 };
293
294 encode_compound_hdr(xdr, req, &hdr);
295 encode_sequence(xdr, &args->seq_args, &hdr);
296 encode_putfh(xdr, args->fh, &hdr);
297 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
298 for (i = 0; i < args->num_dev; i++)
299 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
300 encode_nops(&hdr);
301 }
302
303 /*
304 * Encode CLONE request
305 */
306 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
307 struct xdr_stream *xdr,
308 struct nfs42_clone_args *args)
309 {
310 struct compound_hdr hdr = {
311 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
312 };
313
314 encode_compound_hdr(xdr, req, &hdr);
315 encode_sequence(xdr, &args->seq_args, &hdr);
316 encode_putfh(xdr, args->src_fh, &hdr);
317 encode_savefh(xdr, &hdr);
318 encode_putfh(xdr, args->dst_fh, &hdr);
319 encode_clone(xdr, args, &hdr);
320 encode_getfattr(xdr, args->dst_bitmask, &hdr);
321 encode_nops(&hdr);
322 }
323
324 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
325 {
326 return decode_op_hdr(xdr, OP_ALLOCATE);
327 }
328
329 static int decode_write_response(struct xdr_stream *xdr,
330 struct nfs42_write_res *res)
331 {
332 __be32 *p;
333 int stateids;
334
335 p = xdr_inline_decode(xdr, 4 + 8 + 4);
336 if (unlikely(!p))
337 goto out_overflow;
338
339 stateids = be32_to_cpup(p++);
340 p = xdr_decode_hyper(p, &res->count);
341 res->verifier.committed = be32_to_cpup(p);
342 return decode_verifier(xdr, &res->verifier.verifier);
343
344 out_overflow:
345 print_overflow_msg(__func__, xdr);
346 return -EIO;
347 }
348
349 static int decode_copy_requirements(struct xdr_stream *xdr,
350 struct nfs42_copy_res *res) {
351 __be32 *p;
352
353 p = xdr_inline_decode(xdr, 4 + 4);
354 if (unlikely(!p))
355 goto out_overflow;
356
357 res->consecutive = be32_to_cpup(p++);
358 res->synchronous = be32_to_cpup(p++);
359 return 0;
360 out_overflow:
361 print_overflow_msg(__func__, xdr);
362 return -EIO;
363 }
364
365 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
366 {
367 int status;
368
369 status = decode_op_hdr(xdr, OP_COPY);
370 if (status == NFS4ERR_OFFLOAD_NO_REQS) {
371 status = decode_copy_requirements(xdr, res);
372 if (status)
373 return status;
374 return NFS4ERR_OFFLOAD_NO_REQS;
375 } else if (status)
376 return status;
377
378 status = decode_write_response(xdr, &res->write_res);
379 if (status)
380 return status;
381
382 return decode_copy_requirements(xdr, res);
383 }
384
385 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
386 {
387 return decode_op_hdr(xdr, OP_DEALLOCATE);
388 }
389
390 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
391 {
392 int status;
393 __be32 *p;
394
395 status = decode_op_hdr(xdr, OP_SEEK);
396 if (status)
397 return status;
398
399 p = xdr_inline_decode(xdr, 4 + 8);
400 if (unlikely(!p))
401 goto out_overflow;
402
403 res->sr_eof = be32_to_cpup(p++);
404 p = xdr_decode_hyper(p, &res->sr_offset);
405 return 0;
406
407 out_overflow:
408 print_overflow_msg(__func__, xdr);
409 return -EIO;
410 }
411
412 static int decode_layoutstats(struct xdr_stream *xdr)
413 {
414 return decode_op_hdr(xdr, OP_LAYOUTSTATS);
415 }
416
417 static int decode_clone(struct xdr_stream *xdr)
418 {
419 return decode_op_hdr(xdr, OP_CLONE);
420 }
421
422 /*
423 * Decode ALLOCATE request
424 */
425 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
426 struct xdr_stream *xdr,
427 struct nfs42_falloc_res *res)
428 {
429 struct compound_hdr hdr;
430 int status;
431
432 status = decode_compound_hdr(xdr, &hdr);
433 if (status)
434 goto out;
435 status = decode_sequence(xdr, &res->seq_res, rqstp);
436 if (status)
437 goto out;
438 status = decode_putfh(xdr);
439 if (status)
440 goto out;
441 status = decode_allocate(xdr, res);
442 if (status)
443 goto out;
444 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
445 out:
446 return status;
447 }
448
449 /*
450 * Decode COPY response
451 */
452 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
453 struct xdr_stream *xdr,
454 struct nfs42_copy_res *res)
455 {
456 struct compound_hdr hdr;
457 int status;
458
459 status = decode_compound_hdr(xdr, &hdr);
460 if (status)
461 goto out;
462 status = decode_sequence(xdr, &res->seq_res, rqstp);
463 if (status)
464 goto out;
465 status = decode_putfh(xdr);
466 if (status)
467 goto out;
468 status = decode_savefh(xdr);
469 if (status)
470 goto out;
471 status = decode_putfh(xdr);
472 if (status)
473 goto out;
474 status = decode_copy(xdr, res);
475 out:
476 return status;
477 }
478
479 /*
480 * Decode DEALLOCATE request
481 */
482 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
483 struct xdr_stream *xdr,
484 struct nfs42_falloc_res *res)
485 {
486 struct compound_hdr hdr;
487 int status;
488
489 status = decode_compound_hdr(xdr, &hdr);
490 if (status)
491 goto out;
492 status = decode_sequence(xdr, &res->seq_res, rqstp);
493 if (status)
494 goto out;
495 status = decode_putfh(xdr);
496 if (status)
497 goto out;
498 status = decode_deallocate(xdr, res);
499 if (status)
500 goto out;
501 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
502 out:
503 return status;
504 }
505
506 /*
507 * Decode SEEK request
508 */
509 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
510 struct xdr_stream *xdr,
511 struct nfs42_seek_res *res)
512 {
513 struct compound_hdr hdr;
514 int status;
515
516 status = decode_compound_hdr(xdr, &hdr);
517 if (status)
518 goto out;
519 status = decode_sequence(xdr, &res->seq_res, rqstp);
520 if (status)
521 goto out;
522 status = decode_putfh(xdr);
523 if (status)
524 goto out;
525 status = decode_seek(xdr, res);
526 out:
527 return status;
528 }
529
530 /*
531 * Decode LAYOUTSTATS request
532 */
533 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
534 struct xdr_stream *xdr,
535 struct nfs42_layoutstat_res *res)
536 {
537 struct compound_hdr hdr;
538 int status, i;
539
540 status = decode_compound_hdr(xdr, &hdr);
541 if (status)
542 goto out;
543 status = decode_sequence(xdr, &res->seq_res, rqstp);
544 if (status)
545 goto out;
546 status = decode_putfh(xdr);
547 if (status)
548 goto out;
549 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
550 for (i = 0; i < res->num_dev; i++) {
551 status = decode_layoutstats(xdr);
552 if (status)
553 goto out;
554 }
555 out:
556 res->rpc_status = status;
557 return status;
558 }
559
560 /*
561 * Decode CLONE request
562 */
563 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
564 struct xdr_stream *xdr,
565 struct nfs42_clone_res *res)
566 {
567 struct compound_hdr hdr;
568 int status;
569
570 status = decode_compound_hdr(xdr, &hdr);
571 if (status)
572 goto out;
573 status = decode_sequence(xdr, &res->seq_res, rqstp);
574 if (status)
575 goto out;
576 status = decode_putfh(xdr);
577 if (status)
578 goto out;
579 status = decode_savefh(xdr);
580 if (status)
581 goto out;
582 status = decode_putfh(xdr);
583 if (status)
584 goto out;
585 status = decode_clone(xdr);
586 if (status)
587 goto out;
588 status = decode_getfattr(xdr, res->dst_fattr, res->server);
589
590 out:
591 res->rpc_status = status;
592 return status;
593 }
594
595 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
This page took 0.043983 seconds and 5 git commands to generate.