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