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