• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_read_plus_maxsz		(op_encode_hdr_maxsz + \
49 					 encode_stateid_maxsz + 3)
50 #define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \
51 					(1 /* data_content4 */ + \
52 					 2 /* data_info4.di_offset */ + \
53 					 1 /* data_info4.di_length */)
54 #define NFS42_READ_PLUS_HOLE_SEGMENT_SIZE \
55 					(1 /* data_content4 */ + \
56 					 2 /* data_info4.di_offset */ + \
57 					 2 /* data_info4.di_length */)
58 #define READ_PLUS_SEGMENT_SIZE_DIFF	(NFS42_READ_PLUS_HOLE_SEGMENT_SIZE - \
59 					 NFS42_READ_PLUS_DATA_SEGMENT_SIZE)
60 #define decode_read_plus_maxsz		(op_decode_hdr_maxsz + \
61 					 1 /* rpr_eof */ + \
62 					 1 /* rpr_contents count */ + \
63 					 NFS42_READ_PLUS_HOLE_SEGMENT_SIZE)
64 #define encode_seek_maxsz		(op_encode_hdr_maxsz + \
65 					 encode_stateid_maxsz + \
66 					 2 /* offset */ + \
67 					 1 /* whence */)
68 #define decode_seek_maxsz		(op_decode_hdr_maxsz + \
69 					 1 /* eof */ + \
70 					 1 /* whence */ + \
71 					 2 /* offset */ + \
72 					 2 /* length */)
73 #define encode_io_info_maxsz		4
74 #define encode_layoutstats_maxsz	(op_decode_hdr_maxsz + \
75 					2 /* offset */ + \
76 					2 /* length */ + \
77 					encode_stateid_maxsz + \
78 					encode_io_info_maxsz + \
79 					encode_io_info_maxsz + \
80 					1 /* opaque devaddr4 length */ + \
81 					XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
82 #define decode_layoutstats_maxsz	(op_decode_hdr_maxsz)
83 #define encode_device_error_maxsz	(XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
84 					1 /* status */ + 1 /* opnum */)
85 #define encode_layouterror_maxsz	(op_decode_hdr_maxsz + \
86 					2 /* offset */ + \
87 					2 /* length */ + \
88 					encode_stateid_maxsz + \
89 					1 /* Array size */ + \
90 					encode_device_error_maxsz)
91 #define decode_layouterror_maxsz	(op_decode_hdr_maxsz)
92 #define encode_clone_maxsz		(encode_stateid_maxsz + \
93 					encode_stateid_maxsz + \
94 					2 /* src offset */ + \
95 					2 /* dst offset */ + \
96 					2 /* count */)
97 #define decode_clone_maxsz		(op_decode_hdr_maxsz)
98 
99 #define NFS4_enc_allocate_sz		(compound_encode_hdr_maxsz + \
100 					 encode_sequence_maxsz + \
101 					 encode_putfh_maxsz + \
102 					 encode_allocate_maxsz + \
103 					 encode_getattr_maxsz)
104 #define NFS4_dec_allocate_sz		(compound_decode_hdr_maxsz + \
105 					 decode_sequence_maxsz + \
106 					 decode_putfh_maxsz + \
107 					 decode_allocate_maxsz + \
108 					 decode_getattr_maxsz)
109 #define NFS4_enc_copy_sz		(compound_encode_hdr_maxsz + \
110 					 encode_sequence_maxsz + \
111 					 encode_putfh_maxsz + \
112 					 encode_savefh_maxsz + \
113 					 encode_putfh_maxsz + \
114 					 encode_copy_maxsz + \
115 					 encode_commit_maxsz)
116 #define NFS4_dec_copy_sz		(compound_decode_hdr_maxsz + \
117 					 decode_sequence_maxsz + \
118 					 decode_putfh_maxsz + \
119 					 decode_savefh_maxsz + \
120 					 decode_putfh_maxsz + \
121 					 decode_copy_maxsz + \
122 					 decode_commit_maxsz)
123 #define NFS4_enc_offload_cancel_sz	(compound_encode_hdr_maxsz + \
124 					 encode_sequence_maxsz + \
125 					 encode_putfh_maxsz + \
126 					 encode_offload_cancel_maxsz)
127 #define NFS4_dec_offload_cancel_sz	(compound_decode_hdr_maxsz + \
128 					 decode_sequence_maxsz + \
129 					 decode_putfh_maxsz + \
130 					 decode_offload_cancel_maxsz)
131 #define NFS4_enc_copy_notify_sz		(compound_encode_hdr_maxsz + \
132 					 encode_putfh_maxsz + \
133 					 encode_copy_notify_maxsz)
134 #define NFS4_dec_copy_notify_sz		(compound_decode_hdr_maxsz + \
135 					 decode_putfh_maxsz + \
136 					 decode_copy_notify_maxsz)
137 #define NFS4_enc_deallocate_sz		(compound_encode_hdr_maxsz + \
138 					 encode_sequence_maxsz + \
139 					 encode_putfh_maxsz + \
140 					 encode_deallocate_maxsz + \
141 					 encode_getattr_maxsz)
142 #define NFS4_dec_deallocate_sz		(compound_decode_hdr_maxsz + \
143 					 decode_sequence_maxsz + \
144 					 decode_putfh_maxsz + \
145 					 decode_deallocate_maxsz + \
146 					 decode_getattr_maxsz)
147 #define NFS4_enc_read_plus_sz		(compound_encode_hdr_maxsz + \
148 					 encode_sequence_maxsz + \
149 					 encode_putfh_maxsz + \
150 					 encode_read_plus_maxsz)
151 #define NFS4_dec_read_plus_sz		(compound_decode_hdr_maxsz + \
152 					 decode_sequence_maxsz + \
153 					 decode_putfh_maxsz + \
154 					 decode_read_plus_maxsz)
155 #define NFS4_enc_seek_sz		(compound_encode_hdr_maxsz + \
156 					 encode_sequence_maxsz + \
157 					 encode_putfh_maxsz + \
158 					 encode_seek_maxsz)
159 #define NFS4_dec_seek_sz		(compound_decode_hdr_maxsz + \
160 					 decode_sequence_maxsz + \
161 					 decode_putfh_maxsz + \
162 					 decode_seek_maxsz)
163 #define NFS4_enc_layoutstats_sz		(compound_encode_hdr_maxsz + \
164 					 encode_sequence_maxsz + \
165 					 encode_putfh_maxsz + \
166 					 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
167 #define NFS4_dec_layoutstats_sz		(compound_decode_hdr_maxsz + \
168 					 decode_sequence_maxsz + \
169 					 decode_putfh_maxsz + \
170 					 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
171 #define NFS4_enc_layouterror_sz		(compound_encode_hdr_maxsz + \
172 					 encode_sequence_maxsz + \
173 					 encode_putfh_maxsz + \
174 					 NFS42_LAYOUTERROR_MAX * \
175 					 encode_layouterror_maxsz)
176 #define NFS4_dec_layouterror_sz		(compound_decode_hdr_maxsz + \
177 					 decode_sequence_maxsz + \
178 					 decode_putfh_maxsz + \
179 					 NFS42_LAYOUTERROR_MAX * \
180 					 decode_layouterror_maxsz)
181 #define NFS4_enc_clone_sz		(compound_encode_hdr_maxsz + \
182 					 encode_sequence_maxsz + \
183 					 encode_putfh_maxsz + \
184 					 encode_savefh_maxsz + \
185 					 encode_putfh_maxsz + \
186 					 encode_clone_maxsz + \
187 					 encode_getattr_maxsz)
188 #define NFS4_dec_clone_sz		(compound_decode_hdr_maxsz + \
189 					 decode_sequence_maxsz + \
190 					 decode_putfh_maxsz + \
191 					 decode_savefh_maxsz + \
192 					 decode_putfh_maxsz + \
193 					 decode_clone_maxsz + \
194 					 decode_getattr_maxsz)
195 
196 /* Not limited by NFS itself, limited by the generic xattr code */
197 #define nfs4_xattr_name_maxsz   XDR_QUADLEN(XATTR_NAME_MAX)
198 
199 #define encode_getxattr_maxsz   (op_encode_hdr_maxsz + 1 + \
200 				 nfs4_xattr_name_maxsz)
201 #define decode_getxattr_maxsz   (op_decode_hdr_maxsz + 1 + pagepad_maxsz)
202 #define encode_setxattr_maxsz   (op_encode_hdr_maxsz + \
203 				 1 + nfs4_xattr_name_maxsz + 1)
204 #define decode_setxattr_maxsz   (op_decode_hdr_maxsz + decode_change_info_maxsz)
205 #define encode_listxattrs_maxsz  (op_encode_hdr_maxsz + 2 + 1)
206 #define decode_listxattrs_maxsz  (op_decode_hdr_maxsz + 2 + 1 + 1 + 1)
207 #define encode_removexattr_maxsz (op_encode_hdr_maxsz + 1 + \
208 				  nfs4_xattr_name_maxsz)
209 #define decode_removexattr_maxsz (op_decode_hdr_maxsz + \
210 				  decode_change_info_maxsz)
211 
212 #define NFS4_enc_getxattr_sz	(compound_encode_hdr_maxsz + \
213 				encode_sequence_maxsz + \
214 				encode_putfh_maxsz + \
215 				encode_getxattr_maxsz)
216 #define NFS4_dec_getxattr_sz	(compound_decode_hdr_maxsz + \
217 				decode_sequence_maxsz + \
218 				decode_putfh_maxsz + \
219 				decode_getxattr_maxsz)
220 #define NFS4_enc_setxattr_sz	(compound_encode_hdr_maxsz + \
221 				encode_sequence_maxsz + \
222 				encode_putfh_maxsz + \
223 				encode_setxattr_maxsz)
224 #define NFS4_dec_setxattr_sz	(compound_decode_hdr_maxsz + \
225 				decode_sequence_maxsz + \
226 				decode_putfh_maxsz + \
227 				decode_setxattr_maxsz)
228 #define NFS4_enc_listxattrs_sz	(compound_encode_hdr_maxsz + \
229 				encode_sequence_maxsz + \
230 				encode_putfh_maxsz + \
231 				encode_listxattrs_maxsz)
232 #define NFS4_dec_listxattrs_sz	(compound_decode_hdr_maxsz + \
233 				decode_sequence_maxsz + \
234 				decode_putfh_maxsz + \
235 				decode_listxattrs_maxsz)
236 #define NFS4_enc_removexattr_sz	(compound_encode_hdr_maxsz + \
237 				encode_sequence_maxsz + \
238 				encode_putfh_maxsz + \
239 				encode_removexattr_maxsz)
240 #define NFS4_dec_removexattr_sz	(compound_decode_hdr_maxsz + \
241 				decode_sequence_maxsz + \
242 				decode_putfh_maxsz + \
243 				decode_removexattr_maxsz)
244 
245 /*
246  * These values specify the maximum amount of data that is not
247  * associated with the extended attribute name or extended
248  * attribute list in the SETXATTR, GETXATTR and LISTXATTR
249  * respectively.
250  */
251 const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
252 					compound_encode_hdr_maxsz +
253 					encode_sequence_maxsz +
254 					encode_putfh_maxsz + 1 +
255 					nfs4_xattr_name_maxsz)
256 					* XDR_UNIT);
257 
258 const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
259 					compound_decode_hdr_maxsz +
260 					decode_sequence_maxsz +
261 					decode_putfh_maxsz + 1) * XDR_UNIT);
262 
263 const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
264 					compound_decode_hdr_maxsz +
265 					decode_sequence_maxsz +
266 					decode_putfh_maxsz + 3) * XDR_UNIT);
267 
encode_fallocate(struct xdr_stream * xdr,const struct nfs42_falloc_args * args)268 static void encode_fallocate(struct xdr_stream *xdr,
269 			     const struct nfs42_falloc_args *args)
270 {
271 	encode_nfs4_stateid(xdr, &args->falloc_stateid);
272 	encode_uint64(xdr, args->falloc_offset);
273 	encode_uint64(xdr, args->falloc_length);
274 }
275 
encode_allocate(struct xdr_stream * xdr,const struct nfs42_falloc_args * args,struct compound_hdr * hdr)276 static void encode_allocate(struct xdr_stream *xdr,
277 			    const struct nfs42_falloc_args *args,
278 			    struct compound_hdr *hdr)
279 {
280 	encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
281 	encode_fallocate(xdr, args);
282 }
283 
encode_nl4_server(struct xdr_stream * xdr,const struct nl4_server * ns)284 static void encode_nl4_server(struct xdr_stream *xdr,
285 			      const struct nl4_server *ns)
286 {
287 	encode_uint32(xdr, ns->nl4_type);
288 	switch (ns->nl4_type) {
289 	case NL4_NAME:
290 	case NL4_URL:
291 		encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
292 		break;
293 	case NL4_NETADDR:
294 		encode_string(xdr, ns->u.nl4_addr.netid_len,
295 			      ns->u.nl4_addr.netid);
296 		encode_string(xdr, ns->u.nl4_addr.addr_len,
297 			      ns->u.nl4_addr.addr);
298 		break;
299 	default:
300 		WARN_ON_ONCE(1);
301 	}
302 }
303 
encode_copy(struct xdr_stream * xdr,const struct nfs42_copy_args * args,struct compound_hdr * hdr)304 static void encode_copy(struct xdr_stream *xdr,
305 			const struct nfs42_copy_args *args,
306 			struct compound_hdr *hdr)
307 {
308 	encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
309 	encode_nfs4_stateid(xdr, &args->src_stateid);
310 	encode_nfs4_stateid(xdr, &args->dst_stateid);
311 
312 	encode_uint64(xdr, args->src_pos);
313 	encode_uint64(xdr, args->dst_pos);
314 	encode_uint64(xdr, args->count);
315 
316 	encode_uint32(xdr, 1); /* consecutive = true */
317 	encode_uint32(xdr, args->sync);
318 	if (args->cp_src == NULL) { /* intra-ssc */
319 		encode_uint32(xdr, 0); /* no src server list */
320 		return;
321 	}
322 	encode_uint32(xdr, 1); /* supporting 1 server */
323 	encode_nl4_server(xdr, args->cp_src);
324 }
325 
encode_offload_cancel(struct xdr_stream * xdr,const struct nfs42_offload_status_args * args,struct compound_hdr * hdr)326 static void encode_offload_cancel(struct xdr_stream *xdr,
327 				  const struct nfs42_offload_status_args *args,
328 				  struct compound_hdr *hdr)
329 {
330 	encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
331 	encode_nfs4_stateid(xdr, &args->osa_stateid);
332 }
333 
encode_copy_notify(struct xdr_stream * xdr,const struct nfs42_copy_notify_args * args,struct compound_hdr * hdr)334 static void encode_copy_notify(struct xdr_stream *xdr,
335 			       const struct nfs42_copy_notify_args *args,
336 			       struct compound_hdr *hdr)
337 {
338 	encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
339 	encode_nfs4_stateid(xdr, &args->cna_src_stateid);
340 	encode_nl4_server(xdr, &args->cna_dst);
341 }
342 
encode_deallocate(struct xdr_stream * xdr,const struct nfs42_falloc_args * args,struct compound_hdr * hdr)343 static void encode_deallocate(struct xdr_stream *xdr,
344 			      const struct nfs42_falloc_args *args,
345 			      struct compound_hdr *hdr)
346 {
347 	encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
348 	encode_fallocate(xdr, args);
349 }
350 
encode_read_plus(struct xdr_stream * xdr,const struct nfs_pgio_args * args,struct compound_hdr * hdr)351 static void encode_read_plus(struct xdr_stream *xdr,
352 			     const struct nfs_pgio_args *args,
353 			     struct compound_hdr *hdr)
354 {
355 	encode_op_hdr(xdr, OP_READ_PLUS, decode_read_plus_maxsz, hdr);
356 	encode_nfs4_stateid(xdr, &args->stateid);
357 	encode_uint64(xdr, args->offset);
358 	encode_uint32(xdr, args->count);
359 }
360 
encode_seek(struct xdr_stream * xdr,const struct nfs42_seek_args * args,struct compound_hdr * hdr)361 static void encode_seek(struct xdr_stream *xdr,
362 			const struct nfs42_seek_args *args,
363 			struct compound_hdr *hdr)
364 {
365 	encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
366 	encode_nfs4_stateid(xdr, &args->sa_stateid);
367 	encode_uint64(xdr, args->sa_offset);
368 	encode_uint32(xdr, args->sa_what);
369 }
370 
encode_layoutstats(struct xdr_stream * xdr,const struct nfs42_layoutstat_args * args,struct nfs42_layoutstat_devinfo * devinfo,struct compound_hdr * hdr)371 static void encode_layoutstats(struct xdr_stream *xdr,
372 			       const struct nfs42_layoutstat_args *args,
373 			       struct nfs42_layoutstat_devinfo *devinfo,
374 			       struct compound_hdr *hdr)
375 {
376 	__be32 *p;
377 
378 	encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
379 	p = reserve_space(xdr, 8 + 8);
380 	p = xdr_encode_hyper(p, devinfo->offset);
381 	p = xdr_encode_hyper(p, devinfo->length);
382 	encode_nfs4_stateid(xdr, &args->stateid);
383 	p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
384 	p = xdr_encode_hyper(p, devinfo->read_count);
385 	p = xdr_encode_hyper(p, devinfo->read_bytes);
386 	p = xdr_encode_hyper(p, devinfo->write_count);
387 	p = xdr_encode_hyper(p, devinfo->write_bytes);
388 	p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
389 			NFS4_DEVICEID4_SIZE);
390 	/* Encode layoutupdate4 */
391 	*p++ = cpu_to_be32(devinfo->layout_type);
392 	if (devinfo->ld_private.ops)
393 		devinfo->ld_private.ops->encode(xdr, args,
394 				&devinfo->ld_private);
395 	else
396 		encode_uint32(xdr, 0);
397 }
398 
encode_clone(struct xdr_stream * xdr,const struct nfs42_clone_args * args,struct compound_hdr * hdr)399 static void encode_clone(struct xdr_stream *xdr,
400 			 const struct nfs42_clone_args *args,
401 			 struct compound_hdr *hdr)
402 {
403 	__be32 *p;
404 
405 	encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
406 	encode_nfs4_stateid(xdr, &args->src_stateid);
407 	encode_nfs4_stateid(xdr, &args->dst_stateid);
408 	p = reserve_space(xdr, 3*8);
409 	p = xdr_encode_hyper(p, args->src_offset);
410 	p = xdr_encode_hyper(p, args->dst_offset);
411 	xdr_encode_hyper(p, args->count);
412 }
413 
encode_device_error(struct xdr_stream * xdr,const struct nfs42_device_error * error)414 static void encode_device_error(struct xdr_stream *xdr,
415 				const struct nfs42_device_error *error)
416 {
417 	__be32 *p;
418 
419 	p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
420 	p = xdr_encode_opaque_fixed(p, error->dev_id.data,
421 			NFS4_DEVICEID4_SIZE);
422 	*p++ = cpu_to_be32(error->status);
423 	*p = cpu_to_be32(error->opnum);
424 }
425 
encode_layouterror(struct xdr_stream * xdr,const struct nfs42_layout_error * args,struct compound_hdr * hdr)426 static void encode_layouterror(struct xdr_stream *xdr,
427 			       const struct nfs42_layout_error *args,
428 			       struct compound_hdr *hdr)
429 {
430 	__be32 *p;
431 
432 	encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
433 	p = reserve_space(xdr, 8 + 8);
434 	p = xdr_encode_hyper(p, args->offset);
435 	p = xdr_encode_hyper(p, args->length);
436 	encode_nfs4_stateid(xdr, &args->stateid);
437 	p = reserve_space(xdr, 4);
438 	*p = cpu_to_be32(1);
439 	encode_device_error(xdr, &args->errors[0]);
440 }
441 
encode_setxattr(struct xdr_stream * xdr,const struct nfs42_setxattrargs * arg,struct compound_hdr * hdr)442 static void encode_setxattr(struct xdr_stream *xdr,
443 			    const struct nfs42_setxattrargs *arg,
444 			    struct compound_hdr *hdr)
445 {
446 	__be32 *p;
447 
448 	BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
449 	BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
450 
451 	encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
452 	p = reserve_space(xdr, 4);
453 	*p = cpu_to_be32(arg->xattr_flags);
454 	encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
455 	p = reserve_space(xdr, 4);
456 	*p = cpu_to_be32(arg->xattr_len);
457 	if (arg->xattr_len)
458 		xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
459 }
460 
decode_setxattr(struct xdr_stream * xdr,struct nfs4_change_info * cinfo)461 static int decode_setxattr(struct xdr_stream *xdr,
462 			   struct nfs4_change_info *cinfo)
463 {
464 	int status;
465 
466 	status = decode_op_hdr(xdr, OP_SETXATTR);
467 	if (status)
468 		goto out;
469 	status = decode_change_info(xdr, cinfo);
470 out:
471 	return status;
472 }
473 
474 
encode_getxattr(struct xdr_stream * xdr,const char * name,struct compound_hdr * hdr)475 static void encode_getxattr(struct xdr_stream *xdr, const char *name,
476 			    struct compound_hdr *hdr)
477 {
478 	encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
479 	encode_string(xdr, strlen(name), name);
480 }
481 
decode_getxattr(struct xdr_stream * xdr,struct nfs42_getxattrres * res,struct rpc_rqst * req)482 static int decode_getxattr(struct xdr_stream *xdr,
483 			   struct nfs42_getxattrres *res,
484 			   struct rpc_rqst *req)
485 {
486 	int status;
487 	__be32 *p;
488 	u32 len, rdlen;
489 
490 	status = decode_op_hdr(xdr, OP_GETXATTR);
491 	if (status)
492 		return status;
493 
494 	p = xdr_inline_decode(xdr, 4);
495 	if (unlikely(!p))
496 		return -EIO;
497 
498 	len = be32_to_cpup(p);
499 
500 	/*
501 	 * Only check against the page length here. The actual
502 	 * requested length may be smaller, but that is only
503 	 * checked against after possibly caching a valid reply.
504 	 */
505 	if (len > req->rq_rcv_buf.page_len)
506 		return -ERANGE;
507 
508 	res->xattr_len = len;
509 
510 	if (len > 0) {
511 		rdlen = xdr_read_pages(xdr, len);
512 		if (rdlen < len)
513 			return -EIO;
514 	}
515 
516 	return 0;
517 }
518 
encode_removexattr(struct xdr_stream * xdr,const char * name,struct compound_hdr * hdr)519 static void encode_removexattr(struct xdr_stream *xdr, const char *name,
520 			       struct compound_hdr *hdr)
521 {
522 	encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
523 	encode_string(xdr, strlen(name), name);
524 }
525 
526 
decode_removexattr(struct xdr_stream * xdr,struct nfs4_change_info * cinfo)527 static int decode_removexattr(struct xdr_stream *xdr,
528 			   struct nfs4_change_info *cinfo)
529 {
530 	int status;
531 
532 	status = decode_op_hdr(xdr, OP_REMOVEXATTR);
533 	if (status)
534 		goto out;
535 
536 	status = decode_change_info(xdr, cinfo);
537 out:
538 	return status;
539 }
540 
encode_listxattrs(struct xdr_stream * xdr,const struct nfs42_listxattrsargs * arg,struct compound_hdr * hdr)541 static void encode_listxattrs(struct xdr_stream *xdr,
542 			     const struct nfs42_listxattrsargs *arg,
543 			     struct compound_hdr *hdr)
544 {
545 	__be32 *p;
546 
547 	encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr);
548 
549 	p = reserve_space(xdr, 12);
550 	if (unlikely(!p))
551 		return;
552 
553 	p = xdr_encode_hyper(p, arg->cookie);
554 	/*
555 	 * RFC 8276 says to specify the full max length of the LISTXATTRS
556 	 * XDR reply. Count is set to the XDR length of the names array
557 	 * plus the EOF marker. So, add the cookie and the names count.
558 	 */
559 	*p = cpu_to_be32(arg->count + 8 + 4);
560 }
561 
decode_listxattrs(struct xdr_stream * xdr,struct nfs42_listxattrsres * res)562 static int decode_listxattrs(struct xdr_stream *xdr,
563 			    struct nfs42_listxattrsres *res)
564 {
565 	int status;
566 	__be32 *p;
567 	u32 count, len, ulen;
568 	size_t left, copied;
569 	char *buf;
570 
571 	status = decode_op_hdr(xdr, OP_LISTXATTRS);
572 	if (status) {
573 		/*
574 		 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
575 		 * should be translated to ERANGE.
576 		 */
577 		if (status == -ETOOSMALL)
578 			status = -ERANGE;
579 		/*
580 		 * Special case: for LISTXATTRS, NFS4ERR_NOXATTR
581 		 * should be translated to success with zero-length reply.
582 		 */
583 		if (status == -ENODATA) {
584 			res->eof = true;
585 			status = 0;
586 		}
587 		goto out;
588 	}
589 
590 	p = xdr_inline_decode(xdr, 8);
591 	if (unlikely(!p))
592 		return -EIO;
593 
594 	xdr_decode_hyper(p, &res->cookie);
595 
596 	p = xdr_inline_decode(xdr, 4);
597 	if (unlikely(!p))
598 		return -EIO;
599 
600 	left = res->xattr_len;
601 	buf = res->xattr_buf;
602 
603 	count = be32_to_cpup(p);
604 	copied = 0;
605 
606 	/*
607 	 * We have asked for enough room to encode the maximum number
608 	 * of possible attribute names, so everything should fit.
609 	 *
610 	 * But, don't rely on that assumption. Just decode entries
611 	 * until they don't fit anymore, just in case the server did
612 	 * something odd.
613 	 */
614 	while (count--) {
615 		p = xdr_inline_decode(xdr, 4);
616 		if (unlikely(!p))
617 			return -EIO;
618 
619 		len = be32_to_cpup(p);
620 		if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
621 			status = -ERANGE;
622 			goto out;
623 		}
624 
625 		p = xdr_inline_decode(xdr, len);
626 		if (unlikely(!p))
627 			return -EIO;
628 
629 		ulen = len + XATTR_USER_PREFIX_LEN + 1;
630 		if (buf) {
631 			if (ulen > left) {
632 				status = -ERANGE;
633 				goto out;
634 			}
635 
636 			memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
637 			memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
638 
639 			buf[ulen - 1] = 0;
640 			buf += ulen;
641 			left -= ulen;
642 		}
643 		copied += ulen;
644 	}
645 
646 	p = xdr_inline_decode(xdr, 4);
647 	if (unlikely(!p))
648 		return -EIO;
649 
650 	res->eof = be32_to_cpup(p);
651 	res->copied = copied;
652 
653 out:
654 	if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
655 		status = -E2BIG;
656 
657 	return status;
658 }
659 
660 /*
661  * Encode ALLOCATE request
662  */
nfs4_xdr_enc_allocate(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)663 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
664 				  struct xdr_stream *xdr,
665 				  const void *data)
666 {
667 	const struct nfs42_falloc_args *args = data;
668 	struct compound_hdr hdr = {
669 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
670 	};
671 
672 	encode_compound_hdr(xdr, req, &hdr);
673 	encode_sequence(xdr, &args->seq_args, &hdr);
674 	encode_putfh(xdr, args->falloc_fh, &hdr);
675 	encode_allocate(xdr, args, &hdr);
676 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
677 	encode_nops(&hdr);
678 }
679 
encode_copy_commit(struct xdr_stream * xdr,const struct nfs42_copy_args * args,struct compound_hdr * hdr)680 static void encode_copy_commit(struct xdr_stream *xdr,
681 			  const struct nfs42_copy_args *args,
682 			  struct compound_hdr *hdr)
683 {
684 	__be32 *p;
685 
686 	encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
687 	p = reserve_space(xdr, 12);
688 	p = xdr_encode_hyper(p, args->dst_pos);
689 	*p = cpu_to_be32(args->count);
690 }
691 
692 /*
693  * Encode COPY request
694  */
nfs4_xdr_enc_copy(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)695 static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
696 			      struct xdr_stream *xdr,
697 			      const void *data)
698 {
699 	const struct nfs42_copy_args *args = data;
700 	struct compound_hdr hdr = {
701 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
702 	};
703 
704 	encode_compound_hdr(xdr, req, &hdr);
705 	encode_sequence(xdr, &args->seq_args, &hdr);
706 	encode_putfh(xdr, args->src_fh, &hdr);
707 	encode_savefh(xdr, &hdr);
708 	encode_putfh(xdr, args->dst_fh, &hdr);
709 	encode_copy(xdr, args, &hdr);
710 	if (args->sync)
711 		encode_copy_commit(xdr, args, &hdr);
712 	encode_nops(&hdr);
713 }
714 
715 /*
716  * Encode OFFLOAD_CANEL request
717  */
nfs4_xdr_enc_offload_cancel(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)718 static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
719 					struct xdr_stream *xdr,
720 					const void *data)
721 {
722 	const struct nfs42_offload_status_args *args = data;
723 	struct compound_hdr hdr = {
724 		.minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
725 	};
726 
727 	encode_compound_hdr(xdr, req, &hdr);
728 	encode_sequence(xdr, &args->osa_seq_args, &hdr);
729 	encode_putfh(xdr, args->osa_src_fh, &hdr);
730 	encode_offload_cancel(xdr, args, &hdr);
731 	encode_nops(&hdr);
732 }
733 
734 /*
735  * Encode COPY_NOTIFY request
736  */
nfs4_xdr_enc_copy_notify(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)737 static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
738 				     struct xdr_stream *xdr,
739 				     const void *data)
740 {
741 	const struct nfs42_copy_notify_args *args = data;
742 	struct compound_hdr hdr = {
743 		.minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
744 	};
745 
746 	encode_compound_hdr(xdr, req, &hdr);
747 	encode_sequence(xdr, &args->cna_seq_args, &hdr);
748 	encode_putfh(xdr, args->cna_src_fh, &hdr);
749 	encode_copy_notify(xdr, args, &hdr);
750 	encode_nops(&hdr);
751 }
752 
753 /*
754  * Encode DEALLOCATE request
755  */
nfs4_xdr_enc_deallocate(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)756 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
757 				    struct xdr_stream *xdr,
758 				    const void *data)
759 {
760 	const struct nfs42_falloc_args *args = data;
761 	struct compound_hdr hdr = {
762 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
763 	};
764 
765 	encode_compound_hdr(xdr, req, &hdr);
766 	encode_sequence(xdr, &args->seq_args, &hdr);
767 	encode_putfh(xdr, args->falloc_fh, &hdr);
768 	encode_deallocate(xdr, args, &hdr);
769 	encode_getfattr(xdr, args->falloc_bitmask, &hdr);
770 	encode_nops(&hdr);
771 }
772 
773 /*
774  * Encode READ_PLUS request
775  */
nfs4_xdr_enc_read_plus(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)776 static void nfs4_xdr_enc_read_plus(struct rpc_rqst *req,
777 				   struct xdr_stream *xdr,
778 				   const void *data)
779 {
780 	const struct nfs_pgio_args *args = data;
781 	struct compound_hdr hdr = {
782 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
783 	};
784 
785 	encode_compound_hdr(xdr, req, &hdr);
786 	encode_sequence(xdr, &args->seq_args, &hdr);
787 	encode_putfh(xdr, args->fh, &hdr);
788 	encode_read_plus(xdr, args, &hdr);
789 
790 	rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count,
791 				hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF);
792 	encode_nops(&hdr);
793 }
794 
795 /*
796  * Encode SEEK request
797  */
nfs4_xdr_enc_seek(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)798 static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
799 			      struct xdr_stream *xdr,
800 			      const void *data)
801 {
802 	const struct nfs42_seek_args *args = data;
803 	struct compound_hdr hdr = {
804 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
805 	};
806 
807 	encode_compound_hdr(xdr, req, &hdr);
808 	encode_sequence(xdr, &args->seq_args, &hdr);
809 	encode_putfh(xdr, args->sa_fh, &hdr);
810 	encode_seek(xdr, args, &hdr);
811 	encode_nops(&hdr);
812 }
813 
814 /*
815  * Encode LAYOUTSTATS request
816  */
nfs4_xdr_enc_layoutstats(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)817 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
818 				     struct xdr_stream *xdr,
819 				     const void *data)
820 {
821 	const struct nfs42_layoutstat_args *args = data;
822 	int i;
823 
824 	struct compound_hdr hdr = {
825 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
826 	};
827 
828 	encode_compound_hdr(xdr, req, &hdr);
829 	encode_sequence(xdr, &args->seq_args, &hdr);
830 	encode_putfh(xdr, args->fh, &hdr);
831 	WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
832 	for (i = 0; i < args->num_dev; i++)
833 		encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
834 	encode_nops(&hdr);
835 }
836 
837 /*
838  * Encode CLONE request
839  */
nfs4_xdr_enc_clone(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)840 static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
841 			       struct xdr_stream *xdr,
842 			       const void *data)
843 {
844 	const struct nfs42_clone_args *args = data;
845 	struct compound_hdr hdr = {
846 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
847 	};
848 
849 	encode_compound_hdr(xdr, req, &hdr);
850 	encode_sequence(xdr, &args->seq_args, &hdr);
851 	encode_putfh(xdr, args->src_fh, &hdr);
852 	encode_savefh(xdr, &hdr);
853 	encode_putfh(xdr, args->dst_fh, &hdr);
854 	encode_clone(xdr, args, &hdr);
855 	encode_getfattr(xdr, args->dst_bitmask, &hdr);
856 	encode_nops(&hdr);
857 }
858 
859 /*
860  * Encode LAYOUTERROR request
861  */
nfs4_xdr_enc_layouterror(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)862 static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
863 				     struct xdr_stream *xdr,
864 				     const void *data)
865 {
866 	const struct nfs42_layouterror_args *args = data;
867 	struct compound_hdr hdr = {
868 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
869 	};
870 	int i;
871 
872 	encode_compound_hdr(xdr, req, &hdr);
873 	encode_sequence(xdr, &args->seq_args, &hdr);
874 	encode_putfh(xdr, NFS_FH(args->inode), &hdr);
875 	for (i = 0; i < args->num_errors; i++)
876 		encode_layouterror(xdr, &args->errors[i], &hdr);
877 	encode_nops(&hdr);
878 }
879 
decode_allocate(struct xdr_stream * xdr,struct nfs42_falloc_res * res)880 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
881 {
882 	return decode_op_hdr(xdr, OP_ALLOCATE);
883 }
884 
decode_write_response(struct xdr_stream * xdr,struct nfs42_write_res * res)885 static int decode_write_response(struct xdr_stream *xdr,
886 				 struct nfs42_write_res *res)
887 {
888 	__be32 *p;
889 	int status, count;
890 
891 	p = xdr_inline_decode(xdr, 4);
892 	if (unlikely(!p))
893 		return -EIO;
894 	count = be32_to_cpup(p);
895 	if (count > 1)
896 		return -EREMOTEIO;
897 	else if (count == 1) {
898 		status = decode_opaque_fixed(xdr, &res->stateid,
899 				NFS4_STATEID_SIZE);
900 		if (unlikely(status))
901 			return -EIO;
902 	}
903 	p = xdr_inline_decode(xdr, 8 + 4);
904 	if (unlikely(!p))
905 		return -EIO;
906 	p = xdr_decode_hyper(p, &res->count);
907 	res->verifier.committed = be32_to_cpup(p);
908 	return decode_verifier(xdr, &res->verifier.verifier);
909 }
910 
decode_nl4_server(struct xdr_stream * xdr,struct nl4_server * ns)911 static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
912 {
913 	struct nfs42_netaddr *naddr;
914 	uint32_t dummy;
915 	char *dummy_str;
916 	__be32 *p;
917 	int status;
918 
919 	/* nl_type */
920 	p = xdr_inline_decode(xdr, 4);
921 	if (unlikely(!p))
922 		return -EIO;
923 	ns->nl4_type = be32_to_cpup(p);
924 	switch (ns->nl4_type) {
925 	case NL4_NAME:
926 	case NL4_URL:
927 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
928 		if (unlikely(status))
929 			return status;
930 		if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
931 			return -EIO;
932 		memcpy(&ns->u.nl4_str, dummy_str, dummy);
933 		ns->u.nl4_str_sz = dummy;
934 		break;
935 	case NL4_NETADDR:
936 		naddr = &ns->u.nl4_addr;
937 
938 		/* netid string */
939 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
940 		if (unlikely(status))
941 			return status;
942 		if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
943 			return -EIO;
944 		naddr->netid_len = dummy;
945 		memcpy(naddr->netid, dummy_str, naddr->netid_len);
946 
947 		/* uaddr string */
948 		status = decode_opaque_inline(xdr, &dummy, &dummy_str);
949 		if (unlikely(status))
950 			return status;
951 		if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
952 			return -EIO;
953 		naddr->addr_len = dummy;
954 		memcpy(naddr->addr, dummy_str, naddr->addr_len);
955 		break;
956 	default:
957 		WARN_ON_ONCE(1);
958 		return -EIO;
959 	}
960 	return 0;
961 }
962 
decode_copy_requirements(struct xdr_stream * xdr,struct nfs42_copy_res * res)963 static int decode_copy_requirements(struct xdr_stream *xdr,
964 				    struct nfs42_copy_res *res) {
965 	__be32 *p;
966 
967 	p = xdr_inline_decode(xdr, 4 + 4);
968 	if (unlikely(!p))
969 		return -EIO;
970 
971 	res->consecutive = be32_to_cpup(p++);
972 	res->synchronous = be32_to_cpup(p++);
973 	return 0;
974 }
975 
decode_copy(struct xdr_stream * xdr,struct nfs42_copy_res * res)976 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
977 {
978 	int status;
979 
980 	status = decode_op_hdr(xdr, OP_COPY);
981 	if (status == NFS4ERR_OFFLOAD_NO_REQS) {
982 		status = decode_copy_requirements(xdr, res);
983 		if (status)
984 			return status;
985 		return NFS4ERR_OFFLOAD_NO_REQS;
986 	} else if (status)
987 		return status;
988 
989 	status = decode_write_response(xdr, &res->write_res);
990 	if (status)
991 		return status;
992 
993 	return decode_copy_requirements(xdr, res);
994 }
995 
decode_offload_cancel(struct xdr_stream * xdr,struct nfs42_offload_status_res * res)996 static int decode_offload_cancel(struct xdr_stream *xdr,
997 				 struct nfs42_offload_status_res *res)
998 {
999 	return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
1000 }
1001 
decode_copy_notify(struct xdr_stream * xdr,struct nfs42_copy_notify_res * res)1002 static int decode_copy_notify(struct xdr_stream *xdr,
1003 			      struct nfs42_copy_notify_res *res)
1004 {
1005 	__be32 *p;
1006 	int status, count;
1007 
1008 	status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
1009 	if (status)
1010 		return status;
1011 	/* cnr_lease_time */
1012 	p = xdr_inline_decode(xdr, 12);
1013 	if (unlikely(!p))
1014 		return -EIO;
1015 	p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
1016 	res->cnr_lease_time.nseconds = be32_to_cpup(p);
1017 
1018 	status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
1019 	if (unlikely(status))
1020 		return -EIO;
1021 
1022 	/* number of source addresses */
1023 	p = xdr_inline_decode(xdr, 4);
1024 	if (unlikely(!p))
1025 		return -EIO;
1026 
1027 	count = be32_to_cpup(p);
1028 	if (count > 1)
1029 		pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
1030 			 __func__, count);
1031 
1032 	status = decode_nl4_server(xdr, &res->cnr_src);
1033 	if (unlikely(status))
1034 		return -EIO;
1035 	return 0;
1036 }
1037 
decode_deallocate(struct xdr_stream * xdr,struct nfs42_falloc_res * res)1038 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
1039 {
1040 	return decode_op_hdr(xdr, OP_DEALLOCATE);
1041 }
1042 
1043 struct read_plus_segment {
1044 	enum data_content4 type;
1045 	uint64_t offset;
1046 	union {
1047 		struct {
1048 			uint64_t length;
1049 		} hole;
1050 
1051 		struct {
1052 			uint32_t length;
1053 			unsigned int from;
1054 		} data;
1055 	};
1056 };
1057 
read_plus_segment_length(struct read_plus_segment * seg)1058 static inline uint64_t read_plus_segment_length(struct read_plus_segment *seg)
1059 {
1060 	return seg->type == NFS4_CONTENT_DATA ? seg->data.length : seg->hole.length;
1061 }
1062 
decode_read_plus_segment(struct xdr_stream * xdr,struct read_plus_segment * seg)1063 static int decode_read_plus_segment(struct xdr_stream *xdr,
1064 				    struct read_plus_segment *seg)
1065 {
1066 	__be32 *p;
1067 
1068 	p = xdr_inline_decode(xdr, 4);
1069 	if (!p)
1070 		return -EIO;
1071 	seg->type = be32_to_cpup(p++);
1072 
1073 	p = xdr_inline_decode(xdr, seg->type == NFS4_CONTENT_DATA ? 12 : 16);
1074 	if (!p)
1075 		return -EIO;
1076 	p = xdr_decode_hyper(p, &seg->offset);
1077 
1078 	if (seg->type == NFS4_CONTENT_DATA) {
1079 		struct xdr_buf buf;
1080 		uint32_t len = be32_to_cpup(p);
1081 
1082 		seg->data.length = len;
1083 		seg->data.from = xdr_stream_pos(xdr);
1084 
1085 		if (!xdr_stream_subsegment(xdr, &buf, xdr_align_size(len)))
1086 			return -EIO;
1087 	} else if (seg->type == NFS4_CONTENT_HOLE) {
1088 		xdr_decode_hyper(p, &seg->hole.length);
1089 	} else
1090 		return -EINVAL;
1091 	return 0;
1092 }
1093 
process_read_plus_segment(struct xdr_stream * xdr,struct nfs_pgio_args * args,struct nfs_pgio_res * res,struct read_plus_segment * seg)1094 static int process_read_plus_segment(struct xdr_stream *xdr,
1095 				     struct nfs_pgio_args *args,
1096 				     struct nfs_pgio_res *res,
1097 				     struct read_plus_segment *seg)
1098 {
1099 	unsigned long offset = seg->offset;
1100 	unsigned long length = read_plus_segment_length(seg);
1101 	unsigned int bufpos;
1102 
1103 	if (offset + length < args->offset)
1104 		return 0;
1105 	else if (offset > args->offset + args->count) {
1106 		res->eof = 0;
1107 		return 0;
1108 	} else if (offset < args->offset) {
1109 		length -= (args->offset - offset);
1110 		offset = args->offset;
1111 	} else if (offset + length > args->offset + args->count) {
1112 		length = (args->offset + args->count) - offset;
1113 		res->eof = 0;
1114 	}
1115 
1116 	bufpos = xdr->buf->head[0].iov_len + (offset - args->offset);
1117 	if (seg->type == NFS4_CONTENT_HOLE)
1118 		return xdr_stream_zero(xdr, bufpos, length);
1119 	else
1120 		return xdr_stream_move_subsegment(xdr, seg->data.from, bufpos, length);
1121 }
1122 
decode_read_plus(struct xdr_stream * xdr,struct nfs_pgio_res * res)1123 static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res)
1124 {
1125 	struct nfs_pgio_header *hdr =
1126 		container_of(res, struct nfs_pgio_header, res);
1127 	struct nfs_pgio_args *args = &hdr->args;
1128 	uint32_t segments;
1129 	struct read_plus_segment *segs;
1130 	int status, i;
1131 	__be32 *p;
1132 
1133 	status = decode_op_hdr(xdr, OP_READ_PLUS);
1134 	if (status)
1135 		return status;
1136 
1137 	p = xdr_inline_decode(xdr, 4 + 4);
1138 	if (unlikely(!p))
1139 		return -EIO;
1140 
1141 	res->count = 0;
1142 	res->eof = be32_to_cpup(p++);
1143 	segments = be32_to_cpup(p++);
1144 	if (segments == 0)
1145 		return 0;
1146 
1147 	segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL);
1148 	if (!segs)
1149 		return -ENOMEM;
1150 
1151 	for (i = 0; i < segments; i++) {
1152 		status = decode_read_plus_segment(xdr, &segs[i]);
1153 		if (status < 0)
1154 			goto out;
1155 	}
1156 
1157 	xdr_set_pagelen(xdr, xdr_align_size(args->count));
1158 	for (i = segments; i > 0; i--)
1159 		res->count += process_read_plus_segment(xdr, args, res, &segs[i-1]);
1160 	status = 0;
1161 
1162 out:
1163 	kfree(segs);
1164 	return status;
1165 }
1166 
decode_seek(struct xdr_stream * xdr,struct nfs42_seek_res * res)1167 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
1168 {
1169 	int status;
1170 	__be32 *p;
1171 
1172 	status = decode_op_hdr(xdr, OP_SEEK);
1173 	if (status)
1174 		return status;
1175 
1176 	p = xdr_inline_decode(xdr, 4 + 8);
1177 	if (unlikely(!p))
1178 		return -EIO;
1179 
1180 	res->sr_eof = be32_to_cpup(p++);
1181 	p = xdr_decode_hyper(p, &res->sr_offset);
1182 	return 0;
1183 }
1184 
decode_layoutstats(struct xdr_stream * xdr)1185 static int decode_layoutstats(struct xdr_stream *xdr)
1186 {
1187 	return decode_op_hdr(xdr, OP_LAYOUTSTATS);
1188 }
1189 
decode_clone(struct xdr_stream * xdr)1190 static int decode_clone(struct xdr_stream *xdr)
1191 {
1192 	return decode_op_hdr(xdr, OP_CLONE);
1193 }
1194 
decode_layouterror(struct xdr_stream * xdr)1195 static int decode_layouterror(struct xdr_stream *xdr)
1196 {
1197 	return decode_op_hdr(xdr, OP_LAYOUTERROR);
1198 }
1199 
1200 /*
1201  * Decode ALLOCATE request
1202  */
nfs4_xdr_dec_allocate(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1203 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
1204 				 struct xdr_stream *xdr,
1205 				 void *data)
1206 {
1207 	struct nfs42_falloc_res *res = data;
1208 	struct compound_hdr hdr;
1209 	int status;
1210 
1211 	status = decode_compound_hdr(xdr, &hdr);
1212 	if (status)
1213 		goto out;
1214 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1215 	if (status)
1216 		goto out;
1217 	status = decode_putfh(xdr);
1218 	if (status)
1219 		goto out;
1220 	status = decode_allocate(xdr, res);
1221 	if (status)
1222 		goto out;
1223 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1224 out:
1225 	return status;
1226 }
1227 
1228 /*
1229  * Decode COPY response
1230  */
nfs4_xdr_dec_copy(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1231 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
1232 			     struct xdr_stream *xdr,
1233 			     void *data)
1234 {
1235 	struct nfs42_copy_res *res = data;
1236 	struct compound_hdr hdr;
1237 	int status;
1238 
1239 	status = decode_compound_hdr(xdr, &hdr);
1240 	if (status)
1241 		goto out;
1242 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1243 	if (status)
1244 		goto out;
1245 	status = decode_putfh(xdr);
1246 	if (status)
1247 		goto out;
1248 	status = decode_savefh(xdr);
1249 	if (status)
1250 		goto out;
1251 	status = decode_putfh(xdr);
1252 	if (status)
1253 		goto out;
1254 	status = decode_copy(xdr, res);
1255 	if (status)
1256 		goto out;
1257 	if (res->commit_res.verf)
1258 		status = decode_commit(xdr, &res->commit_res);
1259 out:
1260 	return status;
1261 }
1262 
1263 /*
1264  * Decode OFFLOAD_CANCEL response
1265  */
nfs4_xdr_dec_offload_cancel(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1266 static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
1267 				       struct xdr_stream *xdr,
1268 				       void *data)
1269 {
1270 	struct nfs42_offload_status_res *res = data;
1271 	struct compound_hdr hdr;
1272 	int status;
1273 
1274 	status = decode_compound_hdr(xdr, &hdr);
1275 	if (status)
1276 		goto out;
1277 	status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1278 	if (status)
1279 		goto out;
1280 	status = decode_putfh(xdr);
1281 	if (status)
1282 		goto out;
1283 	status = decode_offload_cancel(xdr, res);
1284 
1285 out:
1286 	return status;
1287 }
1288 
1289 /*
1290  * Decode COPY_NOTIFY response
1291  */
nfs4_xdr_dec_copy_notify(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1292 static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1293 				    struct xdr_stream *xdr,
1294 				    void *data)
1295 {
1296 	struct nfs42_copy_notify_res *res = data;
1297 	struct compound_hdr hdr;
1298 	int status;
1299 
1300 	status = decode_compound_hdr(xdr, &hdr);
1301 	if (status)
1302 		goto out;
1303 	status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1304 	if (status)
1305 		goto out;
1306 	status = decode_putfh(xdr);
1307 	if (status)
1308 		goto out;
1309 	status = decode_copy_notify(xdr, res);
1310 
1311 out:
1312 	return status;
1313 }
1314 
1315 /*
1316  * Decode DEALLOCATE request
1317  */
nfs4_xdr_dec_deallocate(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1318 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
1319 				   struct xdr_stream *xdr,
1320 				   void *data)
1321 {
1322 	struct nfs42_falloc_res *res = data;
1323 	struct compound_hdr hdr;
1324 	int status;
1325 
1326 	status = decode_compound_hdr(xdr, &hdr);
1327 	if (status)
1328 		goto out;
1329 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1330 	if (status)
1331 		goto out;
1332 	status = decode_putfh(xdr);
1333 	if (status)
1334 		goto out;
1335 	status = decode_deallocate(xdr, res);
1336 	if (status)
1337 		goto out;
1338 	decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1339 out:
1340 	return status;
1341 }
1342 
1343 /*
1344  * Decode READ_PLUS request
1345  */
nfs4_xdr_dec_read_plus(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1346 static int nfs4_xdr_dec_read_plus(struct rpc_rqst *rqstp,
1347 				  struct xdr_stream *xdr,
1348 				  void *data)
1349 {
1350 	struct nfs_pgio_res *res = data;
1351 	struct compound_hdr hdr;
1352 	int status;
1353 
1354 	xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE);
1355 
1356 	status = decode_compound_hdr(xdr, &hdr);
1357 	if (status)
1358 		goto out;
1359 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1360 	if (status)
1361 		goto out;
1362 	status = decode_putfh(xdr);
1363 	if (status)
1364 		goto out;
1365 	status = decode_read_plus(xdr, res);
1366 	if (!status)
1367 		status = res->count;
1368 out:
1369 	return status;
1370 }
1371 
1372 /*
1373  * Decode SEEK request
1374  */
nfs4_xdr_dec_seek(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1375 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
1376 			     struct xdr_stream *xdr,
1377 			     void *data)
1378 {
1379 	struct nfs42_seek_res *res = data;
1380 	struct compound_hdr hdr;
1381 	int status;
1382 
1383 	status = decode_compound_hdr(xdr, &hdr);
1384 	if (status)
1385 		goto out;
1386 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1387 	if (status)
1388 		goto out;
1389 	status = decode_putfh(xdr);
1390 	if (status)
1391 		goto out;
1392 	status = decode_seek(xdr, res);
1393 out:
1394 	return status;
1395 }
1396 
1397 /*
1398  * Decode LAYOUTSTATS request
1399  */
nfs4_xdr_dec_layoutstats(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1400 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
1401 				    struct xdr_stream *xdr,
1402 				    void *data)
1403 {
1404 	struct nfs42_layoutstat_res *res = data;
1405 	struct compound_hdr hdr;
1406 	int status, i;
1407 
1408 	status = decode_compound_hdr(xdr, &hdr);
1409 	if (status)
1410 		goto out;
1411 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1412 	if (status)
1413 		goto out;
1414 	status = decode_putfh(xdr);
1415 	if (status)
1416 		goto out;
1417 	WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
1418 	for (i = 0; i < res->num_dev; i++) {
1419 		status = decode_layoutstats(xdr);
1420 		if (status)
1421 			goto out;
1422 	}
1423 out:
1424 	res->rpc_status = status;
1425 	return status;
1426 }
1427 
1428 /*
1429  * Decode CLONE request
1430  */
nfs4_xdr_dec_clone(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1431 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
1432 			      struct xdr_stream *xdr,
1433 			      void *data)
1434 {
1435 	struct nfs42_clone_res *res = data;
1436 	struct compound_hdr hdr;
1437 	int status;
1438 
1439 	status = decode_compound_hdr(xdr, &hdr);
1440 	if (status)
1441 		goto out;
1442 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1443 	if (status)
1444 		goto out;
1445 	status = decode_putfh(xdr);
1446 	if (status)
1447 		goto out;
1448 	status = decode_savefh(xdr);
1449 	if (status)
1450 		goto out;
1451 	status = decode_putfh(xdr);
1452 	if (status)
1453 		goto out;
1454 	status = decode_clone(xdr);
1455 	if (status)
1456 		goto out;
1457 	decode_getfattr(xdr, res->dst_fattr, res->server);
1458 out:
1459 	res->rpc_status = status;
1460 	return status;
1461 }
1462 
1463 /*
1464  * Decode LAYOUTERROR request
1465  */
nfs4_xdr_dec_layouterror(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1466 static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1467 				    struct xdr_stream *xdr,
1468 				    void *data)
1469 {
1470 	struct nfs42_layouterror_res *res = data;
1471 	struct compound_hdr hdr;
1472 	int status, i;
1473 
1474 	status = decode_compound_hdr(xdr, &hdr);
1475 	if (status)
1476 		goto out;
1477 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1478 	if (status)
1479 		goto out;
1480 	status = decode_putfh(xdr);
1481 
1482 	for (i = 0; i < res->num_errors && status == 0; i++)
1483 		status = decode_layouterror(xdr);
1484 out:
1485 	res->rpc_status = status;
1486 	return status;
1487 }
1488 
1489 #ifdef CONFIG_NFS_V4_2
nfs4_xdr_enc_setxattr(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)1490 static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1491 				  const void *data)
1492 {
1493 	const struct nfs42_setxattrargs *args = data;
1494 	struct compound_hdr hdr = {
1495 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1496 	};
1497 
1498 	encode_compound_hdr(xdr, req, &hdr);
1499 	encode_sequence(xdr, &args->seq_args, &hdr);
1500 	encode_putfh(xdr, args->fh, &hdr);
1501 	encode_setxattr(xdr, args, &hdr);
1502 	encode_nops(&hdr);
1503 }
1504 
nfs4_xdr_dec_setxattr(struct rpc_rqst * req,struct xdr_stream * xdr,void * data)1505 static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1506 				 void *data)
1507 {
1508 	struct nfs42_setxattrres *res = data;
1509 	struct compound_hdr hdr;
1510 	int status;
1511 
1512 	status = decode_compound_hdr(xdr, &hdr);
1513 	if (status)
1514 		goto out;
1515 	status = decode_sequence(xdr, &res->seq_res, req);
1516 	if (status)
1517 		goto out;
1518 	status = decode_putfh(xdr);
1519 	if (status)
1520 		goto out;
1521 
1522 	status = decode_setxattr(xdr, &res->cinfo);
1523 out:
1524 	return status;
1525 }
1526 
nfs4_xdr_enc_getxattr(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)1527 static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1528 				  const void *data)
1529 {
1530 	const struct nfs42_getxattrargs *args = data;
1531 	struct compound_hdr hdr = {
1532 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1533 	};
1534 	uint32_t replen;
1535 
1536 	encode_compound_hdr(xdr, req, &hdr);
1537 	encode_sequence(xdr, &args->seq_args, &hdr);
1538 	encode_putfh(xdr, args->fh, &hdr);
1539 	replen = hdr.replen + op_decode_hdr_maxsz + 1;
1540 	encode_getxattr(xdr, args->xattr_name, &hdr);
1541 
1542 	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->xattr_len,
1543 				replen);
1544 
1545 	encode_nops(&hdr);
1546 }
1547 
nfs4_xdr_dec_getxattr(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1548 static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1549 				 struct xdr_stream *xdr, void *data)
1550 {
1551 	struct nfs42_getxattrres *res = data;
1552 	struct compound_hdr hdr;
1553 	int status;
1554 
1555 	status = decode_compound_hdr(xdr, &hdr);
1556 	if (status)
1557 		goto out;
1558 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1559 	if (status)
1560 		goto out;
1561 	status = decode_putfh(xdr);
1562 	if (status)
1563 		goto out;
1564 	status = decode_getxattr(xdr, res, rqstp);
1565 out:
1566 	return status;
1567 }
1568 
nfs4_xdr_enc_listxattrs(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)1569 static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1570 				    struct xdr_stream *xdr, const void *data)
1571 {
1572 	const struct nfs42_listxattrsargs *args = data;
1573 	struct compound_hdr hdr = {
1574 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1575 	};
1576 	uint32_t replen;
1577 
1578 	encode_compound_hdr(xdr, req, &hdr);
1579 	encode_sequence(xdr, &args->seq_args, &hdr);
1580 	encode_putfh(xdr, args->fh, &hdr);
1581 	replen = hdr.replen + op_decode_hdr_maxsz + 2 + 1;
1582 	encode_listxattrs(xdr, args, &hdr);
1583 
1584 	rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count, replen);
1585 
1586 	encode_nops(&hdr);
1587 }
1588 
nfs4_xdr_dec_listxattrs(struct rpc_rqst * rqstp,struct xdr_stream * xdr,void * data)1589 static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1590 				   struct xdr_stream *xdr, void *data)
1591 {
1592 	struct nfs42_listxattrsres *res = data;
1593 	struct compound_hdr hdr;
1594 	int status;
1595 
1596 	xdr_set_scratch_page(xdr, res->scratch);
1597 
1598 	status = decode_compound_hdr(xdr, &hdr);
1599 	if (status)
1600 		goto out;
1601 	status = decode_sequence(xdr, &res->seq_res, rqstp);
1602 	if (status)
1603 		goto out;
1604 	status = decode_putfh(xdr);
1605 	if (status)
1606 		goto out;
1607 	status = decode_listxattrs(xdr, res);
1608 out:
1609 	return status;
1610 }
1611 
nfs4_xdr_enc_removexattr(struct rpc_rqst * req,struct xdr_stream * xdr,const void * data)1612 static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1613 				     struct xdr_stream *xdr, const void *data)
1614 {
1615 	const struct nfs42_removexattrargs *args = data;
1616 	struct compound_hdr hdr = {
1617 		.minorversion = nfs4_xdr_minorversion(&args->seq_args),
1618 	};
1619 
1620 	encode_compound_hdr(xdr, req, &hdr);
1621 	encode_sequence(xdr, &args->seq_args, &hdr);
1622 	encode_putfh(xdr, args->fh, &hdr);
1623 	encode_removexattr(xdr, args->xattr_name, &hdr);
1624 	encode_nops(&hdr);
1625 }
1626 
nfs4_xdr_dec_removexattr(struct rpc_rqst * req,struct xdr_stream * xdr,void * data)1627 static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1628 				    struct xdr_stream *xdr, void *data)
1629 {
1630 	struct nfs42_removexattrres *res = data;
1631 	struct compound_hdr hdr;
1632 	int status;
1633 
1634 	status = decode_compound_hdr(xdr, &hdr);
1635 	if (status)
1636 		goto out;
1637 	status = decode_sequence(xdr, &res->seq_res, req);
1638 	if (status)
1639 		goto out;
1640 	status = decode_putfh(xdr);
1641 	if (status)
1642 		goto out;
1643 
1644 	status = decode_removexattr(xdr, &res->cinfo);
1645 out:
1646 	return status;
1647 }
1648 #endif
1649 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
1650