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