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