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