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