Merge tag 'mac80211-for-davem-2016-06-09' of git://git.kernel.org/pub/scm/linux/kerne...
[cascardo/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 */