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