Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1c6dcbe5 AS |
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 | ||
be3a5d23 TM |
8 | #include "nfs42.h" |
9 | ||
f4ac1674 AS |
10 | #define encode_fallocate_maxsz (encode_stateid_maxsz + \ |
11 | 2 /* offset */ + \ | |
12 | 2 /* length */) | |
2e72448b AS |
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)) | |
f4ac1674 AS |
18 | #define encode_allocate_maxsz (op_encode_hdr_maxsz + \ |
19 | encode_fallocate_maxsz) | |
20 | #define decode_allocate_maxsz (op_decode_hdr_maxsz) | |
2e72448b AS |
21 | #define encode_copy_maxsz (op_encode_hdr_maxsz + \ |
22 | XDR_QUADLEN(NFS4_STATEID_SIZE) + \ | |
23 | XDR_QUADLEN(NFS4_STATEID_SIZE) + \ | |
1d38f3f0 OK |
24 | 2 + 2 + 2 + 1 + 1 + 1 +\ |
25 | 1 + /* One cnr_source_server */\ | |
26 | 1 + /* nl4_type */ \ | |
27 | 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) | |
2e72448b AS |
28 | #define decode_copy_maxsz (op_decode_hdr_maxsz + \ |
29 | NFS42_WRITE_RES_SIZE + \ | |
30 | 1 /* cr_consecutive */ + \ | |
31 | 1 /* cr_synchronous */) | |
cb95deea OK |
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) | |
0491567b OK |
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)) | |
624bd5b7 AS |
45 | #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ |
46 | encode_fallocate_maxsz) | |
47 | #define decode_deallocate_maxsz (op_decode_hdr_maxsz) | |
1c6dcbe5 AS |
48 | #define encode_seek_maxsz (op_encode_hdr_maxsz + \ |
49 | encode_stateid_maxsz + \ | |
50 | 2 /* offset */ + \ | |
51 | 1 /* whence */) | |
52 | #define decode_seek_maxsz (op_decode_hdr_maxsz + \ | |
53 | 1 /* eof */ + \ | |
54 | 1 /* whence */ + \ | |
55 | 2 /* offset */ + \ | |
56 | 2 /* length */) | |
be3a5d23 TM |
57 | #define encode_io_info_maxsz 4 |
58 | #define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \ | |
59 | 2 /* offset */ + \ | |
60 | 2 /* length */ + \ | |
61 | encode_stateid_maxsz + \ | |
62 | encode_io_info_maxsz + \ | |
63 | encode_io_info_maxsz + \ | |
64 | 1 /* opaque devaddr4 length */ + \ | |
65 | XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE)) | |
66 | #define decode_layoutstats_maxsz (op_decode_hdr_maxsz) | |
3eb86093 TM |
67 | #define encode_device_error_maxsz (XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \ |
68 | 1 /* status */ + 1 /* opnum */) | |
69 | #define encode_layouterror_maxsz (op_decode_hdr_maxsz + \ | |
70 | 2 /* offset */ + \ | |
71 | 2 /* length */ + \ | |
72 | encode_stateid_maxsz + \ | |
73 | 1 /* Array size */ + \ | |
74 | encode_device_error_maxsz) | |
75 | #define decode_layouterror_maxsz (op_decode_hdr_maxsz) | |
36022770 PT |
76 | #define encode_clone_maxsz (encode_stateid_maxsz + \ |
77 | encode_stateid_maxsz + \ | |
78 | 2 /* src offset */ + \ | |
79 | 2 /* dst offset */ + \ | |
80 | 2 /* count */) | |
81 | #define decode_clone_maxsz (op_decode_hdr_maxsz) | |
1c6dcbe5 | 82 | |
f4ac1674 | 83 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 84 | encode_sequence_maxsz + \ |
f4ac1674 | 85 | encode_putfh_maxsz + \ |
9a51940b AS |
86 | encode_allocate_maxsz + \ |
87 | encode_getattr_maxsz) | |
f4ac1674 | 88 | #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 89 | decode_sequence_maxsz + \ |
f4ac1674 | 90 | decode_putfh_maxsz + \ |
9a51940b AS |
91 | decode_allocate_maxsz + \ |
92 | decode_getattr_maxsz) | |
2e72448b | 93 | #define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 94 | encode_sequence_maxsz + \ |
2e72448b AS |
95 | encode_putfh_maxsz + \ |
96 | encode_savefh_maxsz + \ | |
97 | encode_putfh_maxsz + \ | |
e0926934 OK |
98 | encode_copy_maxsz + \ |
99 | encode_commit_maxsz) | |
2e72448b | 100 | #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 101 | decode_sequence_maxsz + \ |
2e72448b AS |
102 | decode_putfh_maxsz + \ |
103 | decode_savefh_maxsz + \ | |
104 | decode_putfh_maxsz + \ | |
e0926934 OK |
105 | decode_copy_maxsz + \ |
106 | decode_commit_maxsz) | |
cb95deea | 107 | #define NFS4_enc_offload_cancel_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 108 | encode_sequence_maxsz + \ |
cb95deea OK |
109 | encode_putfh_maxsz + \ |
110 | encode_offload_cancel_maxsz) | |
111 | #define NFS4_dec_offload_cancel_sz (compound_decode_hdr_maxsz + \ | |
1a3466ae | 112 | decode_sequence_maxsz + \ |
cb95deea OK |
113 | decode_putfh_maxsz + \ |
114 | decode_offload_cancel_maxsz) | |
0491567b OK |
115 | #define NFS4_enc_copy_notify_sz (compound_encode_hdr_maxsz + \ |
116 | encode_putfh_maxsz + \ | |
117 | encode_copy_notify_maxsz) | |
118 | #define NFS4_dec_copy_notify_sz (compound_decode_hdr_maxsz + \ | |
119 | decode_putfh_maxsz + \ | |
120 | decode_copy_notify_maxsz) | |
624bd5b7 | 121 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 122 | encode_sequence_maxsz + \ |
624bd5b7 | 123 | encode_putfh_maxsz + \ |
9a51940b AS |
124 | encode_deallocate_maxsz + \ |
125 | encode_getattr_maxsz) | |
624bd5b7 | 126 | #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 127 | decode_sequence_maxsz + \ |
624bd5b7 | 128 | decode_putfh_maxsz + \ |
9a51940b AS |
129 | decode_deallocate_maxsz + \ |
130 | decode_getattr_maxsz) | |
1c6dcbe5 | 131 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 132 | encode_sequence_maxsz + \ |
1c6dcbe5 AS |
133 | encode_putfh_maxsz + \ |
134 | encode_seek_maxsz) | |
135 | #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ | |
1a3466ae | 136 | decode_sequence_maxsz + \ |
1c6dcbe5 AS |
137 | decode_putfh_maxsz + \ |
138 | decode_seek_maxsz) | |
be3a5d23 TM |
139 | #define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \ |
140 | encode_sequence_maxsz + \ | |
141 | encode_putfh_maxsz + \ | |
142 | PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz) | |
143 | #define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \ | |
144 | decode_sequence_maxsz + \ | |
145 | decode_putfh_maxsz + \ | |
146 | PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz) | |
3eb86093 TM |
147 | #define NFS4_enc_layouterror_sz (compound_encode_hdr_maxsz + \ |
148 | encode_sequence_maxsz + \ | |
149 | encode_putfh_maxsz + \ | |
150 | NFS42_LAYOUTERROR_MAX * \ | |
151 | encode_layouterror_maxsz) | |
152 | #define NFS4_dec_layouterror_sz (compound_decode_hdr_maxsz + \ | |
153 | decode_sequence_maxsz + \ | |
154 | decode_putfh_maxsz + \ | |
155 | NFS42_LAYOUTERROR_MAX * \ | |
156 | decode_layouterror_maxsz) | |
36022770 PT |
157 | #define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \ |
158 | encode_sequence_maxsz + \ | |
159 | encode_putfh_maxsz + \ | |
160 | encode_savefh_maxsz + \ | |
161 | encode_putfh_maxsz + \ | |
162 | encode_clone_maxsz + \ | |
163 | encode_getattr_maxsz) | |
164 | #define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \ | |
165 | decode_sequence_maxsz + \ | |
166 | decode_putfh_maxsz + \ | |
167 | decode_savefh_maxsz + \ | |
168 | decode_putfh_maxsz + \ | |
169 | decode_clone_maxsz + \ | |
170 | decode_getattr_maxsz) | |
1c6dcbe5 | 171 | |
f4ac1674 | 172 | static void encode_fallocate(struct xdr_stream *xdr, |
0096d39b | 173 | const struct nfs42_falloc_args *args) |
f4ac1674 AS |
174 | { |
175 | encode_nfs4_stateid(xdr, &args->falloc_stateid); | |
176 | encode_uint64(xdr, args->falloc_offset); | |
177 | encode_uint64(xdr, args->falloc_length); | |
178 | } | |
179 | ||
180 | static void encode_allocate(struct xdr_stream *xdr, | |
0096d39b | 181 | const struct nfs42_falloc_args *args, |
f4ac1674 AS |
182 | struct compound_hdr *hdr) |
183 | { | |
184 | encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); | |
185 | encode_fallocate(xdr, args); | |
186 | } | |
187 | ||
0491567b OK |
188 | static void encode_nl4_server(struct xdr_stream *xdr, |
189 | const struct nl4_server *ns) | |
190 | { | |
191 | encode_uint32(xdr, ns->nl4_type); | |
192 | switch (ns->nl4_type) { | |
193 | case NL4_NAME: | |
194 | case NL4_URL: | |
195 | encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str); | |
196 | break; | |
197 | case NL4_NETADDR: | |
198 | encode_string(xdr, ns->u.nl4_addr.netid_len, | |
199 | ns->u.nl4_addr.netid); | |
200 | encode_string(xdr, ns->u.nl4_addr.addr_len, | |
201 | ns->u.nl4_addr.addr); | |
202 | break; | |
203 | default: | |
204 | WARN_ON_ONCE(1); | |
205 | } | |
206 | } | |
207 | ||
2e72448b | 208 | static void encode_copy(struct xdr_stream *xdr, |
0096d39b | 209 | const struct nfs42_copy_args *args, |
2e72448b AS |
210 | struct compound_hdr *hdr) |
211 | { | |
212 | encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr); | |
213 | encode_nfs4_stateid(xdr, &args->src_stateid); | |
214 | encode_nfs4_stateid(xdr, &args->dst_stateid); | |
215 | ||
216 | encode_uint64(xdr, args->src_pos); | |
217 | encode_uint64(xdr, args->dst_pos); | |
218 | encode_uint64(xdr, args->count); | |
219 | ||
220 | encode_uint32(xdr, 1); /* consecutive = true */ | |
62164f31 | 221 | encode_uint32(xdr, args->sync); |
1d38f3f0 OK |
222 | if (args->cp_src == NULL) { /* intra-ssc */ |
223 | encode_uint32(xdr, 0); /* no src server list */ | |
224 | return; | |
225 | } | |
226 | encode_uint32(xdr, 1); /* supporting 1 server */ | |
227 | encode_nl4_server(xdr, args->cp_src); | |
2e72448b AS |
228 | } |
229 | ||
cb95deea OK |
230 | static void encode_offload_cancel(struct xdr_stream *xdr, |
231 | const struct nfs42_offload_status_args *args, | |
232 | struct compound_hdr *hdr) | |
233 | { | |
234 | encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr); | |
235 | encode_nfs4_stateid(xdr, &args->osa_stateid); | |
236 | } | |
237 | ||
0491567b OK |
238 | static void encode_copy_notify(struct xdr_stream *xdr, |
239 | const struct nfs42_copy_notify_args *args, | |
240 | struct compound_hdr *hdr) | |
241 | { | |
242 | encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr); | |
243 | encode_nfs4_stateid(xdr, &args->cna_src_stateid); | |
244 | encode_nl4_server(xdr, &args->cna_dst); | |
245 | } | |
246 | ||
624bd5b7 | 247 | static void encode_deallocate(struct xdr_stream *xdr, |
0096d39b | 248 | const struct nfs42_falloc_args *args, |
624bd5b7 AS |
249 | struct compound_hdr *hdr) |
250 | { | |
251 | encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); | |
252 | encode_fallocate(xdr, args); | |
253 | } | |
254 | ||
1c6dcbe5 | 255 | static void encode_seek(struct xdr_stream *xdr, |
0096d39b | 256 | const struct nfs42_seek_args *args, |
1c6dcbe5 AS |
257 | struct compound_hdr *hdr) |
258 | { | |
259 | encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr); | |
260 | encode_nfs4_stateid(xdr, &args->sa_stateid); | |
261 | encode_uint64(xdr, args->sa_offset); | |
262 | encode_uint32(xdr, args->sa_what); | |
263 | } | |
264 | ||
be3a5d23 | 265 | static void encode_layoutstats(struct xdr_stream *xdr, |
0096d39b | 266 | const struct nfs42_layoutstat_args *args, |
be3a5d23 TM |
267 | struct nfs42_layoutstat_devinfo *devinfo, |
268 | struct compound_hdr *hdr) | |
269 | { | |
270 | __be32 *p; | |
271 | ||
272 | encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); | |
273 | p = reserve_space(xdr, 8 + 8); | |
274 | p = xdr_encode_hyper(p, devinfo->offset); | |
275 | p = xdr_encode_hyper(p, devinfo->length); | |
276 | encode_nfs4_stateid(xdr, &args->stateid); | |
277 | p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); | |
278 | p = xdr_encode_hyper(p, devinfo->read_count); | |
279 | p = xdr_encode_hyper(p, devinfo->read_bytes); | |
280 | p = xdr_encode_hyper(p, devinfo->write_count); | |
281 | p = xdr_encode_hyper(p, devinfo->write_bytes); | |
282 | p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, | |
283 | NFS4_DEVICEID4_SIZE); | |
284 | /* Encode layoutupdate4 */ | |
285 | *p++ = cpu_to_be32(devinfo->layout_type); | |
422c93c8 TM |
286 | if (devinfo->ld_private.ops) |
287 | devinfo->ld_private.ops->encode(xdr, args, | |
288 | &devinfo->ld_private); | |
be3a5d23 TM |
289 | else |
290 | encode_uint32(xdr, 0); | |
291 | } | |
292 | ||
36022770 | 293 | static void encode_clone(struct xdr_stream *xdr, |
0096d39b | 294 | const struct nfs42_clone_args *args, |
36022770 PT |
295 | struct compound_hdr *hdr) |
296 | { | |
297 | __be32 *p; | |
298 | ||
299 | encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr); | |
300 | encode_nfs4_stateid(xdr, &args->src_stateid); | |
301 | encode_nfs4_stateid(xdr, &args->dst_stateid); | |
302 | p = reserve_space(xdr, 3*8); | |
303 | p = xdr_encode_hyper(p, args->src_offset); | |
304 | p = xdr_encode_hyper(p, args->dst_offset); | |
305 | xdr_encode_hyper(p, args->count); | |
306 | } | |
307 | ||
3eb86093 TM |
308 | static void encode_device_error(struct xdr_stream *xdr, |
309 | const struct nfs42_device_error *error) | |
310 | { | |
311 | __be32 *p; | |
312 | ||
313 | p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4); | |
314 | p = xdr_encode_opaque_fixed(p, error->dev_id.data, | |
315 | NFS4_DEVICEID4_SIZE); | |
316 | *p++ = cpu_to_be32(error->status); | |
317 | *p = cpu_to_be32(error->opnum); | |
318 | } | |
319 | ||
320 | static void encode_layouterror(struct xdr_stream *xdr, | |
321 | const struct nfs42_layout_error *args, | |
322 | struct compound_hdr *hdr) | |
323 | { | |
324 | __be32 *p; | |
325 | ||
326 | encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr); | |
327 | p = reserve_space(xdr, 8 + 8); | |
328 | p = xdr_encode_hyper(p, args->offset); | |
329 | p = xdr_encode_hyper(p, args->length); | |
330 | encode_nfs4_stateid(xdr, &args->stateid); | |
331 | p = reserve_space(xdr, 4); | |
332 | *p = cpu_to_be32(1); | |
333 | encode_device_error(xdr, &args->errors[0]); | |
334 | } | |
335 | ||
f4ac1674 AS |
336 | /* |
337 | * Encode ALLOCATE request | |
338 | */ | |
339 | static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, | |
340 | struct xdr_stream *xdr, | |
0096d39b | 341 | const void *data) |
f4ac1674 | 342 | { |
0096d39b | 343 | const struct nfs42_falloc_args *args = data; |
f4ac1674 AS |
344 | struct compound_hdr hdr = { |
345 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
346 | }; | |
347 | ||
348 | encode_compound_hdr(xdr, req, &hdr); | |
349 | encode_sequence(xdr, &args->seq_args, &hdr); | |
350 | encode_putfh(xdr, args->falloc_fh, &hdr); | |
351 | encode_allocate(xdr, args, &hdr); | |
9a51940b | 352 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); |
f4ac1674 AS |
353 | encode_nops(&hdr); |
354 | } | |
355 | ||
e0926934 | 356 | static void encode_copy_commit(struct xdr_stream *xdr, |
0096d39b | 357 | const struct nfs42_copy_args *args, |
e0926934 OK |
358 | struct compound_hdr *hdr) |
359 | { | |
360 | __be32 *p; | |
361 | ||
362 | encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); | |
363 | p = reserve_space(xdr, 12); | |
364 | p = xdr_encode_hyper(p, args->dst_pos); | |
365 | *p = cpu_to_be32(args->count); | |
366 | } | |
367 | ||
2e72448b AS |
368 | /* |
369 | * Encode COPY request | |
370 | */ | |
371 | static void nfs4_xdr_enc_copy(struct rpc_rqst *req, | |
372 | struct xdr_stream *xdr, | |
0096d39b | 373 | const void *data) |
2e72448b | 374 | { |
0096d39b | 375 | const struct nfs42_copy_args *args = data; |
2e72448b AS |
376 | struct compound_hdr hdr = { |
377 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
378 | }; | |
379 | ||
380 | encode_compound_hdr(xdr, req, &hdr); | |
381 | encode_sequence(xdr, &args->seq_args, &hdr); | |
382 | encode_putfh(xdr, args->src_fh, &hdr); | |
383 | encode_savefh(xdr, &hdr); | |
384 | encode_putfh(xdr, args->dst_fh, &hdr); | |
385 | encode_copy(xdr, args, &hdr); | |
62164f31 OK |
386 | if (args->sync) |
387 | encode_copy_commit(xdr, args, &hdr); | |
2e72448b AS |
388 | encode_nops(&hdr); |
389 | } | |
390 | ||
cb95deea OK |
391 | /* |
392 | * Encode OFFLOAD_CANEL request | |
393 | */ | |
394 | static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req, | |
395 | struct xdr_stream *xdr, | |
396 | const void *data) | |
397 | { | |
398 | const struct nfs42_offload_status_args *args = data; | |
399 | struct compound_hdr hdr = { | |
400 | .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args), | |
401 | }; | |
402 | ||
403 | encode_compound_hdr(xdr, req, &hdr); | |
404 | encode_sequence(xdr, &args->osa_seq_args, &hdr); | |
405 | encode_putfh(xdr, args->osa_src_fh, &hdr); | |
406 | encode_offload_cancel(xdr, args, &hdr); | |
407 | encode_nops(&hdr); | |
408 | } | |
409 | ||
0491567b OK |
410 | /* |
411 | * Encode COPY_NOTIFY request | |
412 | */ | |
413 | static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req, | |
414 | struct xdr_stream *xdr, | |
415 | const void *data) | |
416 | { | |
417 | const struct nfs42_copy_notify_args *args = data; | |
418 | struct compound_hdr hdr = { | |
419 | .minorversion = nfs4_xdr_minorversion(&args->cna_seq_args), | |
420 | }; | |
421 | ||
422 | encode_compound_hdr(xdr, req, &hdr); | |
423 | encode_sequence(xdr, &args->cna_seq_args, &hdr); | |
424 | encode_putfh(xdr, args->cna_src_fh, &hdr); | |
425 | encode_copy_notify(xdr, args, &hdr); | |
426 | encode_nops(&hdr); | |
427 | } | |
428 | ||
624bd5b7 AS |
429 | /* |
430 | * Encode DEALLOCATE request | |
431 | */ | |
432 | static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, | |
433 | struct xdr_stream *xdr, | |
0096d39b | 434 | const void *data) |
624bd5b7 | 435 | { |
0096d39b | 436 | const struct nfs42_falloc_args *args = data; |
624bd5b7 AS |
437 | struct compound_hdr hdr = { |
438 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
439 | }; | |
440 | ||
441 | encode_compound_hdr(xdr, req, &hdr); | |
442 | encode_sequence(xdr, &args->seq_args, &hdr); | |
443 | encode_putfh(xdr, args->falloc_fh, &hdr); | |
444 | encode_deallocate(xdr, args, &hdr); | |
9a51940b | 445 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); |
624bd5b7 AS |
446 | encode_nops(&hdr); |
447 | } | |
448 | ||
1c6dcbe5 AS |
449 | /* |
450 | * Encode SEEK request | |
451 | */ | |
452 | static void nfs4_xdr_enc_seek(struct rpc_rqst *req, | |
453 | struct xdr_stream *xdr, | |
0096d39b | 454 | const void *data) |
1c6dcbe5 | 455 | { |
0096d39b | 456 | const struct nfs42_seek_args *args = data; |
1c6dcbe5 AS |
457 | struct compound_hdr hdr = { |
458 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
459 | }; | |
460 | ||
461 | encode_compound_hdr(xdr, req, &hdr); | |
462 | encode_sequence(xdr, &args->seq_args, &hdr); | |
463 | encode_putfh(xdr, args->sa_fh, &hdr); | |
464 | encode_seek(xdr, args, &hdr); | |
465 | encode_nops(&hdr); | |
466 | } | |
467 | ||
be3a5d23 TM |
468 | /* |
469 | * Encode LAYOUTSTATS request | |
470 | */ | |
471 | static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, | |
472 | struct xdr_stream *xdr, | |
0096d39b | 473 | const void *data) |
be3a5d23 | 474 | { |
0096d39b | 475 | const struct nfs42_layoutstat_args *args = data; |
be3a5d23 TM |
476 | int i; |
477 | ||
478 | struct compound_hdr hdr = { | |
479 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
480 | }; | |
481 | ||
482 | encode_compound_hdr(xdr, req, &hdr); | |
483 | encode_sequence(xdr, &args->seq_args, &hdr); | |
484 | encode_putfh(xdr, args->fh, &hdr); | |
485 | WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); | |
486 | for (i = 0; i < args->num_dev; i++) | |
487 | encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); | |
488 | encode_nops(&hdr); | |
489 | } | |
490 | ||
36022770 PT |
491 | /* |
492 | * Encode CLONE request | |
493 | */ | |
494 | static void nfs4_xdr_enc_clone(struct rpc_rqst *req, | |
495 | struct xdr_stream *xdr, | |
0096d39b | 496 | const void *data) |
36022770 | 497 | { |
0096d39b | 498 | const struct nfs42_clone_args *args = data; |
36022770 PT |
499 | struct compound_hdr hdr = { |
500 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
501 | }; | |
502 | ||
503 | encode_compound_hdr(xdr, req, &hdr); | |
504 | encode_sequence(xdr, &args->seq_args, &hdr); | |
505 | encode_putfh(xdr, args->src_fh, &hdr); | |
506 | encode_savefh(xdr, &hdr); | |
507 | encode_putfh(xdr, args->dst_fh, &hdr); | |
508 | encode_clone(xdr, args, &hdr); | |
509 | encode_getfattr(xdr, args->dst_bitmask, &hdr); | |
510 | encode_nops(&hdr); | |
511 | } | |
512 | ||
3eb86093 TM |
513 | /* |
514 | * Encode LAYOUTERROR request | |
515 | */ | |
516 | static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req, | |
517 | struct xdr_stream *xdr, | |
518 | const void *data) | |
519 | { | |
520 | const struct nfs42_layouterror_args *args = data; | |
521 | struct compound_hdr hdr = { | |
522 | .minorversion = nfs4_xdr_minorversion(&args->seq_args), | |
523 | }; | |
524 | int i; | |
525 | ||
526 | encode_compound_hdr(xdr, req, &hdr); | |
527 | encode_sequence(xdr, &args->seq_args, &hdr); | |
528 | encode_putfh(xdr, NFS_FH(args->inode), &hdr); | |
529 | for (i = 0; i < args->num_errors; i++) | |
530 | encode_layouterror(xdr, &args->errors[i], &hdr); | |
531 | encode_nops(&hdr); | |
532 | } | |
533 | ||
f4ac1674 AS |
534 | static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) |
535 | { | |
536 | return decode_op_hdr(xdr, OP_ALLOCATE); | |
537 | } | |
538 | ||
2e72448b AS |
539 | static int decode_write_response(struct xdr_stream *xdr, |
540 | struct nfs42_write_res *res) | |
541 | { | |
542 | __be32 *p; | |
67aa7444 | 543 | int status, count; |
2e72448b | 544 | |
67aa7444 | 545 | p = xdr_inline_decode(xdr, 4); |
2e72448b | 546 | if (unlikely(!p)) |
eb72f484 | 547 | return -EIO; |
67aa7444 OK |
548 | count = be32_to_cpup(p); |
549 | if (count > 1) | |
6fdf339b | 550 | return -EREMOTEIO; |
67aa7444 OK |
551 | else if (count == 1) { |
552 | status = decode_opaque_fixed(xdr, &res->stateid, | |
553 | NFS4_STATEID_SIZE); | |
554 | if (unlikely(status)) | |
eb72f484 | 555 | return -EIO; |
6fdf339b | 556 | } |
67aa7444 OK |
557 | p = xdr_inline_decode(xdr, 8 + 4); |
558 | if (unlikely(!p)) | |
eb72f484 | 559 | return -EIO; |
2e72448b AS |
560 | p = xdr_decode_hyper(p, &res->count); |
561 | res->verifier.committed = be32_to_cpup(p); | |
562 | return decode_verifier(xdr, &res->verifier.verifier); | |
2e72448b AS |
563 | } |
564 | ||
0491567b OK |
565 | static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns) |
566 | { | |
567 | struct nfs42_netaddr *naddr; | |
568 | uint32_t dummy; | |
569 | char *dummy_str; | |
570 | __be32 *p; | |
571 | int status; | |
572 | ||
573 | /* nl_type */ | |
574 | p = xdr_inline_decode(xdr, 4); | |
575 | if (unlikely(!p)) | |
576 | return -EIO; | |
577 | ns->nl4_type = be32_to_cpup(p); | |
578 | switch (ns->nl4_type) { | |
579 | case NL4_NAME: | |
580 | case NL4_URL: | |
581 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | |
582 | if (unlikely(status)) | |
583 | return status; | |
584 | if (unlikely(dummy > NFS4_OPAQUE_LIMIT)) | |
585 | return -EIO; | |
586 | memcpy(&ns->u.nl4_str, dummy_str, dummy); | |
587 | ns->u.nl4_str_sz = dummy; | |
588 | break; | |
589 | case NL4_NETADDR: | |
590 | naddr = &ns->u.nl4_addr; | |
591 | ||
592 | /* netid string */ | |
593 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | |
594 | if (unlikely(status)) | |
595 | return status; | |
596 | if (unlikely(dummy > RPCBIND_MAXNETIDLEN)) | |
597 | return -EIO; | |
598 | naddr->netid_len = dummy; | |
599 | memcpy(naddr->netid, dummy_str, naddr->netid_len); | |
600 | ||
601 | /* uaddr string */ | |
602 | status = decode_opaque_inline(xdr, &dummy, &dummy_str); | |
603 | if (unlikely(status)) | |
604 | return status; | |
605 | if (unlikely(dummy > RPCBIND_MAXUADDRLEN)) | |
606 | return -EIO; | |
607 | naddr->addr_len = dummy; | |
608 | memcpy(naddr->addr, dummy_str, naddr->addr_len); | |
609 | break; | |
610 | default: | |
611 | WARN_ON_ONCE(1); | |
612 | return -EIO; | |
613 | } | |
614 | return 0; | |
615 | } | |
616 | ||
2e72448b AS |
617 | static int decode_copy_requirements(struct xdr_stream *xdr, |
618 | struct nfs42_copy_res *res) { | |
619 | __be32 *p; | |
620 | ||
621 | p = xdr_inline_decode(xdr, 4 + 4); | |
622 | if (unlikely(!p)) | |
eb72f484 | 623 | return -EIO; |
2e72448b AS |
624 | |
625 | res->consecutive = be32_to_cpup(p++); | |
626 | res->synchronous = be32_to_cpup(p++); | |
627 | return 0; | |
2e72448b AS |
628 | } |
629 | ||
630 | static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) | |
631 | { | |
632 | int status; | |
633 | ||
634 | status = decode_op_hdr(xdr, OP_COPY); | |
635 | if (status == NFS4ERR_OFFLOAD_NO_REQS) { | |
636 | status = decode_copy_requirements(xdr, res); | |
637 | if (status) | |
638 | return status; | |
639 | return NFS4ERR_OFFLOAD_NO_REQS; | |
640 | } else if (status) | |
641 | return status; | |
642 | ||
643 | status = decode_write_response(xdr, &res->write_res); | |
644 | if (status) | |
645 | return status; | |
646 | ||
647 | return decode_copy_requirements(xdr, res); | |
648 | } | |
649 | ||
cb95deea OK |
650 | static int decode_offload_cancel(struct xdr_stream *xdr, |
651 | struct nfs42_offload_status_res *res) | |
652 | { | |
653 | return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL); | |
654 | } | |
655 | ||
0491567b OK |
656 | static int decode_copy_notify(struct xdr_stream *xdr, |
657 | struct nfs42_copy_notify_res *res) | |
658 | { | |
659 | __be32 *p; | |
660 | int status, count; | |
661 | ||
662 | status = decode_op_hdr(xdr, OP_COPY_NOTIFY); | |
663 | if (status) | |
664 | return status; | |
665 | /* cnr_lease_time */ | |
666 | p = xdr_inline_decode(xdr, 12); | |
667 | if (unlikely(!p)) | |
668 | return -EIO; | |
669 | p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds); | |
670 | res->cnr_lease_time.nseconds = be32_to_cpup(p); | |
671 | ||
672 | status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE); | |
673 | if (unlikely(status)) | |
674 | return -EIO; | |
675 | ||
676 | /* number of source addresses */ | |
677 | p = xdr_inline_decode(xdr, 4); | |
678 | if (unlikely(!p)) | |
679 | return -EIO; | |
680 | ||
681 | count = be32_to_cpup(p); | |
682 | if (count > 1) | |
683 | pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n", | |
684 | __func__, count); | |
685 | ||
686 | status = decode_nl4_server(xdr, &res->cnr_src); | |
687 | if (unlikely(status)) | |
688 | return -EIO; | |
689 | return 0; | |
690 | } | |
691 | ||
624bd5b7 AS |
692 | static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) |
693 | { | |
694 | return decode_op_hdr(xdr, OP_DEALLOCATE); | |
695 | } | |
696 | ||
1c6dcbe5 AS |
697 | static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) |
698 | { | |
699 | int status; | |
700 | __be32 *p; | |
701 | ||
702 | status = decode_op_hdr(xdr, OP_SEEK); | |
703 | if (status) | |
704 | return status; | |
705 | ||
706 | p = xdr_inline_decode(xdr, 4 + 8); | |
707 | if (unlikely(!p)) | |
eb72f484 | 708 | return -EIO; |
1c6dcbe5 AS |
709 | |
710 | res->sr_eof = be32_to_cpup(p++); | |
711 | p = xdr_decode_hyper(p, &res->sr_offset); | |
712 | return 0; | |
1c6dcbe5 AS |
713 | } |
714 | ||
19cf6335 | 715 | static int decode_layoutstats(struct xdr_stream *xdr) |
be3a5d23 | 716 | { |
da2e8127 | 717 | return decode_op_hdr(xdr, OP_LAYOUTSTATS); |
be3a5d23 TM |
718 | } |
719 | ||
36022770 PT |
720 | static int decode_clone(struct xdr_stream *xdr) |
721 | { | |
722 | return decode_op_hdr(xdr, OP_CLONE); | |
723 | } | |
724 | ||
3eb86093 TM |
725 | static int decode_layouterror(struct xdr_stream *xdr) |
726 | { | |
727 | return decode_op_hdr(xdr, OP_LAYOUTERROR); | |
728 | } | |
729 | ||
f4ac1674 AS |
730 | /* |
731 | * Decode ALLOCATE request | |
732 | */ | |
733 | static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, | |
734 | struct xdr_stream *xdr, | |
18d9cff4 | 735 | void *data) |
f4ac1674 | 736 | { |
18d9cff4 | 737 | struct nfs42_falloc_res *res = data; |
f4ac1674 AS |
738 | struct compound_hdr hdr; |
739 | int status; | |
740 | ||
741 | status = decode_compound_hdr(xdr, &hdr); | |
742 | if (status) | |
743 | goto out; | |
744 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
745 | if (status) | |
746 | goto out; | |
747 | status = decode_putfh(xdr); | |
748 | if (status) | |
749 | goto out; | |
750 | status = decode_allocate(xdr, res); | |
9a51940b AS |
751 | if (status) |
752 | goto out; | |
753 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | |
f4ac1674 AS |
754 | out: |
755 | return status; | |
756 | } | |
757 | ||
2e72448b AS |
758 | /* |
759 | * Decode COPY response | |
760 | */ | |
761 | static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, | |
762 | struct xdr_stream *xdr, | |
18d9cff4 | 763 | void *data) |
2e72448b | 764 | { |
18d9cff4 | 765 | struct nfs42_copy_res *res = data; |
2e72448b AS |
766 | struct compound_hdr hdr; |
767 | int status; | |
768 | ||
769 | status = decode_compound_hdr(xdr, &hdr); | |
770 | if (status) | |
771 | goto out; | |
772 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
773 | if (status) | |
774 | goto out; | |
775 | status = decode_putfh(xdr); | |
776 | if (status) | |
777 | goto out; | |
778 | status = decode_savefh(xdr); | |
779 | if (status) | |
780 | goto out; | |
781 | status = decode_putfh(xdr); | |
782 | if (status) | |
783 | goto out; | |
784 | status = decode_copy(xdr, res); | |
e0926934 OK |
785 | if (status) |
786 | goto out; | |
62164f31 OK |
787 | if (res->commit_res.verf) |
788 | status = decode_commit(xdr, &res->commit_res); | |
2e72448b AS |
789 | out: |
790 | return status; | |
791 | } | |
792 | ||
cb95deea OK |
793 | /* |
794 | * Decode OFFLOAD_CANCEL response | |
795 | */ | |
796 | static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp, | |
797 | struct xdr_stream *xdr, | |
798 | void *data) | |
799 | { | |
800 | struct nfs42_offload_status_res *res = data; | |
801 | struct compound_hdr hdr; | |
802 | int status; | |
803 | ||
804 | status = decode_compound_hdr(xdr, &hdr); | |
805 | if (status) | |
806 | goto out; | |
807 | status = decode_sequence(xdr, &res->osr_seq_res, rqstp); | |
808 | if (status) | |
809 | goto out; | |
810 | status = decode_putfh(xdr); | |
811 | if (status) | |
812 | goto out; | |
813 | status = decode_offload_cancel(xdr, res); | |
814 | ||
815 | out: | |
816 | return status; | |
817 | } | |
818 | ||
0491567b OK |
819 | /* |
820 | * Decode COPY_NOTIFY response | |
821 | */ | |
822 | static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp, | |
823 | struct xdr_stream *xdr, | |
824 | void *data) | |
825 | { | |
826 | struct nfs42_copy_notify_res *res = data; | |
827 | struct compound_hdr hdr; | |
828 | int status; | |
829 | ||
830 | status = decode_compound_hdr(xdr, &hdr); | |
831 | if (status) | |
832 | goto out; | |
833 | status = decode_sequence(xdr, &res->cnr_seq_res, rqstp); | |
834 | if (status) | |
835 | goto out; | |
836 | status = decode_putfh(xdr); | |
837 | if (status) | |
838 | goto out; | |
839 | status = decode_copy_notify(xdr, res); | |
840 | ||
841 | out: | |
842 | return status; | |
843 | } | |
844 | ||
624bd5b7 AS |
845 | /* |
846 | * Decode DEALLOCATE request | |
847 | */ | |
848 | static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, | |
849 | struct xdr_stream *xdr, | |
18d9cff4 | 850 | void *data) |
624bd5b7 | 851 | { |
18d9cff4 | 852 | struct nfs42_falloc_res *res = data; |
624bd5b7 AS |
853 | struct compound_hdr hdr; |
854 | int status; | |
855 | ||
856 | status = decode_compound_hdr(xdr, &hdr); | |
857 | if (status) | |
858 | goto out; | |
859 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
860 | if (status) | |
861 | goto out; | |
862 | status = decode_putfh(xdr); | |
863 | if (status) | |
864 | goto out; | |
865 | status = decode_deallocate(xdr, res); | |
9a51940b AS |
866 | if (status) |
867 | goto out; | |
868 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | |
624bd5b7 AS |
869 | out: |
870 | return status; | |
871 | } | |
872 | ||
1c6dcbe5 AS |
873 | /* |
874 | * Decode SEEK request | |
875 | */ | |
876 | static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, | |
877 | struct xdr_stream *xdr, | |
18d9cff4 | 878 | void *data) |
1c6dcbe5 | 879 | { |
18d9cff4 | 880 | struct nfs42_seek_res *res = data; |
1c6dcbe5 AS |
881 | struct compound_hdr hdr; |
882 | int status; | |
883 | ||
884 | status = decode_compound_hdr(xdr, &hdr); | |
885 | if (status) | |
886 | goto out; | |
887 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
888 | if (status) | |
889 | goto out; | |
890 | status = decode_putfh(xdr); | |
891 | if (status) | |
892 | goto out; | |
893 | status = decode_seek(xdr, res); | |
894 | out: | |
895 | return status; | |
896 | } | |
be3a5d23 TM |
897 | |
898 | /* | |
899 | * Decode LAYOUTSTATS request | |
900 | */ | |
901 | static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, | |
902 | struct xdr_stream *xdr, | |
18d9cff4 | 903 | void *data) |
be3a5d23 | 904 | { |
18d9cff4 | 905 | struct nfs42_layoutstat_res *res = data; |
be3a5d23 TM |
906 | struct compound_hdr hdr; |
907 | int status, i; | |
908 | ||
909 | status = decode_compound_hdr(xdr, &hdr); | |
910 | if (status) | |
911 | goto out; | |
912 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
913 | if (status) | |
914 | goto out; | |
915 | status = decode_putfh(xdr); | |
916 | if (status) | |
917 | goto out; | |
918 | WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); | |
919 | for (i = 0; i < res->num_dev; i++) { | |
19cf6335 | 920 | status = decode_layoutstats(xdr); |
be3a5d23 TM |
921 | if (status) |
922 | goto out; | |
923 | } | |
924 | out: | |
925 | res->rpc_status = status; | |
926 | return status; | |
927 | } | |
928 | ||
36022770 PT |
929 | /* |
930 | * Decode CLONE request | |
931 | */ | |
932 | static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, | |
933 | struct xdr_stream *xdr, | |
18d9cff4 | 934 | void *data) |
36022770 | 935 | { |
18d9cff4 | 936 | struct nfs42_clone_res *res = data; |
36022770 PT |
937 | struct compound_hdr hdr; |
938 | int status; | |
939 | ||
940 | status = decode_compound_hdr(xdr, &hdr); | |
941 | if (status) | |
942 | goto out; | |
943 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
944 | if (status) | |
945 | goto out; | |
946 | status = decode_putfh(xdr); | |
947 | if (status) | |
948 | goto out; | |
949 | status = decode_savefh(xdr); | |
950 | if (status) | |
951 | goto out; | |
952 | status = decode_putfh(xdr); | |
953 | if (status) | |
954 | goto out; | |
955 | status = decode_clone(xdr); | |
956 | if (status) | |
957 | goto out; | |
958 | status = decode_getfattr(xdr, res->dst_fattr, res->server); | |
959 | ||
960 | out: | |
961 | res->rpc_status = status; | |
962 | return status; | |
963 | } | |
964 | ||
3eb86093 TM |
965 | /* |
966 | * Decode LAYOUTERROR request | |
967 | */ | |
968 | static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp, | |
969 | struct xdr_stream *xdr, | |
970 | void *data) | |
971 | { | |
972 | struct nfs42_layouterror_res *res = data; | |
973 | struct compound_hdr hdr; | |
974 | int status, i; | |
975 | ||
976 | status = decode_compound_hdr(xdr, &hdr); | |
977 | if (status) | |
978 | goto out; | |
979 | status = decode_sequence(xdr, &res->seq_res, rqstp); | |
980 | if (status) | |
981 | goto out; | |
982 | status = decode_putfh(xdr); | |
983 | ||
984 | for (i = 0; i < res->num_errors && status == 0; i++) | |
985 | status = decode_layouterror(xdr); | |
986 | out: | |
987 | res->rpc_status = status; | |
988 | return status; | |
989 | } | |
990 | ||
1c6dcbe5 | 991 | #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ |