]>
Commit | Line | Data |
---|---|---|
b2441318 | 1 | // SPDX-License-Identifier: GPL-2.0 |
1c6dcbe5 AS |
2 | /* |
3 | * Copyright (c) 2014 Anna Schumaker <[email protected]> | |
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 | ||
64edd55d AS |
10 | /* Not limited by NFS itself, limited by the generic xattr code */ |
11 | #define nfs4_xattr_name_maxsz XDR_QUADLEN(XATTR_NAME_MAX) | |
12 | ||
f4ac1674 AS |
13 | #define encode_fallocate_maxsz (encode_stateid_maxsz + \ |
14 | 2 /* offset */ + \ | |
15 | 2 /* length */) | |
2e72448b AS |
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)) | |
f4ac1674 AS |
21 | #define encode_allocate_maxsz (op_encode_hdr_maxsz + \ |
22 | encode_fallocate_maxsz) | |
23 | #define decode_allocate_maxsz (op_decode_hdr_maxsz) | |
2e72448b AS |
24 | #define encode_copy_maxsz (op_encode_hdr_maxsz + \ |
25 | XDR_QUADLEN(NFS4_STATEID_SIZE) + \ | |
26 | XDR_QUADLEN(NFS4_STATEID_SIZE) + \ | |
1d38f3f0 OK |
27 | 2 + 2 + 2 + 1 + 1 + 1 +\ |
28 | 1 + /* One cnr_source_server */\ | |
29 | 1 + /* nl4_type */ \ | |
30 | 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT)) | |
2e72448b AS |
31 | #define decode_copy_maxsz (op_decode_hdr_maxsz + \ |
32 | NFS42_WRITE_RES_SIZE + \ | |
33 | 1 /* cr_consecutive */ + \ | |
34 | 1 /* cr_synchronous */) | |
cb95deea OK |
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) | |
0491567b OK |
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)) | |
624bd5b7 AS |
48 | #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ |
49 | encode_fallocate_maxsz) | |
50 | #define decode_deallocate_maxsz (op_decode_hdr_maxsz) | |
c5675526 AS |
51 | #define encode_read_plus_maxsz (op_encode_hdr_maxsz + \ |
52 | encode_stateid_maxsz + 3) | |
f8527028 AS |
53 | #define NFS42_READ_PLUS_DATA_SEGMENT_SIZE \ |
54 | (1 /* data_content4 */ + \ | |
c5675526 | 55 | 2 /* data_info4.di_offset */ + \ |
f8527028 | 56 | 1 /* data_info4.di_length */) |
8d18f6c5 AS |
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) | |
c5675526 AS |
63 | #define decode_read_plus_maxsz (op_decode_hdr_maxsz + \ |
64 | 1 /* rpr_eof */ + \ | |
65 | 1 /* rpr_contents count */ + \ | |
8d18f6c5 | 66 | NFS42_READ_PLUS_HOLE_SEGMENT_SIZE) |
1c6dcbe5 AS |
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 */) | |
be3a5d23 TM |
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) | |
3eb86093 TM |
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) | |
36022770 PT |
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) | |
64edd55d AS |
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) | |
1c6dcbe5 | 113 | |
f4ac1674 | 114 | #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 115 | encode_sequence_maxsz + \ |
f4ac1674 | 116 | encode_putfh_maxsz + \ |
9a51940b AS |
117 | encode_allocate_maxsz + \ |
118 | encode_getattr_maxsz) | |
f4ac1674 | 119 | #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 120 | decode_sequence_maxsz + \ |
f4ac1674 | 121 | decode_putfh_maxsz + \ |
9a51940b AS |
122 | decode_allocate_maxsz + \ |
123 | decode_getattr_maxsz) | |
2e72448b | 124 | #define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 125 | encode_sequence_maxsz + \ |
2e72448b AS |
126 | encode_putfh_maxsz + \ |
127 | encode_savefh_maxsz + \ | |
128 | encode_putfh_maxsz + \ | |
e0926934 OK |
129 | encode_copy_maxsz + \ |
130 | encode_commit_maxsz) | |
2e72448b | 131 | #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 132 | decode_sequence_maxsz + \ |
2e72448b AS |
133 | decode_putfh_maxsz + \ |
134 | decode_savefh_maxsz + \ | |
135 | decode_putfh_maxsz + \ | |
e0926934 OK |
136 | decode_copy_maxsz + \ |
137 | decode_commit_maxsz) | |
cb95deea | 138 | #define NFS4_enc_offload_cancel_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 139 | encode_sequence_maxsz + \ |
cb95deea OK |
140 | encode_putfh_maxsz + \ |
141 | encode_offload_cancel_maxsz) | |
142 | #define NFS4_dec_offload_cancel_sz (compound_decode_hdr_maxsz + \ | |
1a3466ae | 143 | decode_sequence_maxsz + \ |
cb95deea OK |
144 | decode_putfh_maxsz + \ |
145 | decode_offload_cancel_maxsz) | |
0491567b OK |
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) | |
624bd5b7 | 152 | #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 153 | encode_sequence_maxsz + \ |
624bd5b7 | 154 | encode_putfh_maxsz + \ |
9a51940b AS |
155 | encode_deallocate_maxsz + \ |
156 | encode_getattr_maxsz) | |
624bd5b7 | 157 | #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ |
1a3466ae | 158 | decode_sequence_maxsz + \ |
624bd5b7 | 159 | decode_putfh_maxsz + \ |
9a51940b AS |
160 | decode_deallocate_maxsz + \ |
161 | decode_getattr_maxsz) | |
c5675526 AS |
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) | |
1c6dcbe5 | 170 | #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ |
1a3466ae | 171 | encode_sequence_maxsz + \ |
1c6dcbe5 AS |
172 | encode_putfh_maxsz + \ |
173 | encode_seek_maxsz) | |
174 | #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ | |
1a3466ae | 175 | decode_sequence_maxsz + \ |
1c6dcbe5 AS |
176 | decode_putfh_maxsz + \ |
177 | decode_seek_maxsz) | |
be3a5d23 TM |
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) | |
3eb86093 TM |
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) | |
36022770 PT |
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) | |
64edd55d AS |
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 + \ | |
86e2e1f6 AS |
221 | encode_setxattr_maxsz + \ |
222 | encode_getattr_maxsz) | |
64edd55d AS |
223 | #define NFS4_dec_setxattr_sz (compound_decode_hdr_maxsz + \ |
224 | decode_sequence_maxsz + \ | |
225 | decode_putfh_maxsz + \ | |
86e2e1f6 AS |
226 | decode_setxattr_maxsz + \ |
227 | decode_getattr_maxsz) | |
64edd55d AS |
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) | |
04a5da69 FL |
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); | |
04a5da69 | 267 | |
f4ac1674 | 268 | static void encode_fallocate(struct xdr_stream *xdr, |
0096d39b | 269 | const struct nfs42_falloc_args *args) |
f4ac1674 AS |
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 | ||
276 | static void encode_allocate(struct xdr_stream *xdr, | |
0096d39b | 277 | const struct nfs42_falloc_args *args, |
f4ac1674 AS |
278 | struct compound_hdr *hdr) |
279 | { | |
280 | encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); | |
281 | encode_fallocate(xdr, args); | |
282 | } | |
283 | ||
0491567b OK |
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 | ||
2e72448b | 304 | static void encode_copy(struct xdr_stream *xdr, |
0096d39b | 305 | const struct nfs42_copy_args *args, |
2e72448b AS |
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 */ | |
62164f31 | 317 | encode_uint32(xdr, args->sync); |
1d38f3f0 OK |
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); | |
2e72448b AS |
324 | } |
325 | ||
fd42ba82 AS |
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 | ||
cb95deea OK |
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 | ||
0491567b OK |
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 | ||
624bd5b7 | 355 | static void encode_deallocate(struct xdr_stream *xdr, |
0096d39b | 356 | const struct nfs42_falloc_args *args, |
624bd5b7 AS |
357 | struct compound_hdr *hdr) |
358 | { | |
359 | encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); | |
360 | encode_fallocate(xdr, args); | |
361 | } | |
362 | ||
c5675526 AS |
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 | ||
1c6dcbe5 | 373 | static void encode_seek(struct xdr_stream *xdr, |
0096d39b | 374 | const struct nfs42_seek_args *args, |
1c6dcbe5 AS |
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 | ||
be3a5d23 | 383 | static void encode_layoutstats(struct xdr_stream *xdr, |
0096d39b | 384 | const struct nfs42_layoutstat_args *args, |
be3a5d23 TM |
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); | |
422c93c8 TM |
404 | if (devinfo->ld_private.ops) |
405 | devinfo->ld_private.ops->encode(xdr, args, | |
406 | &devinfo->ld_private); | |
be3a5d23 TM |
407 | else |
408 | encode_uint32(xdr, 0); | |
409 | } | |
410 | ||
36022770 | 411 | static void encode_clone(struct xdr_stream *xdr, |
0096d39b | 412 | const struct nfs42_clone_args *args, |
36022770 PT |
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 | ||
3eb86093 TM |
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 | ||
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 | ||
3e1f0212 FL |
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 | ||
3e1f0212 FL |
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 | ||
3e1f0212 FL |
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 | ||
3e1f0212 FL |
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 | ||
6c2190b3 | 493 | encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz, hdr); |
3e1f0212 FL |
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 | ||
f4ac1674 AS |
508 | /* |
509 | * Encode ALLOCATE request | |
510 | */ | |
511 | static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, | |
512 | struct xdr_stream *xdr, | |
0096d39b | 513 | const void *data) |
f4ac1674 | 514 | { |
0096d39b | 515 | const struct nfs42_falloc_args *args = data; |
f4ac1674 AS |
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); | |
9a51940b | 524 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); |
f4ac1674 AS |
525 | encode_nops(&hdr); |
526 | } | |
527 | ||
2e72448b AS |
528 | /* |
529 | * Encode COPY request | |
530 | */ | |
531 | static void nfs4_xdr_enc_copy(struct rpc_rqst *req, | |
532 | struct xdr_stream *xdr, | |
0096d39b | 533 | const void *data) |
2e72448b | 534 | { |
0096d39b | 535 | const struct nfs42_copy_args *args = data; |
2e72448b AS |
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); | |
62164f31 OK |
546 | if (args->sync) |
547 | encode_copy_commit(xdr, args, &hdr); | |
2e72448b AS |
548 | encode_nops(&hdr); |
549 | } | |
550 | ||
cb95deea OK |
551 | /* |
552 | * Encode OFFLOAD_CANEL request | |
553 | */ | |
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 | ||
0491567b OK |
570 | /* |
571 | * Encode COPY_NOTIFY request | |
572 | */ | |
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 | ||
624bd5b7 AS |
589 | /* |
590 | * Encode DEALLOCATE request | |
591 | */ | |
592 | static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, | |
593 | struct xdr_stream *xdr, | |
0096d39b | 594 | const void *data) |
624bd5b7 | 595 | { |
0096d39b | 596 | const struct nfs42_falloc_args *args = data; |
624bd5b7 AS |
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); | |
9a51940b | 605 | encode_getfattr(xdr, args->falloc_bitmask, &hdr); |
624bd5b7 AS |
606 | encode_nops(&hdr); |
607 | } | |
608 | ||
c5675526 AS |
609 | /* |
610 | * Encode READ_PLUS request | |
611 | */ | |
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 | ||
8d18f6c5 AS |
626 | rpc_prepare_reply_pages(req, args->pages, args->pgbase, args->count, |
627 | hdr.replen - READ_PLUS_SEGMENT_SIZE_DIFF); | |
c5675526 AS |
628 | encode_nops(&hdr); |
629 | } | |
630 | ||
1c6dcbe5 AS |
631 | /* |
632 | * Encode SEEK request | |
633 | */ | |
634 | static void nfs4_xdr_enc_seek(struct rpc_rqst *req, | |
635 | struct xdr_stream *xdr, | |
0096d39b | 636 | const void *data) |
1c6dcbe5 | 637 | { |
0096d39b | 638 | const struct nfs42_seek_args *args = data; |
1c6dcbe5 AS |
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 | ||
be3a5d23 TM |
650 | /* |
651 | * Encode LAYOUTSTATS request | |
652 | */ | |
653 | static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, | |
654 | struct xdr_stream *xdr, | |
0096d39b | 655 | const void *data) |
be3a5d23 | 656 | { |
0096d39b | 657 | const struct nfs42_layoutstat_args *args = data; |
be3a5d23 TM |
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 | ||
36022770 PT |
673 | /* |
674 | * Encode CLONE request | |
675 | */ | |
676 | static void nfs4_xdr_enc_clone(struct rpc_rqst *req, | |
677 | struct xdr_stream *xdr, | |
0096d39b | 678 | const void *data) |
36022770 | 679 | { |
0096d39b | 680 | const struct nfs42_clone_args *args = data; |
36022770 PT |
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 | ||
3eb86093 TM |
695 | /* |
696 | * Encode LAYOUTERROR request | |
697 | */ | |
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 | ||
31f1bd8f AS |
716 | /* |
717 | * Encode SETXATTR request | |
718 | */ | |
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); | |
86e2e1f6 | 731 | encode_getfattr(xdr, args->bitmask, &hdr); |
31f1bd8f AS |
732 | encode_nops(&hdr); |
733 | } | |
734 | ||
735 | /* | |
736 | * Encode GETXATTR request | |
737 | */ | |
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 | */ | |
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 | */ | |
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 | ||
f4ac1674 AS |
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 | ||
2e72448b AS |
805 | static int decode_write_response(struct xdr_stream *xdr, |
806 | struct nfs42_write_res *res) | |
807 | { | |
808 | __be32 *p; | |
67aa7444 | 809 | int status, count; |
2e72448b | 810 | |
67aa7444 | 811 | p = xdr_inline_decode(xdr, 4); |
2e72448b | 812 | if (unlikely(!p)) |
eb72f484 | 813 | return -EIO; |
67aa7444 OK |
814 | count = be32_to_cpup(p); |
815 | if (count > 1) | |
6fdf339b | 816 | return -EREMOTEIO; |
67aa7444 OK |
817 | else if (count == 1) { |
818 | status = decode_opaque_fixed(xdr, &res->stateid, | |
819 | NFS4_STATEID_SIZE); | |
820 | if (unlikely(status)) | |
eb72f484 | 821 | return -EIO; |
6fdf339b | 822 | } |
67aa7444 OK |
823 | p = xdr_inline_decode(xdr, 8 + 4); |
824 | if (unlikely(!p)) | |
eb72f484 | 825 | return -EIO; |
2e72448b AS |
826 | p = xdr_decode_hyper(p, &res->count); |
827 | res->verifier.committed = be32_to_cpup(p); | |
828 | return decode_verifier(xdr, &res->verifier.verifier); | |
2e72448b AS |
829 | } |
830 | ||
0491567b OK |
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 | ||
2e72448b AS |
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)) | |
eb72f484 | 889 | return -EIO; |
2e72448b AS |
890 | |
891 | res->consecutive = be32_to_cpup(p++); | |
892 | res->synchronous = be32_to_cpup(p++); | |
893 | return 0; | |
2e72448b AS |
894 | } |
895 | ||
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 | ||
cb95deea OK |
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 | ||
0491567b OK |
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 | ||
624bd5b7 AS |
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 | ||
d3b00a80 AS |
963 | struct read_plus_segment { |
964 | enum data_content4 type; | |
c5675526 | 965 | uint64_t offset; |
d3b00a80 AS |
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 | ||
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 | ||
983 | static int decode_read_plus_segment(struct xdr_stream *xdr, | |
984 | struct read_plus_segment *seg) | |
985 | { | |
c5675526 AS |
986 | __be32 *p; |
987 | ||
d3b00a80 | 988 | p = xdr_inline_decode(xdr, 4); |
503b934a | 989 | if (!p) |
d3b00a80 AS |
990 | return -EIO; |
991 | seg->type = be32_to_cpup(p++); | |
c5675526 | 992 | |
d3b00a80 AS |
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; | |
c5675526 AS |
1011 | return 0; |
1012 | } | |
1013 | ||
d3b00a80 AS |
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) | |
c05eafad | 1018 | { |
d3b00a80 AS |
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; | |
82f98c8b | 1034 | } |
c05eafad | 1035 | |
d3b00a80 AS |
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); | |
c05eafad AS |
1041 | } |
1042 | ||
c5675526 AS |
1043 | static int decode_read_plus(struct xdr_stream *xdr, struct nfs_pgio_res *res) |
1044 | { | |
82f98c8b TM |
1045 | struct nfs_pgio_header *hdr = |
1046 | container_of(res, struct nfs_pgio_header, res); | |
1047 | struct nfs_pgio_args *args = &hdr->args; | |
d3b00a80 AS |
1048 | uint32_t segments; |
1049 | struct read_plus_segment *segs; | |
bff049a3 | 1050 | int status, i; |
c5675526 AS |
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 | ||
1ee63101 | 1061 | res->count = 0; |
d3b00a80 | 1062 | res->eof = be32_to_cpup(p++); |
c5675526 AS |
1063 | segments = be32_to_cpup(p++); |
1064 | if (segments == 0) | |
bb05a617 | 1065 | return 0; |
c5675526 | 1066 | |
d3b00a80 AS |
1067 | segs = kmalloc_array(segments, sizeof(*segs), GFP_KERNEL); |
1068 | if (!segs) | |
1069 | return -ENOMEM; | |
c5675526 | 1070 | |
d3b00a80 AS |
1071 | for (i = 0; i < segments; i++) { |
1072 | status = decode_read_plus_segment(xdr, &segs[i]); | |
bff049a3 | 1073 | if (status < 0) |
d3b00a80 | 1074 | goto out; |
bff049a3 | 1075 | } |
c5675526 | 1076 | |
d3b00a80 AS |
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 | ||
c5675526 | 1082 | out: |
d3b00a80 AS |
1083 | kfree(segs); |
1084 | return status; | |
c5675526 AS |
1085 | } |
1086 | ||
1c6dcbe5 AS |
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)) | |
eb72f484 | 1098 | return -EIO; |
1c6dcbe5 AS |
1099 | |
1100 | res->sr_eof = be32_to_cpup(p++); | |
1101 | p = xdr_decode_hyper(p, &res->sr_offset); | |
1102 | return 0; | |
1c6dcbe5 AS |
1103 | } |
1104 | ||
19cf6335 | 1105 | static int decode_layoutstats(struct xdr_stream *xdr) |
be3a5d23 | 1106 | { |
da2e8127 | 1107 | return decode_op_hdr(xdr, OP_LAYOUTSTATS); |
be3a5d23 TM |
1108 | } |
1109 | ||
36022770 PT |
1110 | static int decode_clone(struct xdr_stream *xdr) |
1111 | { | |
1112 | return decode_op_hdr(xdr, OP_CLONE); | |
1113 | } | |
1114 | ||
3eb86093 TM |
1115 | static int decode_layouterror(struct xdr_stream *xdr) |
1116 | { | |
1117 | return decode_op_hdr(xdr, OP_LAYOUTERROR); | |
1118 | } | |
1119 | ||
04b4c9fb AS |
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 | ||
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 | ||
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 | ||
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 | ||
f4ac1674 AS |
1282 | /* |
1283 | * Decode ALLOCATE request | |
1284 | */ | |
1285 | static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, | |
1286 | struct xdr_stream *xdr, | |
18d9cff4 | 1287 | void *data) |
f4ac1674 | 1288 | { |
18d9cff4 | 1289 | struct nfs42_falloc_res *res = data; |
f4ac1674 AS |
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); | |
9a51940b AS |
1303 | if (status) |
1304 | goto out; | |
1305 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | |
f4ac1674 AS |
1306 | out: |
1307 | return status; | |
1308 | } | |
1309 | ||
2e72448b AS |
1310 | /* |
1311 | * Decode COPY response | |
1312 | */ | |
1313 | static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, | |
1314 | struct xdr_stream *xdr, | |
18d9cff4 | 1315 | void *data) |
2e72448b | 1316 | { |
18d9cff4 | 1317 | struct nfs42_copy_res *res = data; |
2e72448b AS |
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); | |
e0926934 OK |
1337 | if (status) |
1338 | goto out; | |
62164f31 OK |
1339 | if (res->commit_res.verf) |
1340 | status = decode_commit(xdr, &res->commit_res); | |
2e72448b AS |
1341 | out: |
1342 | return status; | |
1343 | } | |
1344 | ||
cb95deea OK |
1345 | /* |
1346 | * Decode OFFLOAD_CANCEL response | |
1347 | */ | |
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 | ||
0491567b OK |
1371 | /* |
1372 | * Decode COPY_NOTIFY response | |
1373 | */ | |
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 | ||
624bd5b7 AS |
1397 | /* |
1398 | * Decode DEALLOCATE request | |
1399 | */ | |
1400 | static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, | |
1401 | struct xdr_stream *xdr, | |
18d9cff4 | 1402 | void *data) |
624bd5b7 | 1403 | { |
18d9cff4 | 1404 | struct nfs42_falloc_res *res = data; |
624bd5b7 AS |
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); | |
9a51940b AS |
1418 | if (status) |
1419 | goto out; | |
1420 | decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); | |
624bd5b7 AS |
1421 | out: |
1422 | return status; | |
1423 | } | |
1424 | ||
c5675526 AS |
1425 | /* |
1426 | * Decode READ_PLUS request | |
1427 | */ | |
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 | ||
303a7805 | 1436 | xdr_set_scratch_buffer(xdr, res->scratch, READ_PLUS_SCRATCH_SIZE); |
fbd2a05f | 1437 | |
c5675526 AS |
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 | ||
1c6dcbe5 AS |
1454 | /* |
1455 | * Decode SEEK request | |
1456 | */ | |
1457 | static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, | |
1458 | struct xdr_stream *xdr, | |
18d9cff4 | 1459 | void *data) |
1c6dcbe5 | 1460 | { |
18d9cff4 | 1461 | struct nfs42_seek_res *res = data; |
1c6dcbe5 AS |
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 | } | |
be3a5d23 TM |
1478 | |
1479 | /* | |
1480 | * Decode LAYOUTSTATS request | |
1481 | */ | |
1482 | static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, | |
1483 | struct xdr_stream *xdr, | |
18d9cff4 | 1484 | void *data) |
be3a5d23 | 1485 | { |
18d9cff4 | 1486 | struct nfs42_layoutstat_res *res = data; |
be3a5d23 TM |
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++) { | |
19cf6335 | 1501 | status = decode_layoutstats(xdr); |
be3a5d23 TM |
1502 | if (status) |
1503 | goto out; | |
1504 | } | |
1505 | out: | |
1506 | res->rpc_status = status; | |
1507 | return status; | |
1508 | } | |
1509 | ||
36022770 PT |
1510 | /* |
1511 | * Decode CLONE request | |
1512 | */ | |
1513 | static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, | |
1514 | struct xdr_stream *xdr, | |
18d9cff4 | 1515 | void *data) |
36022770 | 1516 | { |
18d9cff4 | 1517 | struct nfs42_clone_res *res = data; |
36022770 PT |
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; | |
d3c45824 | 1539 | decode_getfattr(xdr, res->dst_fattr, res->server); |
36022770 PT |
1540 | out: |
1541 | res->rpc_status = status; | |
1542 | return status; | |
1543 | } | |
1544 | ||
3eb86093 TM |
1545 | /* |
1546 | * Decode LAYOUTERROR request | |
1547 | */ | |
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 | ||
d5940973 AS |
1571 | /* |
1572 | * Decode SETXATTR request | |
1573 | */ | |
3e1f0212 FL |
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; | |
3e1f0212 | 1590 | status = decode_setxattr(xdr, &res->cinfo); |
86e2e1f6 AS |
1591 | if (status) |
1592 | goto out; | |
1593 | status = decode_getfattr(xdr, res->fattr, res->server); | |
3e1f0212 FL |
1594 | out: |
1595 | return status; | |
1596 | } | |
1597 | ||
d5940973 AS |
1598 | /* |
1599 | * Decode GETXATTR request | |
1600 | */ | |
3e1f0212 FL |
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 | ||
d5940973 AS |
1622 | /* |
1623 | * Decode LISTXATTR request | |
1624 | */ | |
3e1f0212 FL |
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 | ||
0ae4c3e8 | 1632 | xdr_set_scratch_page(xdr, res->scratch); |
3e1f0212 FL |
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 | ||
d5940973 AS |
1648 | /* |
1649 | * Decode REMOVEXATTR request | |
1650 | */ | |
3e1f0212 FL |
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 | } | |
1c6dcbe5 | 1672 | #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ |