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