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