xref: /linux/fs/nfs/nfs42xdr.c (revision 48dea9a700c8728cc31a1dd44588b97578de86ee)
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 /* Not limited by NFS itself, limited by the generic xattr code */
173 #define nfs4_xattr_name_maxsz   XDR_QUADLEN(XATTR_NAME_MAX)
174 
175 #define encode_getxattr_maxsz   (op_encode_hdr_maxsz + 1 + \
176 				 nfs4_xattr_name_maxsz)
177 #define decode_getxattr_maxsz   (op_decode_hdr_maxsz + 1 + 1)
178 #define encode_setxattr_maxsz   (op_encode_hdr_maxsz + \
179 				 1 + nfs4_xattr_name_maxsz + 1)
180 #define decode_setxattr_maxsz   (op_decode_hdr_maxsz + decode_change_info_maxsz)
181 #define encode_listxattrs_maxsz  (op_encode_hdr_maxsz + 2 + 1)
182 #define decode_listxattrs_maxsz  (op_decode_hdr_maxsz + 2 + 1 + 1)
183 #define encode_removexattr_maxsz (op_encode_hdr_maxsz + 1 + \
184 				  nfs4_xattr_name_maxsz)
185 #define decode_removexattr_maxsz (op_decode_hdr_maxsz + \
186 				  decode_change_info_maxsz)
187 
188 #define NFS4_enc_getxattr_sz	(compound_encode_hdr_maxsz + \
189 				encode_sequence_maxsz + \
190 				encode_putfh_maxsz + \
191 				encode_getxattr_maxsz)
192 #define NFS4_dec_getxattr_sz	(compound_decode_hdr_maxsz + \
193 				decode_sequence_maxsz + \
194 				decode_putfh_maxsz + \
195 				decode_getxattr_maxsz)
196 #define NFS4_enc_setxattr_sz	(compound_encode_hdr_maxsz + \
197 				encode_sequence_maxsz + \
198 				encode_putfh_maxsz + \
199 				encode_setxattr_maxsz)
200 #define NFS4_dec_setxattr_sz	(compound_decode_hdr_maxsz + \
201 				decode_sequence_maxsz + \
202 				decode_putfh_maxsz + \
203 				decode_setxattr_maxsz)
204 #define NFS4_enc_listxattrs_sz	(compound_encode_hdr_maxsz + \
205 				encode_sequence_maxsz + \
206 				encode_putfh_maxsz + \
207 				encode_listxattrs_maxsz)
208 #define NFS4_dec_listxattrs_sz	(compound_decode_hdr_maxsz + \
209 				decode_sequence_maxsz + \
210 				decode_putfh_maxsz + \
211 				decode_listxattrs_maxsz)
212 #define NFS4_enc_removexattr_sz	(compound_encode_hdr_maxsz + \
213 				encode_sequence_maxsz + \
214 				encode_putfh_maxsz + \
215 				encode_removexattr_maxsz)
216 #define NFS4_dec_removexattr_sz	(compound_decode_hdr_maxsz + \
217 				decode_sequence_maxsz + \
218 				decode_putfh_maxsz + \
219 				decode_removexattr_maxsz)
220 
221 /*
222  * These values specify the maximum amount of data that is not
223  * associated with the extended attribute name or extended
224  * attribute list in the SETXATTR, GETXATTR and LISTXATTR
225  * respectively.
226  */
227 const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
228 					compound_encode_hdr_maxsz +
229 					encode_sequence_maxsz +
230 					encode_putfh_maxsz + 1 +
231 					nfs4_xattr_name_maxsz)
232 					* XDR_UNIT);
233 
234 const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
235 					compound_decode_hdr_maxsz +
236 					decode_sequence_maxsz +
237 					decode_putfh_maxsz + 1) * XDR_UNIT);
238 
239 const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
240 					compound_decode_hdr_maxsz +
241 					decode_sequence_maxsz +
242 					decode_putfh_maxsz + 3) * XDR_UNIT);
243 
244 static void encode_fallocate(struct xdr_stream *xdr,
245 			     const struct nfs42_falloc_args *args)
246 {
247 	encode_nfs4_stateid(xdr, &args->falloc_stateid);
248 	encode_uint64(xdr, args->falloc_offset);
249 	encode_uint64(xdr, args->falloc_length);
250 }
251 
252 static void encode_allocate(struct xdr_stream *xdr,
253 			    const struct nfs42_falloc_args *args,
254 			    struct compound_hdr *hdr)
255 {
256 	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
257 	encode_fallocate(xdr, args);
258 }
259 
260 static void encode_nl4_server(struct xdr_stream *xdr,
261 			      const struct nl4_server *ns)
262 {
263 	encode_uint32(xdr, ns->nl4_type);
264 	switch (ns->nl4_type) {
265 	case NL4_NAME:
266 	case NL4_URL:
267 		encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
268 		break;
269 	case NL4_NETADDR:
270 		encode_string(xdr, ns->u.nl4_addr.netid_len,
271 			      ns->u.nl4_addr.netid);
272 		encode_string(xdr, ns->u.nl4_addr.addr_len,
273 			      ns->u.nl4_addr.addr);
274 		break;
275 	default:
276 		WARN_ON_ONCE(1);
277 	}
278 }
279 
280 static void encode_copy(struct xdr_stream *xdr,
281 			const struct nfs42_copy_args *args,
282 			struct compound_hdr *hdr)
283 {
284 	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
285 	encode_nfs4_stateid(xdr, &args->src_stateid);
286 	encode_nfs4_stateid(xdr, &args->dst_stateid);
287 
288 	encode_uint64(xdr, args->src_pos);
289 	encode_uint64(xdr, args->dst_pos);
290 	encode_uint64(xdr, args->count);
291 
292 	encode_uint32(xdr, 1); /* consecutive = true */
293 	encode_uint32(xdr, args->sync);
294 	if (args->cp_src == NULL) { /* intra-ssc */
295 		encode_uint32(xdr, 0); /* no src server list */
296 		return;
297 	}
298 	encode_uint32(xdr, 1); /* supporting 1 server */
299 	encode_nl4_server(xdr, args->cp_src);
300 }
301 
302 static void encode_offload_cancel(struct xdr_stream *xdr,
303 				  const struct nfs42_offload_status_args *args,
304 				  struct compound_hdr *hdr)
305 {
306 	encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
307 	encode_nfs4_stateid(xdr, &args->osa_stateid);
308 }
309 
310 static void encode_copy_notify(struct xdr_stream *xdr,
311 			       const struct nfs42_copy_notify_args *args,
312 			       struct compound_hdr *hdr)
313 {
314 	encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
315 	encode_nfs4_stateid(xdr, &args->cna_src_stateid);
316 	encode_nl4_server(xdr, &args->cna_dst);
317 }
318 
319 static void encode_deallocate(struct xdr_stream *xdr,
320 			      const struct nfs42_falloc_args *args,
321 			      struct compound_hdr *hdr)
322 {
323 	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
324 	encode_fallocate(xdr, args);
325 }
326 
327 static void encode_seek(struct xdr_stream *xdr,
328 			const struct nfs42_seek_args *args,
329 			struct compound_hdr *hdr)
330 {
331 	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
332 	encode_nfs4_stateid(xdr, &args->sa_stateid);
333 	encode_uint64(xdr, args->sa_offset);
334 	encode_uint32(xdr, args->sa_what);
335 }
336 
337 static void encode_layoutstats(struct xdr_stream *xdr,
338 			       const struct nfs42_layoutstat_args *args,
339 			       struct nfs42_layoutstat_devinfo *devinfo,
340 			       struct compound_hdr *hdr)
341 {
342 	__be32 *p;
343 
344 	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
345 	p = reserve_space(xdr, 8 + 8);
346 	p = xdr_encode_hyper(p, devinfo->offset);
347 	p = xdr_encode_hyper(p, devinfo->length);
348 	encode_nfs4_stateid(xdr, &args->stateid);
349 	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
350 	p = xdr_encode_hyper(p, devinfo->read_count);
351 	p = xdr_encode_hyper(p, devinfo->read_bytes);
352 	p = xdr_encode_hyper(p, devinfo->write_count);
353 	p = xdr_encode_hyper(p, devinfo->write_bytes);
354 	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
355 			NFS4_DEVICEID4_SIZE);
356 	/* Encode layoutupdate4 */
357 	*p++ = cpu_to_be32(devinfo->layout_type);
358 	if (devinfo->ld_private.ops)
359 		devinfo->ld_private.ops->encode(xdr, args,
360 				&devinfo->ld_private);
361 	else
362 		encode_uint32(xdr, 0);
363 }
364 
365 static void encode_clone(struct xdr_stream *xdr,
366 			 const struct nfs42_clone_args *args,
367 			 struct compound_hdr *hdr)
368 {
369 	__be32 *p;
370 
371 	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
372 	encode_nfs4_stateid(xdr, &args->src_stateid);
373 	encode_nfs4_stateid(xdr, &args->dst_stateid);
374 	p = reserve_space(xdr, 3*8);
375 	p = xdr_encode_hyper(p, args->src_offset);
376 	p = xdr_encode_hyper(p, args->dst_offset);
377 	xdr_encode_hyper(p, args->count);
378 }
379 
380 static void encode_device_error(struct xdr_stream *xdr,
381 				const struct nfs42_device_error *error)
382 {
383 	__be32 *p;
384 
385 	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
386 	p = xdr_encode_opaque_fixed(p, error->dev_id.data,
387 			NFS4_DEVICEID4_SIZE);
388 	*p++ = cpu_to_be32(error->status);
389 	*p = cpu_to_be32(error->opnum);
390 }
391 
392 static void encode_layouterror(struct xdr_stream *xdr,
393 			       const struct nfs42_layout_error *args,
394 			       struct compound_hdr *hdr)
395 {
396 	__be32 *p;
397 
398 	encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
399 	p = reserve_space(xdr, 8 + 8);
400 	p = xdr_encode_hyper(p, args->offset);
401 	p = xdr_encode_hyper(p, args->length);
402 	encode_nfs4_stateid(xdr, &args->stateid);
403 	p = reserve_space(xdr, 4);
404 	*p = cpu_to_be32(1);
405 	encode_device_error(xdr, &args->errors[0]);
406 }
407 
408 static void encode_setxattr(struct xdr_stream *xdr,
409 			    const struct nfs42_setxattrargs *arg,
410 			    struct compound_hdr *hdr)
411 {
412 	__be32 *p;
413 
414 	BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
415 	BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
416 
417 	encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
418 	p = reserve_space(xdr, 4);
419 	*p = cpu_to_be32(arg->xattr_flags);
420 	encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
421 	p = reserve_space(xdr, 4);
422 	*p = cpu_to_be32(arg->xattr_len);
423 	if (arg->xattr_len)
424 		xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
425 }
426 
427 static int decode_setxattr(struct xdr_stream *xdr,
428 			   struct nfs4_change_info *cinfo)
429 {
430 	int status;
431 
432 	status = decode_op_hdr(xdr, OP_SETXATTR);
433 	if (status)
434 		goto out;
435 	status = decode_change_info(xdr, cinfo);
436 out:
437 	return status;
438 }
439 
440 
441 static void encode_getxattr(struct xdr_stream *xdr, const char *name,
442 			    struct compound_hdr *hdr)
443 {
444 	encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
445 	encode_string(xdr, strlen(name), name);
446 }
447 
448 static int decode_getxattr(struct xdr_stream *xdr,
449 			   struct nfs42_getxattrres *res,
450 			   struct rpc_rqst *req)
451 {
452 	int status;
453 	__be32 *p;
454 	u32 len, rdlen;
455 
456 	status = decode_op_hdr(xdr, OP_GETXATTR);
457 	if (status)
458 		return status;
459 
460 	p = xdr_inline_decode(xdr, 4);
461 	if (unlikely(!p))
462 		return -EIO;
463 
464 	len = be32_to_cpup(p);
465 	if (len > req->rq_rcv_buf.page_len)
466 		return -ERANGE;
467 
468 	res->xattr_len = len;
469 
470 	if (len > 0) {
471 		rdlen = xdr_read_pages(xdr, len);
472 		if (rdlen < len)
473 			return -EIO;
474 	}
475 
476 	return 0;
477 }
478 
479 static void encode_removexattr(struct xdr_stream *xdr, const char *name,
480 			       struct compound_hdr *hdr)
481 {
482 	encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
483 	encode_string(xdr, strlen(name), name);
484 }
485 
486 
487 static int decode_removexattr(struct xdr_stream *xdr,
488 			   struct nfs4_change_info *cinfo)
489 {
490 	int status;
491 
492 	status = decode_op_hdr(xdr, OP_REMOVEXATTR);
493 	if (status)
494 		goto out;
495 
496 	status = decode_change_info(xdr, cinfo);
497 out:
498 	return status;
499 }
500 
501 static void encode_listxattrs(struct xdr_stream *xdr,
502 			     const struct nfs42_listxattrsargs *arg,
503 			     struct compound_hdr *hdr)
504 {
505 	__be32 *p;
506 
507 	encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz + 1, hdr);
508 
509 	p = reserve_space(xdr, 12);
510 	if (unlikely(!p))
511 		return;
512 
513 	p = xdr_encode_hyper(p, arg->cookie);
514 	/*
515 	 * RFC 8276 says to specify the full max length of the LISTXATTRS
516 	 * XDR reply. Count is set to the XDR length of the names array
517 	 * plus the EOF marker. So, add the cookie and the names count.
518 	 */
519 	*p = cpu_to_be32(arg->count + 8 + 4);
520 }
521 
522 static int decode_listxattrs(struct xdr_stream *xdr,
523 			    struct nfs42_listxattrsres *res)
524 {
525 	int status;
526 	__be32 *p;
527 	u32 count, len, ulen;
528 	size_t left, copied;
529 	char *buf;
530 
531 	status = decode_op_hdr(xdr, OP_LISTXATTRS);
532 	if (status) {
533 		/*
534 		 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
535 		 * should be translated to ERANGE.
536 		 */
537 		if (status == -ETOOSMALL)
538 			status = -ERANGE;
539 		goto out;
540 	}
541 
542 	p = xdr_inline_decode(xdr, 8);
543 	if (unlikely(!p))
544 		return -EIO;
545 
546 	xdr_decode_hyper(p, &res->cookie);
547 
548 	p = xdr_inline_decode(xdr, 4);
549 	if (unlikely(!p))
550 		return -EIO;
551 
552 	left = res->xattr_len;
553 	buf = res->xattr_buf;
554 
555 	count = be32_to_cpup(p);
556 	copied = 0;
557 
558 	/*
559 	 * We have asked for enough room to encode the maximum number
560 	 * of possible attribute names, so everything should fit.
561 	 *
562 	 * But, don't rely on that assumption. Just decode entries
563 	 * until they don't fit anymore, just in case the server did
564 	 * something odd.
565 	 */
566 	while (count--) {
567 		p = xdr_inline_decode(xdr, 4);
568 		if (unlikely(!p))
569 			return -EIO;
570 
571 		len = be32_to_cpup(p);
572 		if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
573 			status = -ERANGE;
574 			goto out;
575 		}
576 
577 		p = xdr_inline_decode(xdr, len);
578 		if (unlikely(!p))
579 			return -EIO;
580 
581 		ulen = len + XATTR_USER_PREFIX_LEN + 1;
582 		if (buf) {
583 			if (ulen > left) {
584 				status = -ERANGE;
585 				goto out;
586 			}
587 
588 			memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
589 			memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
590 
591 			buf[ulen - 1] = 0;
592 			buf += ulen;
593 			left -= ulen;
594 		}
595 		copied += ulen;
596 	}
597 
598 	p = xdr_inline_decode(xdr, 4);
599 	if (unlikely(!p))
600 		return -EIO;
601 
602 	res->eof = be32_to_cpup(p);
603 	res->copied = copied;
604 
605 out:
606 	if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
607 		status = -E2BIG;
608 
609 	return status;
610 }
611 
612 /*
613  * Encode ALLOCATE request
614  */
615 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
616 				  struct xdr_stream *xdr,
617 				  const void *data)
618 {
619 	const struct nfs42_falloc_args *args = data;
620 	struct compound_hdr hdr = {
621 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
622 	};
623 
624 	encode_compound_hdr(xdr, req, &hdr);
625 	encode_sequence(xdr, &args->seq_args, &hdr);
626 	encode_putfh(xdr, args->falloc_fh, &hdr);
627 	encode_allocate(xdr, args, &hdr);
628 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
629 	encode_nops(&hdr);
630 }
631 
632 static void encode_copy_commit(struct xdr_stream *xdr,
633 			  const struct nfs42_copy_args *args,
634 			  struct compound_hdr *hdr)
635 {
636 	__be32 *p;
637 
638 	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
639 	p = reserve_space(xdr, 12);
640 	p = xdr_encode_hyper(p, args->dst_pos);
641 	*p = cpu_to_be32(args->count);
642 }
643 
644 /*
645  * Encode COPY request
646  */
647 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
648 			      struct xdr_stream *xdr,
649 			      const void *data)
650 {
651 	const struct nfs42_copy_args *args = data;
652 	struct compound_hdr hdr = {
653 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
654 	};
655 
656 	encode_compound_hdr(xdr, req, &hdr);
657 	encode_sequence(xdr, &args->seq_args, &hdr);
658 	encode_putfh(xdr, args->src_fh, &hdr);
659 	encode_savefh(xdr, &hdr);
660 	encode_putfh(xdr, args->dst_fh, &hdr);
661 	encode_copy(xdr, args, &hdr);
662 	if (args->sync)
663 		encode_copy_commit(xdr, args, &hdr);
664 	encode_nops(&hdr);
665 }
666 
667 /*
668  * Encode OFFLOAD_CANEL request
669  */
670 static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
671 					struct xdr_stream *xdr,
672 					const void *data)
673 {
674 	const struct nfs42_offload_status_args *args = data;
675 	struct compound_hdr hdr = {
676 		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
677 	};
678 
679 	encode_compound_hdr(xdr, req, &hdr);
680 	encode_sequence(xdr, &args->osa_seq_args, &hdr);
681 	encode_putfh(xdr, args->osa_src_fh, &hdr);
682 	encode_offload_cancel(xdr, args, &hdr);
683 	encode_nops(&hdr);
684 }
685 
686 /*
687  * Encode COPY_NOTIFY request
688  */
689 static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
690 				     struct xdr_stream *xdr,
691 				     const void *data)
692 {
693 	const struct nfs42_copy_notify_args *args = data;
694 	struct compound_hdr hdr = {
695 		.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
696 	};
697 
698 	encode_compound_hdr(xdr, req, &hdr);
699 	encode_sequence(xdr, &args->cna_seq_args, &hdr);
700 	encode_putfh(xdr, args->cna_src_fh, &hdr);
701 	encode_copy_notify(xdr, args, &hdr);
702 	encode_nops(&hdr);
703 }
704 
705 /*
706  * Encode DEALLOCATE request
707  */
708 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
709 				    struct xdr_stream *xdr,
710 				    const void *data)
711 {
712 	const struct nfs42_falloc_args *args = data;
713 	struct compound_hdr hdr = {
714 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
715 	};
716 
717 	encode_compound_hdr(xdr, req, &hdr);
718 	encode_sequence(xdr, &args->seq_args, &hdr);
719 	encode_putfh(xdr, args->falloc_fh, &hdr);
720 	encode_deallocate(xdr, args, &hdr);
721 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
722 	encode_nops(&hdr);
723 }
724 
725 /*
726  * Encode SEEK request
727  */
728 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
729 			      struct xdr_stream *xdr,
730 			      const void *data)
731 {
732 	const struct nfs42_seek_args *args = data;
733 	struct compound_hdr hdr = {
734 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
735 	};
736 
737 	encode_compound_hdr(xdr, req, &hdr);
738 	encode_sequence(xdr, &args->seq_args, &hdr);
739 	encode_putfh(xdr, args->sa_fh, &hdr);
740 	encode_seek(xdr, args, &hdr);
741 	encode_nops(&hdr);
742 }
743 
744 /*
745  * Encode LAYOUTSTATS request
746  */
747 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
748 				     struct xdr_stream *xdr,
749 				     const void *data)
750 {
751 	const struct nfs42_layoutstat_args *args = data;
752 	int i;
753 
754 	struct compound_hdr hdr = {
755 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
756 	};
757 
758 	encode_compound_hdr(xdr, req, &hdr);
759 	encode_sequence(xdr, &args->seq_args, &hdr);
760 	encode_putfh(xdr, args->fh, &hdr);
761 	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
762 	for (i = 0; i < args->num_dev; i++)
763 		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
764 	encode_nops(&hdr);
765 }
766 
767 /*
768  * Encode CLONE request
769  */
770 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
771 			       struct xdr_stream *xdr,
772 			       const void *data)
773 {
774 	const struct nfs42_clone_args *args = data;
775 	struct compound_hdr hdr = {
776 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
777 	};
778 
779 	encode_compound_hdr(xdr, req, &hdr);
780 	encode_sequence(xdr, &args->seq_args, &hdr);
781 	encode_putfh(xdr, args->src_fh, &hdr);
782 	encode_savefh(xdr, &hdr);
783 	encode_putfh(xdr, args->dst_fh, &hdr);
784 	encode_clone(xdr, args, &hdr);
785 	encode_getfattr(xdr, args->dst_bitmask, &hdr);
786 	encode_nops(&hdr);
787 }
788 
789 /*
790  * Encode LAYOUTERROR request
791  */
792 static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
793 				     struct xdr_stream *xdr,
794 				     const void *data)
795 {
796 	const struct nfs42_layouterror_args *args = data;
797 	struct compound_hdr hdr = {
798 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
799 	};
800 	int i;
801 
802 	encode_compound_hdr(xdr, req, &hdr);
803 	encode_sequence(xdr, &args->seq_args, &hdr);
804 	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
805 	for (i = 0; i < args->num_errors; i++)
806 		encode_layouterror(xdr, &args->errors[i], &hdr);
807 	encode_nops(&hdr);
808 }
809 
810 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
811 {
812 	return decode_op_hdr(xdr, OP_ALLOCATE);
813 }
814 
815 static int decode_write_response(struct xdr_stream *xdr,
816 				 struct nfs42_write_res *res)
817 {
818 	__be32 *p;
819 	int status, count;
820 
821 	p = xdr_inline_decode(xdr, 4);
822 	if (unlikely(!p))
823 		return -EIO;
824 	count = be32_to_cpup(p);
825 	if (count > 1)
826 		return -EREMOTEIO;
827 	else if (count == 1) {
828 		status = decode_opaque_fixed(xdr, &res->stateid,
829 				NFS4_STATEID_SIZE);
830 		if (unlikely(status))
831 			return -EIO;
832 	}
833 	p = xdr_inline_decode(xdr, 8 + 4);
834 	if (unlikely(!p))
835 		return -EIO;
836 	p = xdr_decode_hyper(p, &res->count);
837 	res->verifier.committed = be32_to_cpup(p);
838 	return decode_verifier(xdr, &res->verifier.verifier);
839 }
840 
841 static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
842 {
843 	struct nfs42_netaddr *naddr;
844 	uint32_t dummy;
845 	char *dummy_str;
846 	__be32 *p;
847 	int status;
848 
849 	/* nl_type */
850 	p = xdr_inline_decode(xdr, 4);
851 	if (unlikely(!p))
852 		return -EIO;
853 	ns->nl4_type = be32_to_cpup(p);
854 	switch (ns->nl4_type) {
855 	case NL4_NAME:
856 	case NL4_URL:
857 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
858 		if (unlikely(status))
859 			return status;
860 		if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
861 			return -EIO;
862 		memcpy(&ns->u.nl4_str, dummy_str, dummy);
863 		ns->u.nl4_str_sz = dummy;
864 		break;
865 	case NL4_NETADDR:
866 		naddr = &ns->u.nl4_addr;
867 
868 		/* netid string */
869 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
870 		if (unlikely(status))
871 			return status;
872 		if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
873 			return -EIO;
874 		naddr->netid_len = dummy;
875 		memcpy(naddr->netid, dummy_str, naddr->netid_len);
876 
877 		/* uaddr string */
878 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
879 		if (unlikely(status))
880 			return status;
881 		if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
882 			return -EIO;
883 		naddr->addr_len = dummy;
884 		memcpy(naddr->addr, dummy_str, naddr->addr_len);
885 		break;
886 	default:
887 		WARN_ON_ONCE(1);
888 		return -EIO;
889 	}
890 	return 0;
891 }
892 
893 static int decode_copy_requirements(struct xdr_stream *xdr,
894 				    struct nfs42_copy_res *res) {
895 	__be32 *p;
896 
897 	p = xdr_inline_decode(xdr, 4 + 4);
898 	if (unlikely(!p))
899 		return -EIO;
900 
901 	res->consecutive = be32_to_cpup(p++);
902 	res->synchronous = be32_to_cpup(p++);
903 	return 0;
904 }
905 
906 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
907 {
908 	int status;
909 
910 	status = decode_op_hdr(xdr, OP_COPY);
911 	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
912 		status = decode_copy_requirements(xdr, res);
913 		if (status)
914 			return status;
915 		return NFS4ERR_OFFLOAD_NO_REQS;
916 	} else if (status)
917 		return status;
918 
919 	status = decode_write_response(xdr, &res->write_res);
920 	if (status)
921 		return status;
922 
923 	return decode_copy_requirements(xdr, res);
924 }
925 
926 static int decode_offload_cancel(struct xdr_stream *xdr,
927 				 struct nfs42_offload_status_res *res)
928 {
929 	return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
930 }
931 
932 static int decode_copy_notify(struct xdr_stream *xdr,
933 			      struct nfs42_copy_notify_res *res)
934 {
935 	__be32 *p;
936 	int status, count;
937 
938 	status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
939 	if (status)
940 		return status;
941 	/* cnr_lease_time */
942 	p = xdr_inline_decode(xdr, 12);
943 	if (unlikely(!p))
944 		return -EIO;
945 	p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
946 	res->cnr_lease_time.nseconds = be32_to_cpup(p);
947 
948 	status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
949 	if (unlikely(status))
950 		return -EIO;
951 
952 	/* number of source addresses */
953 	p = xdr_inline_decode(xdr, 4);
954 	if (unlikely(!p))
955 		return -EIO;
956 
957 	count = be32_to_cpup(p);
958 	if (count > 1)
959 		pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
960 			 __func__, count);
961 
962 	status = decode_nl4_server(xdr, &res->cnr_src);
963 	if (unlikely(status))
964 		return -EIO;
965 	return 0;
966 }
967 
968 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
969 {
970 	return decode_op_hdr(xdr, OP_DEALLOCATE);
971 }
972 
973 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
974 {
975 	int status;
976 	__be32 *p;
977 
978 	status = decode_op_hdr(xdr, OP_SEEK);
979 	if (status)
980 		return status;
981 
982 	p = xdr_inline_decode(xdr, 4 + 8);
983 	if (unlikely(!p))
984 		return -EIO;
985 
986 	res->sr_eof = be32_to_cpup(p++);
987 	p = xdr_decode_hyper(p, &res->sr_offset);
988 	return 0;
989 }
990 
991 static int decode_layoutstats(struct xdr_stream *xdr)
992 {
993 	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
994 }
995 
996 static int decode_clone(struct xdr_stream *xdr)
997 {
998 	return decode_op_hdr(xdr, OP_CLONE);
999 }
1000 
1001 static int decode_layouterror(struct xdr_stream *xdr)
1002 {
1003 	return decode_op_hdr(xdr, OP_LAYOUTERROR);
1004 }
1005 
1006 /*
1007  * Decode ALLOCATE request
1008  */
1009 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
1010 				 struct xdr_stream *xdr,
1011 				 void *data)
1012 {
1013 	struct nfs42_falloc_res *res = data;
1014 	struct compound_hdr hdr;
1015 	int status;
1016 
1017 	status = decode_compound_hdr(xdr, &hdr);
1018 	if (status)
1019 		goto out;
1020 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1021 	if (status)
1022 		goto out;
1023 	status = decode_putfh(xdr);
1024 	if (status)
1025 		goto out;
1026 	status = decode_allocate(xdr, res);
1027 	if (status)
1028 		goto out;
1029 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1030 out:
1031 	return status;
1032 }
1033 
1034 /*
1035  * Decode COPY response
1036  */
1037 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
1038 			     struct xdr_stream *xdr,
1039 			     void *data)
1040 {
1041 	struct nfs42_copy_res *res = data;
1042 	struct compound_hdr hdr;
1043 	int status;
1044 
1045 	status = decode_compound_hdr(xdr, &hdr);
1046 	if (status)
1047 		goto out;
1048 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1049 	if (status)
1050 		goto out;
1051 	status = decode_putfh(xdr);
1052 	if (status)
1053 		goto out;
1054 	status = decode_savefh(xdr);
1055 	if (status)
1056 		goto out;
1057 	status = decode_putfh(xdr);
1058 	if (status)
1059 		goto out;
1060 	status = decode_copy(xdr, res);
1061 	if (status)
1062 		goto out;
1063 	if (res->commit_res.verf)
1064 		status = decode_commit(xdr, &res->commit_res);
1065 out:
1066 	return status;
1067 }
1068 
1069 /*
1070  * Decode OFFLOAD_CANCEL response
1071  */
1072 static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
1073 				       struct xdr_stream *xdr,
1074 				       void *data)
1075 {
1076 	struct nfs42_offload_status_res *res = data;
1077 	struct compound_hdr hdr;
1078 	int status;
1079 
1080 	status = decode_compound_hdr(xdr, &hdr);
1081 	if (status)
1082 		goto out;
1083 	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1084 	if (status)
1085 		goto out;
1086 	status = decode_putfh(xdr);
1087 	if (status)
1088 		goto out;
1089 	status = decode_offload_cancel(xdr, res);
1090 
1091 out:
1092 	return status;
1093 }
1094 
1095 /*
1096  * Decode COPY_NOTIFY response
1097  */
1098 static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1099 				    struct xdr_stream *xdr,
1100 				    void *data)
1101 {
1102 	struct nfs42_copy_notify_res *res = data;
1103 	struct compound_hdr hdr;
1104 	int status;
1105 
1106 	status = decode_compound_hdr(xdr, &hdr);
1107 	if (status)
1108 		goto out;
1109 	status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1110 	if (status)
1111 		goto out;
1112 	status = decode_putfh(xdr);
1113 	if (status)
1114 		goto out;
1115 	status = decode_copy_notify(xdr, res);
1116 
1117 out:
1118 	return status;
1119 }
1120 
1121 /*
1122  * Decode DEALLOCATE request
1123  */
1124 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
1125 				   struct xdr_stream *xdr,
1126 				   void *data)
1127 {
1128 	struct nfs42_falloc_res *res = data;
1129 	struct compound_hdr hdr;
1130 	int status;
1131 
1132 	status = decode_compound_hdr(xdr, &hdr);
1133 	if (status)
1134 		goto out;
1135 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1136 	if (status)
1137 		goto out;
1138 	status = decode_putfh(xdr);
1139 	if (status)
1140 		goto out;
1141 	status = decode_deallocate(xdr, res);
1142 	if (status)
1143 		goto out;
1144 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1145 out:
1146 	return status;
1147 }
1148 
1149 /*
1150  * Decode SEEK request
1151  */
1152 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
1153 			     struct xdr_stream *xdr,
1154 			     void *data)
1155 {
1156 	struct nfs42_seek_res *res = data;
1157 	struct compound_hdr hdr;
1158 	int status;
1159 
1160 	status = decode_compound_hdr(xdr, &hdr);
1161 	if (status)
1162 		goto out;
1163 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1164 	if (status)
1165 		goto out;
1166 	status = decode_putfh(xdr);
1167 	if (status)
1168 		goto out;
1169 	status = decode_seek(xdr, res);
1170 out:
1171 	return status;
1172 }
1173 
1174 /*
1175  * Decode LAYOUTSTATS request
1176  */
1177 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
1178 				    struct xdr_stream *xdr,
1179 				    void *data)
1180 {
1181 	struct nfs42_layoutstat_res *res = data;
1182 	struct compound_hdr hdr;
1183 	int status, i;
1184 
1185 	status = decode_compound_hdr(xdr, &hdr);
1186 	if (status)
1187 		goto out;
1188 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1189 	if (status)
1190 		goto out;
1191 	status = decode_putfh(xdr);
1192 	if (status)
1193 		goto out;
1194 	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
1195 	for (i = 0; i < res->num_dev; i++) {
1196 		status = decode_layoutstats(xdr);
1197 		if (status)
1198 			goto out;
1199 	}
1200 out:
1201 	res->rpc_status = status;
1202 	return status;
1203 }
1204 
1205 /*
1206  * Decode CLONE request
1207  */
1208 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
1209 			      struct xdr_stream *xdr,
1210 			      void *data)
1211 {
1212 	struct nfs42_clone_res *res = data;
1213 	struct compound_hdr hdr;
1214 	int status;
1215 
1216 	status = decode_compound_hdr(xdr, &hdr);
1217 	if (status)
1218 		goto out;
1219 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1220 	if (status)
1221 		goto out;
1222 	status = decode_putfh(xdr);
1223 	if (status)
1224 		goto out;
1225 	status = decode_savefh(xdr);
1226 	if (status)
1227 		goto out;
1228 	status = decode_putfh(xdr);
1229 	if (status)
1230 		goto out;
1231 	status = decode_clone(xdr);
1232 	if (status)
1233 		goto out;
1234 	status = decode_getfattr(xdr, res->dst_fattr, res->server);
1235 
1236 out:
1237 	res->rpc_status = status;
1238 	return status;
1239 }
1240 
1241 /*
1242  * Decode LAYOUTERROR request
1243  */
1244 static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1245 				    struct xdr_stream *xdr,
1246 				    void *data)
1247 {
1248 	struct nfs42_layouterror_res *res = data;
1249 	struct compound_hdr hdr;
1250 	int status, i;
1251 
1252 	status = decode_compound_hdr(xdr, &hdr);
1253 	if (status)
1254 		goto out;
1255 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1256 	if (status)
1257 		goto out;
1258 	status = decode_putfh(xdr);
1259 
1260 	for (i = 0; i < res->num_errors && status == 0; i++)
1261 		status = decode_layouterror(xdr);
1262 out:
1263 	res->rpc_status = status;
1264 	return status;
1265 }
1266 
1267 #ifdef CONFIG_NFS_V4_2
1268 static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1269 				  const void *data)
1270 {
1271 	const struct nfs42_setxattrargs *args = data;
1272 	struct compound_hdr hdr = {
1273 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1274 	};
1275 
1276 	encode_compound_hdr(xdr, req, &hdr);
1277 	encode_sequence(xdr, &args->seq_args, &hdr);
1278 	encode_putfh(xdr, args->fh, &hdr);
1279 	encode_setxattr(xdr, args, &hdr);
1280 	encode_nops(&hdr);
1281 }
1282 
1283 static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1284 				 void *data)
1285 {
1286 	struct nfs42_setxattrres *res = data;
1287 	struct compound_hdr hdr;
1288 	int status;
1289 
1290 	status = decode_compound_hdr(xdr, &hdr);
1291 	if (status)
1292 		goto out;
1293 	status = decode_sequence(xdr, &res->seq_res, req);
1294 	if (status)
1295 		goto out;
1296 	status = decode_putfh(xdr);
1297 	if (status)
1298 		goto out;
1299 
1300 	status = decode_setxattr(xdr, &res->cinfo);
1301 out:
1302 	return status;
1303 }
1304 
1305 static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1306 				  const void *data)
1307 {
1308 	const struct nfs42_getxattrargs *args = data;
1309 	struct compound_hdr hdr = {
1310 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1311 	};
1312 	size_t plen;
1313 
1314 	encode_compound_hdr(xdr, req, &hdr);
1315 	encode_sequence(xdr, &args->seq_args, &hdr);
1316 	encode_putfh(xdr, args->fh, &hdr);
1317 	encode_getxattr(xdr, args->xattr_name, &hdr);
1318 
1319 	plen = args->xattr_len ? args->xattr_len : XATTR_SIZE_MAX;
1320 
1321 	rpc_prepare_reply_pages(req, args->xattr_pages, 0, plen,
1322 	    hdr.replen);
1323 	req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1324 
1325 	encode_nops(&hdr);
1326 }
1327 
1328 static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1329 				 struct xdr_stream *xdr, void *data)
1330 {
1331 	struct nfs42_getxattrres *res = data;
1332 	struct compound_hdr hdr;
1333 	int status;
1334 
1335 	status = decode_compound_hdr(xdr, &hdr);
1336 	if (status)
1337 		goto out;
1338 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1339 	if (status)
1340 		goto out;
1341 	status = decode_putfh(xdr);
1342 	if (status)
1343 		goto out;
1344 	status = decode_getxattr(xdr, res, rqstp);
1345 out:
1346 	return status;
1347 }
1348 
1349 static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1350 				    struct xdr_stream *xdr, const void *data)
1351 {
1352 	const struct nfs42_listxattrsargs *args = data;
1353 	struct compound_hdr hdr = {
1354 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1355 	};
1356 
1357 	encode_compound_hdr(xdr, req, &hdr);
1358 	encode_sequence(xdr, &args->seq_args, &hdr);
1359 	encode_putfh(xdr, args->fh, &hdr);
1360 	encode_listxattrs(xdr, args, &hdr);
1361 
1362 	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
1363 	    hdr.replen);
1364 	req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1365 
1366 	encode_nops(&hdr);
1367 }
1368 
1369 static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1370 				   struct xdr_stream *xdr, void *data)
1371 {
1372 	struct nfs42_listxattrsres *res = data;
1373 	struct compound_hdr hdr;
1374 	int status;
1375 
1376 	xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
1377 
1378 	status = decode_compound_hdr(xdr, &hdr);
1379 	if (status)
1380 		goto out;
1381 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1382 	if (status)
1383 		goto out;
1384 	status = decode_putfh(xdr);
1385 	if (status)
1386 		goto out;
1387 	status = decode_listxattrs(xdr, res);
1388 out:
1389 	return status;
1390 }
1391 
1392 static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1393 				     struct xdr_stream *xdr, const void *data)
1394 {
1395 	const struct nfs42_removexattrargs *args = data;
1396 	struct compound_hdr hdr = {
1397 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1398 	};
1399 
1400 	encode_compound_hdr(xdr, req, &hdr);
1401 	encode_sequence(xdr, &args->seq_args, &hdr);
1402 	encode_putfh(xdr, args->fh, &hdr);
1403 	encode_removexattr(xdr, args->xattr_name, &hdr);
1404 	encode_nops(&hdr);
1405 }
1406 
1407 static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1408 				    struct xdr_stream *xdr, void *data)
1409 {
1410 	struct nfs42_removexattrres *res = data;
1411 	struct compound_hdr hdr;
1412 	int status;
1413 
1414 	status = decode_compound_hdr(xdr, &hdr);
1415 	if (status)
1416 		goto out;
1417 	status = decode_sequence(xdr, &res->seq_res, req);
1418 	if (status)
1419 		goto out;
1420 	status = decode_putfh(xdr);
1421 	if (status)
1422 		goto out;
1423 
1424 	status = decode_removexattr(xdr, &res->cinfo);
1425 out:
1426 	return status;
1427 }
1428 #endif
1429 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
1430