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