Merge tag 'md/4.13-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/shli/md
[sfrench/cifs-2.6.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                                          encode_commit_maxsz)
71 #define NFS4_dec_copy_sz                (compound_decode_hdr_maxsz + \
72                                          decode_putfh_maxsz + \
73                                          decode_savefh_maxsz + \
74                                          decode_putfh_maxsz + \
75                                          decode_copy_maxsz + \
76                                          decode_commit_maxsz)
77 #define NFS4_enc_deallocate_sz          (compound_encode_hdr_maxsz + \
78                                          encode_putfh_maxsz + \
79                                          encode_deallocate_maxsz + \
80                                          encode_getattr_maxsz)
81 #define NFS4_dec_deallocate_sz          (compound_decode_hdr_maxsz + \
82                                          decode_putfh_maxsz + \
83                                          decode_deallocate_maxsz + \
84                                          decode_getattr_maxsz)
85 #define NFS4_enc_seek_sz                (compound_encode_hdr_maxsz + \
86                                          encode_putfh_maxsz + \
87                                          encode_seek_maxsz)
88 #define NFS4_dec_seek_sz                (compound_decode_hdr_maxsz + \
89                                          decode_putfh_maxsz + \
90                                          decode_seek_maxsz)
91 #define NFS4_enc_layoutstats_sz         (compound_encode_hdr_maxsz + \
92                                          encode_sequence_maxsz + \
93                                          encode_putfh_maxsz + \
94                                          PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
95 #define NFS4_dec_layoutstats_sz         (compound_decode_hdr_maxsz + \
96                                          decode_sequence_maxsz + \
97                                          decode_putfh_maxsz + \
98                                          PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
99 #define NFS4_enc_clone_sz               (compound_encode_hdr_maxsz + \
100                                          encode_sequence_maxsz + \
101                                          encode_putfh_maxsz + \
102                                          encode_savefh_maxsz + \
103                                          encode_putfh_maxsz + \
104                                          encode_clone_maxsz + \
105                                          encode_getattr_maxsz)
106 #define NFS4_dec_clone_sz               (compound_decode_hdr_maxsz + \
107                                          decode_sequence_maxsz + \
108                                          decode_putfh_maxsz + \
109                                          decode_savefh_maxsz + \
110                                          decode_putfh_maxsz + \
111                                          decode_clone_maxsz + \
112                                          decode_getattr_maxsz)
113
114 static void encode_fallocate(struct xdr_stream *xdr,
115                              const struct nfs42_falloc_args *args)
116 {
117         encode_nfs4_stateid(xdr, &args->falloc_stateid);
118         encode_uint64(xdr, args->falloc_offset);
119         encode_uint64(xdr, args->falloc_length);
120 }
121
122 static void encode_allocate(struct xdr_stream *xdr,
123                             const struct nfs42_falloc_args *args,
124                             struct compound_hdr *hdr)
125 {
126         encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
127         encode_fallocate(xdr, args);
128 }
129
130 static void encode_copy(struct xdr_stream *xdr,
131                         const struct nfs42_copy_args *args,
132                         struct compound_hdr *hdr)
133 {
134         encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
135         encode_nfs4_stateid(xdr, &args->src_stateid);
136         encode_nfs4_stateid(xdr, &args->dst_stateid);
137
138         encode_uint64(xdr, args->src_pos);
139         encode_uint64(xdr, args->dst_pos);
140         encode_uint64(xdr, args->count);
141
142         encode_uint32(xdr, 1); /* consecutive = true */
143         encode_uint32(xdr, 1); /* synchronous = true */
144         encode_uint32(xdr, 0); /* src server list */
145 }
146
147 static void encode_deallocate(struct xdr_stream *xdr,
148                               const struct nfs42_falloc_args *args,
149                               struct compound_hdr *hdr)
150 {
151         encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
152         encode_fallocate(xdr, args);
153 }
154
155 static void encode_seek(struct xdr_stream *xdr,
156                         const struct nfs42_seek_args *args,
157                         struct compound_hdr *hdr)
158 {
159         encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
160         encode_nfs4_stateid(xdr, &args->sa_stateid);
161         encode_uint64(xdr, args->sa_offset);
162         encode_uint32(xdr, args->sa_what);
163 }
164
165 static void encode_layoutstats(struct xdr_stream *xdr,
166                                const struct nfs42_layoutstat_args *args,
167                                struct nfs42_layoutstat_devinfo *devinfo,
168                                struct compound_hdr *hdr)
169 {
170         __be32 *p;
171
172         encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
173         p = reserve_space(xdr, 8 + 8);
174         p = xdr_encode_hyper(p, devinfo->offset);
175         p = xdr_encode_hyper(p, devinfo->length);
176         encode_nfs4_stateid(xdr, &args->stateid);
177         p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
178         p = xdr_encode_hyper(p, devinfo->read_count);
179         p = xdr_encode_hyper(p, devinfo->read_bytes);
180         p = xdr_encode_hyper(p, devinfo->write_count);
181         p = xdr_encode_hyper(p, devinfo->write_bytes);
182         p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
183                         NFS4_DEVICEID4_SIZE);
184         /* Encode layoutupdate4 */
185         *p++ = cpu_to_be32(devinfo->layout_type);
186         if (devinfo->ld_private.ops)
187                 devinfo->ld_private.ops->encode(xdr, args,
188                                 &devinfo->ld_private);
189         else
190                 encode_uint32(xdr, 0);
191 }
192
193 static void encode_clone(struct xdr_stream *xdr,
194                          const struct nfs42_clone_args *args,
195                          struct compound_hdr *hdr)
196 {
197         __be32 *p;
198
199         encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
200         encode_nfs4_stateid(xdr, &args->src_stateid);
201         encode_nfs4_stateid(xdr, &args->dst_stateid);
202         p = reserve_space(xdr, 3*8);
203         p = xdr_encode_hyper(p, args->src_offset);
204         p = xdr_encode_hyper(p, args->dst_offset);
205         xdr_encode_hyper(p, args->count);
206 }
207
208 /*
209  * Encode ALLOCATE request
210  */
211 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
212                                   struct xdr_stream *xdr,
213                                   const void *data)
214 {
215         const struct nfs42_falloc_args *args = data;
216         struct compound_hdr hdr = {
217                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
218         };
219
220         encode_compound_hdr(xdr, req, &hdr);
221         encode_sequence(xdr, &args->seq_args, &hdr);
222         encode_putfh(xdr, args->falloc_fh, &hdr);
223         encode_allocate(xdr, args, &hdr);
224         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
225         encode_nops(&hdr);
226 }
227
228 static void encode_copy_commit(struct xdr_stream *xdr,
229                           const struct nfs42_copy_args *args,
230                           struct compound_hdr *hdr)
231 {
232         __be32 *p;
233
234         encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
235         p = reserve_space(xdr, 12);
236         p = xdr_encode_hyper(p, args->dst_pos);
237         *p = cpu_to_be32(args->count);
238 }
239
240 /*
241  * Encode COPY request
242  */
243 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
244                               struct xdr_stream *xdr,
245                               const void *data)
246 {
247         const struct nfs42_copy_args *args = data;
248         struct compound_hdr hdr = {
249                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
250         };
251
252         encode_compound_hdr(xdr, req, &hdr);
253         encode_sequence(xdr, &args->seq_args, &hdr);
254         encode_putfh(xdr, args->src_fh, &hdr);
255         encode_savefh(xdr, &hdr);
256         encode_putfh(xdr, args->dst_fh, &hdr);
257         encode_copy(xdr, args, &hdr);
258         encode_copy_commit(xdr, args, &hdr);
259         encode_nops(&hdr);
260 }
261
262 /*
263  * Encode DEALLOCATE request
264  */
265 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
266                                     struct xdr_stream *xdr,
267                                     const void *data)
268 {
269         const struct nfs42_falloc_args *args = data;
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->falloc_fh, &hdr);
277         encode_deallocate(xdr, args, &hdr);
278         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
279         encode_nops(&hdr);
280 }
281
282 /*
283  * Encode SEEK request
284  */
285 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
286                               struct xdr_stream *xdr,
287                               const void *data)
288 {
289         const struct nfs42_seek_args *args = data;
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->sa_fh, &hdr);
297         encode_seek(xdr, args, &hdr);
298         encode_nops(&hdr);
299 }
300
301 /*
302  * Encode LAYOUTSTATS request
303  */
304 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
305                                      struct xdr_stream *xdr,
306                                      const void *data)
307 {
308         const struct nfs42_layoutstat_args *args = data;
309         int i;
310
311         struct compound_hdr hdr = {
312                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
313         };
314
315         encode_compound_hdr(xdr, req, &hdr);
316         encode_sequence(xdr, &args->seq_args, &hdr);
317         encode_putfh(xdr, args->fh, &hdr);
318         WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
319         for (i = 0; i < args->num_dev; i++)
320                 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
321         encode_nops(&hdr);
322 }
323
324 /*
325  * Encode CLONE request
326  */
327 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
328                                struct xdr_stream *xdr,
329                                const void *data)
330 {
331         const struct nfs42_clone_args *args = data;
332         struct compound_hdr hdr = {
333                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
334         };
335
336         encode_compound_hdr(xdr, req, &hdr);
337         encode_sequence(xdr, &args->seq_args, &hdr);
338         encode_putfh(xdr, args->src_fh, &hdr);
339         encode_savefh(xdr, &hdr);
340         encode_putfh(xdr, args->dst_fh, &hdr);
341         encode_clone(xdr, args, &hdr);
342         encode_getfattr(xdr, args->dst_bitmask, &hdr);
343         encode_nops(&hdr);
344 }
345
346 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
347 {
348         return decode_op_hdr(xdr, OP_ALLOCATE);
349 }
350
351 static int decode_write_response(struct xdr_stream *xdr,
352                                  struct nfs42_write_res *res)
353 {
354         __be32 *p;
355
356         p = xdr_inline_decode(xdr, 4 + 8 + 4);
357         if (unlikely(!p))
358                 goto out_overflow;
359
360         /*
361          * We never use asynchronous mode, so warn if a server returns
362          * a stateid.
363          */
364         if (unlikely(*p != 0)) {
365                 pr_err_once("%s: server has set unrequested "
366                                 "asynchronous mode\n", __func__);
367                 return -EREMOTEIO;
368         }
369         p++;
370         p = xdr_decode_hyper(p, &res->count);
371         res->verifier.committed = be32_to_cpup(p);
372         return decode_verifier(xdr, &res->verifier.verifier);
373
374 out_overflow:
375         print_overflow_msg(__func__, xdr);
376         return -EIO;
377 }
378
379 static int decode_copy_requirements(struct xdr_stream *xdr,
380                                     struct nfs42_copy_res *res) {
381         __be32 *p;
382
383         p = xdr_inline_decode(xdr, 4 + 4);
384         if (unlikely(!p))
385                 goto out_overflow;
386
387         res->consecutive = be32_to_cpup(p++);
388         res->synchronous = be32_to_cpup(p++);
389         return 0;
390 out_overflow:
391         print_overflow_msg(__func__, xdr);
392         return -EIO;
393 }
394
395 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
396 {
397         int status;
398
399         status = decode_op_hdr(xdr, OP_COPY);
400         if (status == NFS4ERR_OFFLOAD_NO_REQS) {
401                 status = decode_copy_requirements(xdr, res);
402                 if (status)
403                         return status;
404                 return NFS4ERR_OFFLOAD_NO_REQS;
405         } else if (status)
406                 return status;
407
408         status = decode_write_response(xdr, &res->write_res);
409         if (status)
410                 return status;
411
412         return decode_copy_requirements(xdr, res);
413 }
414
415 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
416 {
417         return decode_op_hdr(xdr, OP_DEALLOCATE);
418 }
419
420 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
421 {
422         int status;
423         __be32 *p;
424
425         status = decode_op_hdr(xdr, OP_SEEK);
426         if (status)
427                 return status;
428
429         p = xdr_inline_decode(xdr, 4 + 8);
430         if (unlikely(!p))
431                 goto out_overflow;
432
433         res->sr_eof = be32_to_cpup(p++);
434         p = xdr_decode_hyper(p, &res->sr_offset);
435         return 0;
436
437 out_overflow:
438         print_overflow_msg(__func__, xdr);
439         return -EIO;
440 }
441
442 static int decode_layoutstats(struct xdr_stream *xdr)
443 {
444         return decode_op_hdr(xdr, OP_LAYOUTSTATS);
445 }
446
447 static int decode_clone(struct xdr_stream *xdr)
448 {
449         return decode_op_hdr(xdr, OP_CLONE);
450 }
451
452 /*
453  * Decode ALLOCATE request
454  */
455 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
456                                  struct xdr_stream *xdr,
457                                  void *data)
458 {
459         struct nfs42_falloc_res *res = data;
460         struct compound_hdr hdr;
461         int status;
462
463         status = decode_compound_hdr(xdr, &hdr);
464         if (status)
465                 goto out;
466         status = decode_sequence(xdr, &res->seq_res, rqstp);
467         if (status)
468                 goto out;
469         status = decode_putfh(xdr);
470         if (status)
471                 goto out;
472         status = decode_allocate(xdr, res);
473         if (status)
474                 goto out;
475         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
476 out:
477         return status;
478 }
479
480 /*
481  * Decode COPY response
482  */
483 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
484                              struct xdr_stream *xdr,
485                              void *data)
486 {
487         struct nfs42_copy_res *res = data;
488         struct compound_hdr hdr;
489         int status;
490
491         status = decode_compound_hdr(xdr, &hdr);
492         if (status)
493                 goto out;
494         status = decode_sequence(xdr, &res->seq_res, rqstp);
495         if (status)
496                 goto out;
497         status = decode_putfh(xdr);
498         if (status)
499                 goto out;
500         status = decode_savefh(xdr);
501         if (status)
502                 goto out;
503         status = decode_putfh(xdr);
504         if (status)
505                 goto out;
506         status = decode_copy(xdr, res);
507         if (status)
508                 goto out;
509         status = decode_commit(xdr, &res->commit_res);
510 out:
511         return status;
512 }
513
514 /*
515  * Decode DEALLOCATE request
516  */
517 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
518                                    struct xdr_stream *xdr,
519                                    void *data)
520 {
521         struct nfs42_falloc_res *res = data;
522         struct compound_hdr hdr;
523         int status;
524
525         status = decode_compound_hdr(xdr, &hdr);
526         if (status)
527                 goto out;
528         status = decode_sequence(xdr, &res->seq_res, rqstp);
529         if (status)
530                 goto out;
531         status = decode_putfh(xdr);
532         if (status)
533                 goto out;
534         status = decode_deallocate(xdr, res);
535         if (status)
536                 goto out;
537         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
538 out:
539         return status;
540 }
541
542 /*
543  * Decode SEEK request
544  */
545 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
546                              struct xdr_stream *xdr,
547                              void *data)
548 {
549         struct nfs42_seek_res *res = data;
550         struct compound_hdr hdr;
551         int status;
552
553         status = decode_compound_hdr(xdr, &hdr);
554         if (status)
555                 goto out;
556         status = decode_sequence(xdr, &res->seq_res, rqstp);
557         if (status)
558                 goto out;
559         status = decode_putfh(xdr);
560         if (status)
561                 goto out;
562         status = decode_seek(xdr, res);
563 out:
564         return status;
565 }
566
567 /*
568  * Decode LAYOUTSTATS request
569  */
570 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
571                                     struct xdr_stream *xdr,
572                                     void *data)
573 {
574         struct nfs42_layoutstat_res *res = data;
575         struct compound_hdr hdr;
576         int status, i;
577
578         status = decode_compound_hdr(xdr, &hdr);
579         if (status)
580                 goto out;
581         status = decode_sequence(xdr, &res->seq_res, rqstp);
582         if (status)
583                 goto out;
584         status = decode_putfh(xdr);
585         if (status)
586                 goto out;
587         WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
588         for (i = 0; i < res->num_dev; i++) {
589                 status = decode_layoutstats(xdr);
590                 if (status)
591                         goto out;
592         }
593 out:
594         res->rpc_status = status;
595         return status;
596 }
597
598 /*
599  * Decode CLONE request
600  */
601 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
602                               struct xdr_stream *xdr,
603                               void *data)
604 {
605         struct nfs42_clone_res *res = data;
606         struct compound_hdr hdr;
607         int status;
608
609         status = decode_compound_hdr(xdr, &hdr);
610         if (status)
611                 goto out;
612         status = decode_sequence(xdr, &res->seq_res, rqstp);
613         if (status)
614                 goto out;
615         status = decode_putfh(xdr);
616         if (status)
617                 goto out;
618         status = decode_savefh(xdr);
619         if (status)
620                 goto out;
621         status = decode_putfh(xdr);
622         if (status)
623                 goto out;
624         status = decode_clone(xdr);
625         if (status)
626                 goto out;
627         status = decode_getfattr(xdr, res->dst_fattr, res->server);
628
629 out:
630         res->rpc_status = status;
631         return status;
632 }
633
634 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */