]> git.karo-electronics.de Git - karo-tx-linux.git/blob - fs/nfs/nfs42xdr.c
NFS append COMMIT after synchronous COPY
[karo-tx-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                                          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                              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                             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                         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                               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                         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                                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                          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                                   struct nfs42_falloc_args *args)
214 {
215         struct compound_hdr hdr = {
216                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
217         };
218
219         encode_compound_hdr(xdr, req, &hdr);
220         encode_sequence(xdr, &args->seq_args, &hdr);
221         encode_putfh(xdr, args->falloc_fh, &hdr);
222         encode_allocate(xdr, args, &hdr);
223         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
224         encode_nops(&hdr);
225 }
226
227 static void encode_copy_commit(struct xdr_stream *xdr,
228                           struct nfs42_copy_args *args,
229                           struct compound_hdr *hdr)
230 {
231         __be32 *p;
232
233         encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
234         p = reserve_space(xdr, 12);
235         p = xdr_encode_hyper(p, args->dst_pos);
236         *p = cpu_to_be32(args->count);
237 }
238
239 /*
240  * Encode COPY request
241  */
242 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
243                               struct xdr_stream *xdr,
244                               struct nfs42_copy_args *args)
245 {
246         struct compound_hdr hdr = {
247                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
248         };
249
250         encode_compound_hdr(xdr, req, &hdr);
251         encode_sequence(xdr, &args->seq_args, &hdr);
252         encode_putfh(xdr, args->src_fh, &hdr);
253         encode_savefh(xdr, &hdr);
254         encode_putfh(xdr, args->dst_fh, &hdr);
255         encode_copy(xdr, args, &hdr);
256         encode_copy_commit(xdr, args, &hdr);
257         encode_nops(&hdr);
258 }
259
260 /*
261  * Encode DEALLOCATE request
262  */
263 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
264                                     struct xdr_stream *xdr,
265                                     struct nfs42_falloc_args *args)
266 {
267         struct compound_hdr hdr = {
268                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
269         };
270
271         encode_compound_hdr(xdr, req, &hdr);
272         encode_sequence(xdr, &args->seq_args, &hdr);
273         encode_putfh(xdr, args->falloc_fh, &hdr);
274         encode_deallocate(xdr, args, &hdr);
275         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
276         encode_nops(&hdr);
277 }
278
279 /*
280  * Encode SEEK request
281  */
282 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
283                               struct xdr_stream *xdr,
284                               struct nfs42_seek_args *args)
285 {
286         struct compound_hdr hdr = {
287                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
288         };
289
290         encode_compound_hdr(xdr, req, &hdr);
291         encode_sequence(xdr, &args->seq_args, &hdr);
292         encode_putfh(xdr, args->sa_fh, &hdr);
293         encode_seek(xdr, args, &hdr);
294         encode_nops(&hdr);
295 }
296
297 /*
298  * Encode LAYOUTSTATS request
299  */
300 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
301                                      struct xdr_stream *xdr,
302                                      struct nfs42_layoutstat_args *args)
303 {
304         int i;
305
306         struct compound_hdr hdr = {
307                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
308         };
309
310         encode_compound_hdr(xdr, req, &hdr);
311         encode_sequence(xdr, &args->seq_args, &hdr);
312         encode_putfh(xdr, args->fh, &hdr);
313         WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
314         for (i = 0; i < args->num_dev; i++)
315                 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
316         encode_nops(&hdr);
317 }
318
319 /*
320  * Encode CLONE request
321  */
322 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
323                                struct xdr_stream *xdr,
324                                struct nfs42_clone_args *args)
325 {
326         struct compound_hdr hdr = {
327                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
328         };
329
330         encode_compound_hdr(xdr, req, &hdr);
331         encode_sequence(xdr, &args->seq_args, &hdr);
332         encode_putfh(xdr, args->src_fh, &hdr);
333         encode_savefh(xdr, &hdr);
334         encode_putfh(xdr, args->dst_fh, &hdr);
335         encode_clone(xdr, args, &hdr);
336         encode_getfattr(xdr, args->dst_bitmask, &hdr);
337         encode_nops(&hdr);
338 }
339
340 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
341 {
342         return decode_op_hdr(xdr, OP_ALLOCATE);
343 }
344
345 static int decode_write_response(struct xdr_stream *xdr,
346                                  struct nfs42_write_res *res)
347 {
348         __be32 *p;
349
350         p = xdr_inline_decode(xdr, 4 + 8 + 4);
351         if (unlikely(!p))
352                 goto out_overflow;
353
354         /*
355          * We never use asynchronous mode, so warn if a server returns
356          * a stateid.
357          */
358         if (unlikely(*p != 0)) {
359                 pr_err_once("%s: server has set unrequested "
360                                 "asynchronous mode\n", __func__);
361                 return -EREMOTEIO;
362         }
363         p++;
364         p = xdr_decode_hyper(p, &res->count);
365         res->verifier.committed = be32_to_cpup(p);
366         return decode_verifier(xdr, &res->verifier.verifier);
367
368 out_overflow:
369         print_overflow_msg(__func__, xdr);
370         return -EIO;
371 }
372
373 static int decode_copy_requirements(struct xdr_stream *xdr,
374                                     struct nfs42_copy_res *res) {
375         __be32 *p;
376
377         p = xdr_inline_decode(xdr, 4 + 4);
378         if (unlikely(!p))
379                 goto out_overflow;
380
381         res->consecutive = be32_to_cpup(p++);
382         res->synchronous = be32_to_cpup(p++);
383         return 0;
384 out_overflow:
385         print_overflow_msg(__func__, xdr);
386         return -EIO;
387 }
388
389 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
390 {
391         int status;
392
393         status = decode_op_hdr(xdr, OP_COPY);
394         if (status == NFS4ERR_OFFLOAD_NO_REQS) {
395                 status = decode_copy_requirements(xdr, res);
396                 if (status)
397                         return status;
398                 return NFS4ERR_OFFLOAD_NO_REQS;
399         } else if (status)
400                 return status;
401
402         status = decode_write_response(xdr, &res->write_res);
403         if (status)
404                 return status;
405
406         return decode_copy_requirements(xdr, res);
407 }
408
409 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
410 {
411         return decode_op_hdr(xdr, OP_DEALLOCATE);
412 }
413
414 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
415 {
416         int status;
417         __be32 *p;
418
419         status = decode_op_hdr(xdr, OP_SEEK);
420         if (status)
421                 return status;
422
423         p = xdr_inline_decode(xdr, 4 + 8);
424         if (unlikely(!p))
425                 goto out_overflow;
426
427         res->sr_eof = be32_to_cpup(p++);
428         p = xdr_decode_hyper(p, &res->sr_offset);
429         return 0;
430
431 out_overflow:
432         print_overflow_msg(__func__, xdr);
433         return -EIO;
434 }
435
436 static int decode_layoutstats(struct xdr_stream *xdr)
437 {
438         return decode_op_hdr(xdr, OP_LAYOUTSTATS);
439 }
440
441 static int decode_clone(struct xdr_stream *xdr)
442 {
443         return decode_op_hdr(xdr, OP_CLONE);
444 }
445
446 /*
447  * Decode ALLOCATE request
448  */
449 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
450                                  struct xdr_stream *xdr,
451                                  struct nfs42_falloc_res *res)
452 {
453         struct compound_hdr hdr;
454         int status;
455
456         status = decode_compound_hdr(xdr, &hdr);
457         if (status)
458                 goto out;
459         status = decode_sequence(xdr, &res->seq_res, rqstp);
460         if (status)
461                 goto out;
462         status = decode_putfh(xdr);
463         if (status)
464                 goto out;
465         status = decode_allocate(xdr, res);
466         if (status)
467                 goto out;
468         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
469 out:
470         return status;
471 }
472
473 /*
474  * Decode COPY response
475  */
476 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
477                              struct xdr_stream *xdr,
478                              struct nfs42_copy_res *res)
479 {
480         struct compound_hdr hdr;
481         int status;
482
483         status = decode_compound_hdr(xdr, &hdr);
484         if (status)
485                 goto out;
486         status = decode_sequence(xdr, &res->seq_res, rqstp);
487         if (status)
488                 goto out;
489         status = decode_putfh(xdr);
490         if (status)
491                 goto out;
492         status = decode_savefh(xdr);
493         if (status)
494                 goto out;
495         status = decode_putfh(xdr);
496         if (status)
497                 goto out;
498         status = decode_copy(xdr, res);
499         if (status)
500                 goto out;
501         status = decode_commit(xdr, &res->commit_res);
502 out:
503         return status;
504 }
505
506 /*
507  * Decode DEALLOCATE request
508  */
509 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
510                                    struct xdr_stream *xdr,
511                                    struct nfs42_falloc_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_deallocate(xdr, res);
526         if (status)
527                 goto out;
528         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
529 out:
530         return status;
531 }
532
533 /*
534  * Decode SEEK request
535  */
536 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
537                              struct xdr_stream *xdr,
538                              struct nfs42_seek_res *res)
539 {
540         struct compound_hdr hdr;
541         int status;
542
543         status = decode_compound_hdr(xdr, &hdr);
544         if (status)
545                 goto out;
546         status = decode_sequence(xdr, &res->seq_res, rqstp);
547         if (status)
548                 goto out;
549         status = decode_putfh(xdr);
550         if (status)
551                 goto out;
552         status = decode_seek(xdr, res);
553 out:
554         return status;
555 }
556
557 /*
558  * Decode LAYOUTSTATS request
559  */
560 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
561                                     struct xdr_stream *xdr,
562                                     struct nfs42_layoutstat_res *res)
563 {
564         struct compound_hdr hdr;
565         int status, i;
566
567         status = decode_compound_hdr(xdr, &hdr);
568         if (status)
569                 goto out;
570         status = decode_sequence(xdr, &res->seq_res, rqstp);
571         if (status)
572                 goto out;
573         status = decode_putfh(xdr);
574         if (status)
575                 goto out;
576         WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
577         for (i = 0; i < res->num_dev; i++) {
578                 status = decode_layoutstats(xdr);
579                 if (status)
580                         goto out;
581         }
582 out:
583         res->rpc_status = status;
584         return status;
585 }
586
587 /*
588  * Decode CLONE request
589  */
590 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
591                               struct xdr_stream *xdr,
592                               struct nfs42_clone_res *res)
593 {
594         struct compound_hdr hdr;
595         int status;
596
597         status = decode_compound_hdr(xdr, &hdr);
598         if (status)
599                 goto out;
600         status = decode_sequence(xdr, &res->seq_res, rqstp);
601         if (status)
602                 goto out;
603         status = decode_putfh(xdr);
604         if (status)
605                 goto out;
606         status = decode_savefh(xdr);
607         if (status)
608                 goto out;
609         status = decode_putfh(xdr);
610         if (status)
611                 goto out;
612         status = decode_clone(xdr);
613         if (status)
614                 goto out;
615         status = decode_getfattr(xdr, res->dst_fattr, res->server);
616
617 out:
618         res->rpc_status = status;
619         return status;
620 }
621
622 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */