Merge tag 'erofs-for-5.5-rc2-fixes' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-microblaze.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                                          1 + /* One cnr_source_server */\
26                                          1 + /* nl4_type */ \
27                                          1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
28 #define decode_copy_maxsz               (op_decode_hdr_maxsz + \
29                                          NFS42_WRITE_RES_SIZE + \
30                                          1 /* cr_consecutive */ + \
31                                          1 /* cr_synchronous */)
32 #define encode_offload_cancel_maxsz     (op_encode_hdr_maxsz + \
33                                          XDR_QUADLEN(NFS4_STATEID_SIZE))
34 #define decode_offload_cancel_maxsz     (op_decode_hdr_maxsz)
35 #define encode_copy_notify_maxsz        (op_encode_hdr_maxsz + \
36                                          XDR_QUADLEN(NFS4_STATEID_SIZE) + \
37                                          1 + /* nl4_type */ \
38                                          1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
39 #define decode_copy_notify_maxsz        (op_decode_hdr_maxsz + \
40                                          3 + /* cnr_lease_time */\
41                                          XDR_QUADLEN(NFS4_STATEID_SIZE) + \
42                                          1 + /* Support 1 cnr_source_server */\
43                                          1 + /* nl4_type */ \
44                                          1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
45 #define encode_deallocate_maxsz         (op_encode_hdr_maxsz + \
46                                          encode_fallocate_maxsz)
47 #define decode_deallocate_maxsz         (op_decode_hdr_maxsz)
48 #define encode_seek_maxsz               (op_encode_hdr_maxsz + \
49                                          encode_stateid_maxsz + \
50                                          2 /* offset */ + \
51                                          1 /* whence */)
52 #define decode_seek_maxsz               (op_decode_hdr_maxsz + \
53                                          1 /* eof */ + \
54                                          1 /* whence */ + \
55                                          2 /* offset */ + \
56                                          2 /* length */)
57 #define encode_io_info_maxsz            4
58 #define encode_layoutstats_maxsz        (op_decode_hdr_maxsz + \
59                                         2 /* offset */ + \
60                                         2 /* length */ + \
61                                         encode_stateid_maxsz + \
62                                         encode_io_info_maxsz + \
63                                         encode_io_info_maxsz + \
64                                         1 /* opaque devaddr4 length */ + \
65                                         XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
66 #define decode_layoutstats_maxsz        (op_decode_hdr_maxsz)
67 #define encode_device_error_maxsz       (XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
68                                         1 /* status */ + 1 /* opnum */)
69 #define encode_layouterror_maxsz        (op_decode_hdr_maxsz + \
70                                         2 /* offset */ + \
71                                         2 /* length */ + \
72                                         encode_stateid_maxsz + \
73                                         1 /* Array size */ + \
74                                         encode_device_error_maxsz)
75 #define decode_layouterror_maxsz        (op_decode_hdr_maxsz)
76 #define encode_clone_maxsz              (encode_stateid_maxsz + \
77                                         encode_stateid_maxsz + \
78                                         2 /* src offset */ + \
79                                         2 /* dst offset */ + \
80                                         2 /* count */)
81 #define decode_clone_maxsz              (op_decode_hdr_maxsz)
82
83 #define NFS4_enc_allocate_sz            (compound_encode_hdr_maxsz + \
84                                          encode_sequence_maxsz + \
85                                          encode_putfh_maxsz + \
86                                          encode_allocate_maxsz + \
87                                          encode_getattr_maxsz)
88 #define NFS4_dec_allocate_sz            (compound_decode_hdr_maxsz + \
89                                          decode_sequence_maxsz + \
90                                          decode_putfh_maxsz + \
91                                          decode_allocate_maxsz + \
92                                          decode_getattr_maxsz)
93 #define NFS4_enc_copy_sz                (compound_encode_hdr_maxsz + \
94                                          encode_sequence_maxsz + \
95                                          encode_putfh_maxsz + \
96                                          encode_savefh_maxsz + \
97                                          encode_putfh_maxsz + \
98                                          encode_copy_maxsz + \
99                                          encode_commit_maxsz)
100 #define NFS4_dec_copy_sz                (compound_decode_hdr_maxsz + \
101                                          decode_sequence_maxsz + \
102                                          decode_putfh_maxsz + \
103                                          decode_savefh_maxsz + \
104                                          decode_putfh_maxsz + \
105                                          decode_copy_maxsz + \
106                                          decode_commit_maxsz)
107 #define NFS4_enc_offload_cancel_sz      (compound_encode_hdr_maxsz + \
108                                          encode_sequence_maxsz + \
109                                          encode_putfh_maxsz + \
110                                          encode_offload_cancel_maxsz)
111 #define NFS4_dec_offload_cancel_sz      (compound_decode_hdr_maxsz + \
112                                          decode_sequence_maxsz + \
113                                          decode_putfh_maxsz + \
114                                          decode_offload_cancel_maxsz)
115 #define NFS4_enc_copy_notify_sz         (compound_encode_hdr_maxsz + \
116                                          encode_putfh_maxsz + \
117                                          encode_copy_notify_maxsz)
118 #define NFS4_dec_copy_notify_sz         (compound_decode_hdr_maxsz + \
119                                          decode_putfh_maxsz + \
120                                          decode_copy_notify_maxsz)
121 #define NFS4_enc_deallocate_sz          (compound_encode_hdr_maxsz + \
122                                          encode_sequence_maxsz + \
123                                          encode_putfh_maxsz + \
124                                          encode_deallocate_maxsz + \
125                                          encode_getattr_maxsz)
126 #define NFS4_dec_deallocate_sz          (compound_decode_hdr_maxsz + \
127                                          decode_sequence_maxsz + \
128                                          decode_putfh_maxsz + \
129                                          decode_deallocate_maxsz + \
130                                          decode_getattr_maxsz)
131 #define NFS4_enc_seek_sz                (compound_encode_hdr_maxsz + \
132                                          encode_sequence_maxsz + \
133                                          encode_putfh_maxsz + \
134                                          encode_seek_maxsz)
135 #define NFS4_dec_seek_sz                (compound_decode_hdr_maxsz + \
136                                          decode_sequence_maxsz + \
137                                          decode_putfh_maxsz + \
138                                          decode_seek_maxsz)
139 #define NFS4_enc_layoutstats_sz         (compound_encode_hdr_maxsz + \
140                                          encode_sequence_maxsz + \
141                                          encode_putfh_maxsz + \
142                                          PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
143 #define NFS4_dec_layoutstats_sz         (compound_decode_hdr_maxsz + \
144                                          decode_sequence_maxsz + \
145                                          decode_putfh_maxsz + \
146                                          PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
147 #define NFS4_enc_layouterror_sz         (compound_encode_hdr_maxsz + \
148                                          encode_sequence_maxsz + \
149                                          encode_putfh_maxsz + \
150                                          NFS42_LAYOUTERROR_MAX * \
151                                          encode_layouterror_maxsz)
152 #define NFS4_dec_layouterror_sz         (compound_decode_hdr_maxsz + \
153                                          decode_sequence_maxsz + \
154                                          decode_putfh_maxsz + \
155                                          NFS42_LAYOUTERROR_MAX * \
156                                          decode_layouterror_maxsz)
157 #define NFS4_enc_clone_sz               (compound_encode_hdr_maxsz + \
158                                          encode_sequence_maxsz + \
159                                          encode_putfh_maxsz + \
160                                          encode_savefh_maxsz + \
161                                          encode_putfh_maxsz + \
162                                          encode_clone_maxsz + \
163                                          encode_getattr_maxsz)
164 #define NFS4_dec_clone_sz               (compound_decode_hdr_maxsz + \
165                                          decode_sequence_maxsz + \
166                                          decode_putfh_maxsz + \
167                                          decode_savefh_maxsz + \
168                                          decode_putfh_maxsz + \
169                                          decode_clone_maxsz + \
170                                          decode_getattr_maxsz)
171
172 static void encode_fallocate(struct xdr_stream *xdr,
173                              const struct nfs42_falloc_args *args)
174 {
175         encode_nfs4_stateid(xdr, &args->falloc_stateid);
176         encode_uint64(xdr, args->falloc_offset);
177         encode_uint64(xdr, args->falloc_length);
178 }
179
180 static void encode_allocate(struct xdr_stream *xdr,
181                             const struct nfs42_falloc_args *args,
182                             struct compound_hdr *hdr)
183 {
184         encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
185         encode_fallocate(xdr, args);
186 }
187
188 static void encode_nl4_server(struct xdr_stream *xdr,
189                               const struct nl4_server *ns)
190 {
191         encode_uint32(xdr, ns->nl4_type);
192         switch (ns->nl4_type) {
193         case NL4_NAME:
194         case NL4_URL:
195                 encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
196                 break;
197         case NL4_NETADDR:
198                 encode_string(xdr, ns->u.nl4_addr.netid_len,
199                               ns->u.nl4_addr.netid);
200                 encode_string(xdr, ns->u.nl4_addr.addr_len,
201                               ns->u.nl4_addr.addr);
202                 break;
203         default:
204                 WARN_ON_ONCE(1);
205         }
206 }
207
208 static void encode_copy(struct xdr_stream *xdr,
209                         const struct nfs42_copy_args *args,
210                         struct compound_hdr *hdr)
211 {
212         encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
213         encode_nfs4_stateid(xdr, &args->src_stateid);
214         encode_nfs4_stateid(xdr, &args->dst_stateid);
215
216         encode_uint64(xdr, args->src_pos);
217         encode_uint64(xdr, args->dst_pos);
218         encode_uint64(xdr, args->count);
219
220         encode_uint32(xdr, 1); /* consecutive = true */
221         encode_uint32(xdr, args->sync);
222         if (args->cp_src == NULL) { /* intra-ssc */
223                 encode_uint32(xdr, 0); /* no src server list */
224                 return;
225         }
226         encode_uint32(xdr, 1); /* supporting 1 server */
227         encode_nl4_server(xdr, args->cp_src);
228 }
229
230 static void encode_offload_cancel(struct xdr_stream *xdr,
231                                   const struct nfs42_offload_status_args *args,
232                                   struct compound_hdr *hdr)
233 {
234         encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
235         encode_nfs4_stateid(xdr, &args->osa_stateid);
236 }
237
238 static void encode_copy_notify(struct xdr_stream *xdr,
239                                const struct nfs42_copy_notify_args *args,
240                                struct compound_hdr *hdr)
241 {
242         encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
243         encode_nfs4_stateid(xdr, &args->cna_src_stateid);
244         encode_nl4_server(xdr, &args->cna_dst);
245 }
246
247 static void encode_deallocate(struct xdr_stream *xdr,
248                               const struct nfs42_falloc_args *args,
249                               struct compound_hdr *hdr)
250 {
251         encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
252         encode_fallocate(xdr, args);
253 }
254
255 static void encode_seek(struct xdr_stream *xdr,
256                         const struct nfs42_seek_args *args,
257                         struct compound_hdr *hdr)
258 {
259         encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
260         encode_nfs4_stateid(xdr, &args->sa_stateid);
261         encode_uint64(xdr, args->sa_offset);
262         encode_uint32(xdr, args->sa_what);
263 }
264
265 static void encode_layoutstats(struct xdr_stream *xdr,
266                                const struct nfs42_layoutstat_args *args,
267                                struct nfs42_layoutstat_devinfo *devinfo,
268                                struct compound_hdr *hdr)
269 {
270         __be32 *p;
271
272         encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
273         p = reserve_space(xdr, 8 + 8);
274         p = xdr_encode_hyper(p, devinfo->offset);
275         p = xdr_encode_hyper(p, devinfo->length);
276         encode_nfs4_stateid(xdr, &args->stateid);
277         p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
278         p = xdr_encode_hyper(p, devinfo->read_count);
279         p = xdr_encode_hyper(p, devinfo->read_bytes);
280         p = xdr_encode_hyper(p, devinfo->write_count);
281         p = xdr_encode_hyper(p, devinfo->write_bytes);
282         p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
283                         NFS4_DEVICEID4_SIZE);
284         /* Encode layoutupdate4 */
285         *p++ = cpu_to_be32(devinfo->layout_type);
286         if (devinfo->ld_private.ops)
287                 devinfo->ld_private.ops->encode(xdr, args,
288                                 &devinfo->ld_private);
289         else
290                 encode_uint32(xdr, 0);
291 }
292
293 static void encode_clone(struct xdr_stream *xdr,
294                          const struct nfs42_clone_args *args,
295                          struct compound_hdr *hdr)
296 {
297         __be32 *p;
298
299         encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
300         encode_nfs4_stateid(xdr, &args->src_stateid);
301         encode_nfs4_stateid(xdr, &args->dst_stateid);
302         p = reserve_space(xdr, 3*8);
303         p = xdr_encode_hyper(p, args->src_offset);
304         p = xdr_encode_hyper(p, args->dst_offset);
305         xdr_encode_hyper(p, args->count);
306 }
307
308 static void encode_device_error(struct xdr_stream *xdr,
309                                 const struct nfs42_device_error *error)
310 {
311         __be32 *p;
312
313         p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
314         p = xdr_encode_opaque_fixed(p, error->dev_id.data,
315                         NFS4_DEVICEID4_SIZE);
316         *p++ = cpu_to_be32(error->status);
317         *p = cpu_to_be32(error->opnum);
318 }
319
320 static void encode_layouterror(struct xdr_stream *xdr,
321                                const struct nfs42_layout_error *args,
322                                struct compound_hdr *hdr)
323 {
324         __be32 *p;
325
326         encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
327         p = reserve_space(xdr, 8 + 8);
328         p = xdr_encode_hyper(p, args->offset);
329         p = xdr_encode_hyper(p, args->length);
330         encode_nfs4_stateid(xdr, &args->stateid);
331         p = reserve_space(xdr, 4);
332         *p = cpu_to_be32(1);
333         encode_device_error(xdr, &args->errors[0]);
334 }
335
336 /*
337  * Encode ALLOCATE request
338  */
339 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
340                                   struct xdr_stream *xdr,
341                                   const void *data)
342 {
343         const struct nfs42_falloc_args *args = data;
344         struct compound_hdr hdr = {
345                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
346         };
347
348         encode_compound_hdr(xdr, req, &hdr);
349         encode_sequence(xdr, &args->seq_args, &hdr);
350         encode_putfh(xdr, args->falloc_fh, &hdr);
351         encode_allocate(xdr, args, &hdr);
352         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
353         encode_nops(&hdr);
354 }
355
356 static void encode_copy_commit(struct xdr_stream *xdr,
357                           const struct nfs42_copy_args *args,
358                           struct compound_hdr *hdr)
359 {
360         __be32 *p;
361
362         encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
363         p = reserve_space(xdr, 12);
364         p = xdr_encode_hyper(p, args->dst_pos);
365         *p = cpu_to_be32(args->count);
366 }
367
368 /*
369  * Encode COPY request
370  */
371 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
372                               struct xdr_stream *xdr,
373                               const void *data)
374 {
375         const struct nfs42_copy_args *args = data;
376         struct compound_hdr hdr = {
377                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
378         };
379
380         encode_compound_hdr(xdr, req, &hdr);
381         encode_sequence(xdr, &args->seq_args, &hdr);
382         encode_putfh(xdr, args->src_fh, &hdr);
383         encode_savefh(xdr, &hdr);
384         encode_putfh(xdr, args->dst_fh, &hdr);
385         encode_copy(xdr, args, &hdr);
386         if (args->sync)
387                 encode_copy_commit(xdr, args, &hdr);
388         encode_nops(&hdr);
389 }
390
391 /*
392  * Encode OFFLOAD_CANEL request
393  */
394 static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
395                                         struct xdr_stream *xdr,
396                                         const void *data)
397 {
398         const struct nfs42_offload_status_args *args = data;
399         struct compound_hdr hdr = {
400                 .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
401         };
402
403         encode_compound_hdr(xdr, req, &hdr);
404         encode_sequence(xdr, &args->osa_seq_args, &hdr);
405         encode_putfh(xdr, args->osa_src_fh, &hdr);
406         encode_offload_cancel(xdr, args, &hdr);
407         encode_nops(&hdr);
408 }
409
410 /*
411  * Encode COPY_NOTIFY request
412  */
413 static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
414                                      struct xdr_stream *xdr,
415                                      const void *data)
416 {
417         const struct nfs42_copy_notify_args *args = data;
418         struct compound_hdr hdr = {
419                 .minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
420         };
421
422         encode_compound_hdr(xdr, req, &hdr);
423         encode_sequence(xdr, &args->cna_seq_args, &hdr);
424         encode_putfh(xdr, args->cna_src_fh, &hdr);
425         encode_copy_notify(xdr, args, &hdr);
426         encode_nops(&hdr);
427 }
428
429 /*
430  * Encode DEALLOCATE request
431  */
432 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
433                                     struct xdr_stream *xdr,
434                                     const void *data)
435 {
436         const struct nfs42_falloc_args *args = data;
437         struct compound_hdr hdr = {
438                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
439         };
440
441         encode_compound_hdr(xdr, req, &hdr);
442         encode_sequence(xdr, &args->seq_args, &hdr);
443         encode_putfh(xdr, args->falloc_fh, &hdr);
444         encode_deallocate(xdr, args, &hdr);
445         encode_getfattr(xdr, args->falloc_bitmask, &hdr);
446         encode_nops(&hdr);
447 }
448
449 /*
450  * Encode SEEK request
451  */
452 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
453                               struct xdr_stream *xdr,
454                               const void *data)
455 {
456         const struct nfs42_seek_args *args = data;
457         struct compound_hdr hdr = {
458                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
459         };
460
461         encode_compound_hdr(xdr, req, &hdr);
462         encode_sequence(xdr, &args->seq_args, &hdr);
463         encode_putfh(xdr, args->sa_fh, &hdr);
464         encode_seek(xdr, args, &hdr);
465         encode_nops(&hdr);
466 }
467
468 /*
469  * Encode LAYOUTSTATS request
470  */
471 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
472                                      struct xdr_stream *xdr,
473                                      const void *data)
474 {
475         const struct nfs42_layoutstat_args *args = data;
476         int i;
477
478         struct compound_hdr hdr = {
479                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
480         };
481
482         encode_compound_hdr(xdr, req, &hdr);
483         encode_sequence(xdr, &args->seq_args, &hdr);
484         encode_putfh(xdr, args->fh, &hdr);
485         WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
486         for (i = 0; i < args->num_dev; i++)
487                 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
488         encode_nops(&hdr);
489 }
490
491 /*
492  * Encode CLONE request
493  */
494 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
495                                struct xdr_stream *xdr,
496                                const void *data)
497 {
498         const struct nfs42_clone_args *args = data;
499         struct compound_hdr hdr = {
500                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
501         };
502
503         encode_compound_hdr(xdr, req, &hdr);
504         encode_sequence(xdr, &args->seq_args, &hdr);
505         encode_putfh(xdr, args->src_fh, &hdr);
506         encode_savefh(xdr, &hdr);
507         encode_putfh(xdr, args->dst_fh, &hdr);
508         encode_clone(xdr, args, &hdr);
509         encode_getfattr(xdr, args->dst_bitmask, &hdr);
510         encode_nops(&hdr);
511 }
512
513 /*
514  * Encode LAYOUTERROR request
515  */
516 static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
517                                      struct xdr_stream *xdr,
518                                      const void *data)
519 {
520         const struct nfs42_layouterror_args *args = data;
521         struct compound_hdr hdr = {
522                 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
523         };
524         int i;
525
526         encode_compound_hdr(xdr, req, &hdr);
527         encode_sequence(xdr, &args->seq_args, &hdr);
528         encode_putfh(xdr, NFS_FH(args->inode), &hdr);
529         for (i = 0; i < args->num_errors; i++)
530                 encode_layouterror(xdr, &args->errors[i], &hdr);
531         encode_nops(&hdr);
532 }
533
534 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
535 {
536         return decode_op_hdr(xdr, OP_ALLOCATE);
537 }
538
539 static int decode_write_response(struct xdr_stream *xdr,
540                                  struct nfs42_write_res *res)
541 {
542         __be32 *p;
543         int status, count;
544
545         p = xdr_inline_decode(xdr, 4);
546         if (unlikely(!p))
547                 return -EIO;
548         count = be32_to_cpup(p);
549         if (count > 1)
550                 return -EREMOTEIO;
551         else if (count == 1) {
552                 status = decode_opaque_fixed(xdr, &res->stateid,
553                                 NFS4_STATEID_SIZE);
554                 if (unlikely(status))
555                         return -EIO;
556         }
557         p = xdr_inline_decode(xdr, 8 + 4);
558         if (unlikely(!p))
559                 return -EIO;
560         p = xdr_decode_hyper(p, &res->count);
561         res->verifier.committed = be32_to_cpup(p);
562         return decode_verifier(xdr, &res->verifier.verifier);
563 }
564
565 static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
566 {
567         struct nfs42_netaddr *naddr;
568         uint32_t dummy;
569         char *dummy_str;
570         __be32 *p;
571         int status;
572
573         /* nl_type */
574         p = xdr_inline_decode(xdr, 4);
575         if (unlikely(!p))
576                 return -EIO;
577         ns->nl4_type = be32_to_cpup(p);
578         switch (ns->nl4_type) {
579         case NL4_NAME:
580         case NL4_URL:
581                 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
582                 if (unlikely(status))
583                         return status;
584                 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
585                         return -EIO;
586                 memcpy(&ns->u.nl4_str, dummy_str, dummy);
587                 ns->u.nl4_str_sz = dummy;
588                 break;
589         case NL4_NETADDR:
590                 naddr = &ns->u.nl4_addr;
591
592                 /* netid string */
593                 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
594                 if (unlikely(status))
595                         return status;
596                 if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
597                         return -EIO;
598                 naddr->netid_len = dummy;
599                 memcpy(naddr->netid, dummy_str, naddr->netid_len);
600
601                 /* uaddr string */
602                 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
603                 if (unlikely(status))
604                         return status;
605                 if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
606                         return -EIO;
607                 naddr->addr_len = dummy;
608                 memcpy(naddr->addr, dummy_str, naddr->addr_len);
609                 break;
610         default:
611                 WARN_ON_ONCE(1);
612                 return -EIO;
613         }
614         return 0;
615 }
616
617 static int decode_copy_requirements(struct xdr_stream *xdr,
618                                     struct nfs42_copy_res *res) {
619         __be32 *p;
620
621         p = xdr_inline_decode(xdr, 4 + 4);
622         if (unlikely(!p))
623                 return -EIO;
624
625         res->consecutive = be32_to_cpup(p++);
626         res->synchronous = be32_to_cpup(p++);
627         return 0;
628 }
629
630 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
631 {
632         int status;
633
634         status = decode_op_hdr(xdr, OP_COPY);
635         if (status == NFS4ERR_OFFLOAD_NO_REQS) {
636                 status = decode_copy_requirements(xdr, res);
637                 if (status)
638                         return status;
639                 return NFS4ERR_OFFLOAD_NO_REQS;
640         } else if (status)
641                 return status;
642
643         status = decode_write_response(xdr, &res->write_res);
644         if (status)
645                 return status;
646
647         return decode_copy_requirements(xdr, res);
648 }
649
650 static int decode_offload_cancel(struct xdr_stream *xdr,
651                                  struct nfs42_offload_status_res *res)
652 {
653         return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
654 }
655
656 static int decode_copy_notify(struct xdr_stream *xdr,
657                               struct nfs42_copy_notify_res *res)
658 {
659         __be32 *p;
660         int status, count;
661
662         status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
663         if (status)
664                 return status;
665         /* cnr_lease_time */
666         p = xdr_inline_decode(xdr, 12);
667         if (unlikely(!p))
668                 return -EIO;
669         p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
670         res->cnr_lease_time.nseconds = be32_to_cpup(p);
671
672         status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
673         if (unlikely(status))
674                 return -EIO;
675
676         /* number of source addresses */
677         p = xdr_inline_decode(xdr, 4);
678         if (unlikely(!p))
679                 return -EIO;
680
681         count = be32_to_cpup(p);
682         if (count > 1)
683                 pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
684                          __func__, count);
685
686         status = decode_nl4_server(xdr, &res->cnr_src);
687         if (unlikely(status))
688                 return -EIO;
689         return 0;
690 }
691
692 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
693 {
694         return decode_op_hdr(xdr, OP_DEALLOCATE);
695 }
696
697 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
698 {
699         int status;
700         __be32 *p;
701
702         status = decode_op_hdr(xdr, OP_SEEK);
703         if (status)
704                 return status;
705
706         p = xdr_inline_decode(xdr, 4 + 8);
707         if (unlikely(!p))
708                 return -EIO;
709
710         res->sr_eof = be32_to_cpup(p++);
711         p = xdr_decode_hyper(p, &res->sr_offset);
712         return 0;
713 }
714
715 static int decode_layoutstats(struct xdr_stream *xdr)
716 {
717         return decode_op_hdr(xdr, OP_LAYOUTSTATS);
718 }
719
720 static int decode_clone(struct xdr_stream *xdr)
721 {
722         return decode_op_hdr(xdr, OP_CLONE);
723 }
724
725 static int decode_layouterror(struct xdr_stream *xdr)
726 {
727         return decode_op_hdr(xdr, OP_LAYOUTERROR);
728 }
729
730 /*
731  * Decode ALLOCATE request
732  */
733 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
734                                  struct xdr_stream *xdr,
735                                  void *data)
736 {
737         struct nfs42_falloc_res *res = data;
738         struct compound_hdr hdr;
739         int status;
740
741         status = decode_compound_hdr(xdr, &hdr);
742         if (status)
743                 goto out;
744         status = decode_sequence(xdr, &res->seq_res, rqstp);
745         if (status)
746                 goto out;
747         status = decode_putfh(xdr);
748         if (status)
749                 goto out;
750         status = decode_allocate(xdr, res);
751         if (status)
752                 goto out;
753         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
754 out:
755         return status;
756 }
757
758 /*
759  * Decode COPY response
760  */
761 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
762                              struct xdr_stream *xdr,
763                              void *data)
764 {
765         struct nfs42_copy_res *res = data;
766         struct compound_hdr hdr;
767         int status;
768
769         status = decode_compound_hdr(xdr, &hdr);
770         if (status)
771                 goto out;
772         status = decode_sequence(xdr, &res->seq_res, rqstp);
773         if (status)
774                 goto out;
775         status = decode_putfh(xdr);
776         if (status)
777                 goto out;
778         status = decode_savefh(xdr);
779         if (status)
780                 goto out;
781         status = decode_putfh(xdr);
782         if (status)
783                 goto out;
784         status = decode_copy(xdr, res);
785         if (status)
786                 goto out;
787         if (res->commit_res.verf)
788                 status = decode_commit(xdr, &res->commit_res);
789 out:
790         return status;
791 }
792
793 /*
794  * Decode OFFLOAD_CANCEL response
795  */
796 static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
797                                        struct xdr_stream *xdr,
798                                        void *data)
799 {
800         struct nfs42_offload_status_res *res = data;
801         struct compound_hdr hdr;
802         int status;
803
804         status = decode_compound_hdr(xdr, &hdr);
805         if (status)
806                 goto out;
807         status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
808         if (status)
809                 goto out;
810         status = decode_putfh(xdr);
811         if (status)
812                 goto out;
813         status = decode_offload_cancel(xdr, res);
814
815 out:
816         return status;
817 }
818
819 /*
820  * Decode COPY_NOTIFY response
821  */
822 static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
823                                     struct xdr_stream *xdr,
824                                     void *data)
825 {
826         struct nfs42_copy_notify_res *res = data;
827         struct compound_hdr hdr;
828         int status;
829
830         status = decode_compound_hdr(xdr, &hdr);
831         if (status)
832                 goto out;
833         status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
834         if (status)
835                 goto out;
836         status = decode_putfh(xdr);
837         if (status)
838                 goto out;
839         status = decode_copy_notify(xdr, res);
840
841 out:
842         return status;
843 }
844
845 /*
846  * Decode DEALLOCATE request
847  */
848 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
849                                    struct xdr_stream *xdr,
850                                    void *data)
851 {
852         struct nfs42_falloc_res *res = data;
853         struct compound_hdr hdr;
854         int status;
855
856         status = decode_compound_hdr(xdr, &hdr);
857         if (status)
858                 goto out;
859         status = decode_sequence(xdr, &res->seq_res, rqstp);
860         if (status)
861                 goto out;
862         status = decode_putfh(xdr);
863         if (status)
864                 goto out;
865         status = decode_deallocate(xdr, res);
866         if (status)
867                 goto out;
868         decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
869 out:
870         return status;
871 }
872
873 /*
874  * Decode SEEK request
875  */
876 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
877                              struct xdr_stream *xdr,
878                              void *data)
879 {
880         struct nfs42_seek_res *res = data;
881         struct compound_hdr hdr;
882         int status;
883
884         status = decode_compound_hdr(xdr, &hdr);
885         if (status)
886                 goto out;
887         status = decode_sequence(xdr, &res->seq_res, rqstp);
888         if (status)
889                 goto out;
890         status = decode_putfh(xdr);
891         if (status)
892                 goto out;
893         status = decode_seek(xdr, res);
894 out:
895         return status;
896 }
897
898 /*
899  * Decode LAYOUTSTATS request
900  */
901 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
902                                     struct xdr_stream *xdr,
903                                     void *data)
904 {
905         struct nfs42_layoutstat_res *res = data;
906         struct compound_hdr hdr;
907         int status, i;
908
909         status = decode_compound_hdr(xdr, &hdr);
910         if (status)
911                 goto out;
912         status = decode_sequence(xdr, &res->seq_res, rqstp);
913         if (status)
914                 goto out;
915         status = decode_putfh(xdr);
916         if (status)
917                 goto out;
918         WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
919         for (i = 0; i < res->num_dev; i++) {
920                 status = decode_layoutstats(xdr);
921                 if (status)
922                         goto out;
923         }
924 out:
925         res->rpc_status = status;
926         return status;
927 }
928
929 /*
930  * Decode CLONE request
931  */
932 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
933                               struct xdr_stream *xdr,
934                               void *data)
935 {
936         struct nfs42_clone_res *res = data;
937         struct compound_hdr hdr;
938         int status;
939
940         status = decode_compound_hdr(xdr, &hdr);
941         if (status)
942                 goto out;
943         status = decode_sequence(xdr, &res->seq_res, rqstp);
944         if (status)
945                 goto out;
946         status = decode_putfh(xdr);
947         if (status)
948                 goto out;
949         status = decode_savefh(xdr);
950         if (status)
951                 goto out;
952         status = decode_putfh(xdr);
953         if (status)
954                 goto out;
955         status = decode_clone(xdr);
956         if (status)
957                 goto out;
958         status = decode_getfattr(xdr, res->dst_fattr, res->server);
959
960 out:
961         res->rpc_status = status;
962         return status;
963 }
964
965 /*
966  * Decode LAYOUTERROR request
967  */
968 static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
969                                     struct xdr_stream *xdr,
970                                     void *data)
971 {
972         struct nfs42_layouterror_res *res = data;
973         struct compound_hdr hdr;
974         int status, i;
975
976         status = decode_compound_hdr(xdr, &hdr);
977         if (status)
978                 goto out;
979         status = decode_sequence(xdr, &res->seq_res, rqstp);
980         if (status)
981                 goto out;
982         status = decode_putfh(xdr);
983
984         for (i = 0; i < res->num_errors && status == 0; i++)
985                 status = decode_layouterror(xdr);
986 out:
987         res->rpc_status = status;
988         return status;
989 }
990
991 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */