xref: /linux/fs/nfs/nfs42xdr.c (revision 9a6b55ac)
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 */
992