Loading...
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#define encode_fallocate_maxsz (encode_stateid_maxsz + \
11 2 /* offset */ + \
12 2 /* length */)
13#define NFS42_WRITE_RES_SIZE (1 /* wr_callback_id size */ +\
14 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
15 2 /* wr_count */ + \
16 1 /* wr_committed */ + \
17 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
18#define encode_allocate_maxsz (op_encode_hdr_maxsz + \
19 encode_fallocate_maxsz)
20#define decode_allocate_maxsz (op_decode_hdr_maxsz)
21#define encode_copy_maxsz (op_encode_hdr_maxsz + \
22 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
23 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
24 2 + 2 + 2 + 1 + 1 + 1 +\
25 1 + /* One cnr_source_server */\
26 1 + /* nl4_type */ \
27 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
28#define decode_copy_maxsz (op_decode_hdr_maxsz + \
29 NFS42_WRITE_RES_SIZE + \
30 1 /* cr_consecutive */ + \
31 1 /* cr_synchronous */)
32#define encode_offload_cancel_maxsz (op_encode_hdr_maxsz + \
33 XDR_QUADLEN(NFS4_STATEID_SIZE))
34#define decode_offload_cancel_maxsz (op_decode_hdr_maxsz)
35#define encode_copy_notify_maxsz (op_encode_hdr_maxsz + \
36 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
37 1 + /* nl4_type */ \
38 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
39#define decode_copy_notify_maxsz (op_decode_hdr_maxsz + \
40 3 + /* cnr_lease_time */\
41 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
42 1 + /* Support 1 cnr_source_server */\
43 1 + /* nl4_type */ \
44 1 + XDR_QUADLEN(NFS4_OPAQUE_LIMIT))
45#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
46 encode_fallocate_maxsz)
47#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
48#define encode_seek_maxsz (op_encode_hdr_maxsz + \
49 encode_stateid_maxsz + \
50 2 /* offset */ + \
51 1 /* whence */)
52#define decode_seek_maxsz (op_decode_hdr_maxsz + \
53 1 /* eof */ + \
54 1 /* whence */ + \
55 2 /* offset */ + \
56 2 /* length */)
57#define encode_io_info_maxsz 4
58#define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \
59 2 /* offset */ + \
60 2 /* length */ + \
61 encode_stateid_maxsz + \
62 encode_io_info_maxsz + \
63 encode_io_info_maxsz + \
64 1 /* opaque devaddr4 length */ + \
65 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
66#define decode_layoutstats_maxsz (op_decode_hdr_maxsz)
67#define encode_device_error_maxsz (XDR_QUADLEN(NFS4_DEVICEID4_SIZE) + \
68 1 /* status */ + 1 /* opnum */)
69#define encode_layouterror_maxsz (op_decode_hdr_maxsz + \
70 2 /* offset */ + \
71 2 /* length */ + \
72 encode_stateid_maxsz + \
73 1 /* Array size */ + \
74 encode_device_error_maxsz)
75#define decode_layouterror_maxsz (op_decode_hdr_maxsz)
76#define encode_clone_maxsz (encode_stateid_maxsz + \
77 encode_stateid_maxsz + \
78 2 /* src offset */ + \
79 2 /* dst offset */ + \
80 2 /* count */)
81#define decode_clone_maxsz (op_decode_hdr_maxsz)
82
83#define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \
84 encode_sequence_maxsz + \
85 encode_putfh_maxsz + \
86 encode_allocate_maxsz + \
87 encode_getattr_maxsz)
88#define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \
89 decode_sequence_maxsz + \
90 decode_putfh_maxsz + \
91 decode_allocate_maxsz + \
92 decode_getattr_maxsz)
93#define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \
94 encode_sequence_maxsz + \
95 encode_putfh_maxsz + \
96 encode_savefh_maxsz + \
97 encode_putfh_maxsz + \
98 encode_copy_maxsz + \
99 encode_commit_maxsz)
100#define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \
101 decode_sequence_maxsz + \
102 decode_putfh_maxsz + \
103 decode_savefh_maxsz + \
104 decode_putfh_maxsz + \
105 decode_copy_maxsz + \
106 decode_commit_maxsz)
107#define NFS4_enc_offload_cancel_sz (compound_encode_hdr_maxsz + \
108 encode_sequence_maxsz + \
109 encode_putfh_maxsz + \
110 encode_offload_cancel_maxsz)
111#define NFS4_dec_offload_cancel_sz (compound_decode_hdr_maxsz + \
112 decode_sequence_maxsz + \
113 decode_putfh_maxsz + \
114 decode_offload_cancel_maxsz)
115#define NFS4_enc_copy_notify_sz (compound_encode_hdr_maxsz + \
116 encode_putfh_maxsz + \
117 encode_copy_notify_maxsz)
118#define NFS4_dec_copy_notify_sz (compound_decode_hdr_maxsz + \
119 decode_putfh_maxsz + \
120 decode_copy_notify_maxsz)
121#define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \
122 encode_sequence_maxsz + \
123 encode_putfh_maxsz + \
124 encode_deallocate_maxsz + \
125 encode_getattr_maxsz)
126#define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \
127 decode_sequence_maxsz + \
128 decode_putfh_maxsz + \
129 decode_deallocate_maxsz + \
130 decode_getattr_maxsz)
131#define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
132 encode_sequence_maxsz + \
133 encode_putfh_maxsz + \
134 encode_seek_maxsz)
135#define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \
136 decode_sequence_maxsz + \
137 decode_putfh_maxsz + \
138 decode_seek_maxsz)
139#define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \
140 encode_sequence_maxsz + \
141 encode_putfh_maxsz + \
142 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
143#define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \
144 decode_sequence_maxsz + \
145 decode_putfh_maxsz + \
146 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
147#define NFS4_enc_layouterror_sz (compound_encode_hdr_maxsz + \
148 encode_sequence_maxsz + \
149 encode_putfh_maxsz + \
150 NFS42_LAYOUTERROR_MAX * \
151 encode_layouterror_maxsz)
152#define NFS4_dec_layouterror_sz (compound_decode_hdr_maxsz + \
153 decode_sequence_maxsz + \
154 decode_putfh_maxsz + \
155 NFS42_LAYOUTERROR_MAX * \
156 decode_layouterror_maxsz)
157#define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \
158 encode_sequence_maxsz + \
159 encode_putfh_maxsz + \
160 encode_savefh_maxsz + \
161 encode_putfh_maxsz + \
162 encode_clone_maxsz + \
163 encode_getattr_maxsz)
164#define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \
165 decode_sequence_maxsz + \
166 decode_putfh_maxsz + \
167 decode_savefh_maxsz + \
168 decode_putfh_maxsz + \
169 decode_clone_maxsz + \
170 decode_getattr_maxsz)
171
172/* Not limited by NFS itself, limited by the generic xattr code */
173#define nfs4_xattr_name_maxsz XDR_QUADLEN(XATTR_NAME_MAX)
174
175#define encode_getxattr_maxsz (op_encode_hdr_maxsz + 1 + \
176 nfs4_xattr_name_maxsz)
177#define decode_getxattr_maxsz (op_decode_hdr_maxsz + 1 + 1)
178#define encode_setxattr_maxsz (op_encode_hdr_maxsz + \
179 1 + nfs4_xattr_name_maxsz + 1)
180#define decode_setxattr_maxsz (op_decode_hdr_maxsz + decode_change_info_maxsz)
181#define encode_listxattrs_maxsz (op_encode_hdr_maxsz + 2 + 1)
182#define decode_listxattrs_maxsz (op_decode_hdr_maxsz + 2 + 1 + 1)
183#define encode_removexattr_maxsz (op_encode_hdr_maxsz + 1 + \
184 nfs4_xattr_name_maxsz)
185#define decode_removexattr_maxsz (op_decode_hdr_maxsz + \
186 decode_change_info_maxsz)
187
188#define NFS4_enc_getxattr_sz (compound_encode_hdr_maxsz + \
189 encode_sequence_maxsz + \
190 encode_putfh_maxsz + \
191 encode_getxattr_maxsz)
192#define NFS4_dec_getxattr_sz (compound_decode_hdr_maxsz + \
193 decode_sequence_maxsz + \
194 decode_putfh_maxsz + \
195 decode_getxattr_maxsz)
196#define NFS4_enc_setxattr_sz (compound_encode_hdr_maxsz + \
197 encode_sequence_maxsz + \
198 encode_putfh_maxsz + \
199 encode_setxattr_maxsz)
200#define NFS4_dec_setxattr_sz (compound_decode_hdr_maxsz + \
201 decode_sequence_maxsz + \
202 decode_putfh_maxsz + \
203 decode_setxattr_maxsz)
204#define NFS4_enc_listxattrs_sz (compound_encode_hdr_maxsz + \
205 encode_sequence_maxsz + \
206 encode_putfh_maxsz + \
207 encode_listxattrs_maxsz)
208#define NFS4_dec_listxattrs_sz (compound_decode_hdr_maxsz + \
209 decode_sequence_maxsz + \
210 decode_putfh_maxsz + \
211 decode_listxattrs_maxsz)
212#define NFS4_enc_removexattr_sz (compound_encode_hdr_maxsz + \
213 encode_sequence_maxsz + \
214 encode_putfh_maxsz + \
215 encode_removexattr_maxsz)
216#define NFS4_dec_removexattr_sz (compound_decode_hdr_maxsz + \
217 decode_sequence_maxsz + \
218 decode_putfh_maxsz + \
219 decode_removexattr_maxsz)
220
221/*
222 * These values specify the maximum amount of data that is not
223 * associated with the extended attribute name or extended
224 * attribute list in the SETXATTR, GETXATTR and LISTXATTR
225 * respectively.
226 */
227const u32 nfs42_maxsetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
228 compound_encode_hdr_maxsz +
229 encode_sequence_maxsz +
230 encode_putfh_maxsz + 1 +
231 nfs4_xattr_name_maxsz)
232 * XDR_UNIT);
233
234const u32 nfs42_maxgetxattr_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
235 compound_decode_hdr_maxsz +
236 decode_sequence_maxsz +
237 decode_putfh_maxsz + 1) * XDR_UNIT);
238
239const u32 nfs42_maxlistxattrs_overhead = ((RPC_MAX_HEADER_WITH_AUTH +
240 compound_decode_hdr_maxsz +
241 decode_sequence_maxsz +
242 decode_putfh_maxsz + 3) * XDR_UNIT);
243
244static void encode_fallocate(struct xdr_stream *xdr,
245 const struct nfs42_falloc_args *args)
246{
247 encode_nfs4_stateid(xdr, &args->falloc_stateid);
248 encode_uint64(xdr, args->falloc_offset);
249 encode_uint64(xdr, args->falloc_length);
250}
251
252static void encode_allocate(struct xdr_stream *xdr,
253 const struct nfs42_falloc_args *args,
254 struct compound_hdr *hdr)
255{
256 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
257 encode_fallocate(xdr, args);
258}
259
260static void encode_nl4_server(struct xdr_stream *xdr,
261 const struct nl4_server *ns)
262{
263 encode_uint32(xdr, ns->nl4_type);
264 switch (ns->nl4_type) {
265 case NL4_NAME:
266 case NL4_URL:
267 encode_string(xdr, ns->u.nl4_str_sz, ns->u.nl4_str);
268 break;
269 case NL4_NETADDR:
270 encode_string(xdr, ns->u.nl4_addr.netid_len,
271 ns->u.nl4_addr.netid);
272 encode_string(xdr, ns->u.nl4_addr.addr_len,
273 ns->u.nl4_addr.addr);
274 break;
275 default:
276 WARN_ON_ONCE(1);
277 }
278}
279
280static void encode_copy(struct xdr_stream *xdr,
281 const struct nfs42_copy_args *args,
282 struct compound_hdr *hdr)
283{
284 encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
285 encode_nfs4_stateid(xdr, &args->src_stateid);
286 encode_nfs4_stateid(xdr, &args->dst_stateid);
287
288 encode_uint64(xdr, args->src_pos);
289 encode_uint64(xdr, args->dst_pos);
290 encode_uint64(xdr, args->count);
291
292 encode_uint32(xdr, 1); /* consecutive = true */
293 encode_uint32(xdr, args->sync);
294 if (args->cp_src == NULL) { /* intra-ssc */
295 encode_uint32(xdr, 0); /* no src server list */
296 return;
297 }
298 encode_uint32(xdr, 1); /* supporting 1 server */
299 encode_nl4_server(xdr, args->cp_src);
300}
301
302static void encode_offload_cancel(struct xdr_stream *xdr,
303 const struct nfs42_offload_status_args *args,
304 struct compound_hdr *hdr)
305{
306 encode_op_hdr(xdr, OP_OFFLOAD_CANCEL, decode_offload_cancel_maxsz, hdr);
307 encode_nfs4_stateid(xdr, &args->osa_stateid);
308}
309
310static void encode_copy_notify(struct xdr_stream *xdr,
311 const struct nfs42_copy_notify_args *args,
312 struct compound_hdr *hdr)
313{
314 encode_op_hdr(xdr, OP_COPY_NOTIFY, decode_copy_notify_maxsz, hdr);
315 encode_nfs4_stateid(xdr, &args->cna_src_stateid);
316 encode_nl4_server(xdr, &args->cna_dst);
317}
318
319static void encode_deallocate(struct xdr_stream *xdr,
320 const struct nfs42_falloc_args *args,
321 struct compound_hdr *hdr)
322{
323 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
324 encode_fallocate(xdr, args);
325}
326
327static void encode_seek(struct xdr_stream *xdr,
328 const struct nfs42_seek_args *args,
329 struct compound_hdr *hdr)
330{
331 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
332 encode_nfs4_stateid(xdr, &args->sa_stateid);
333 encode_uint64(xdr, args->sa_offset);
334 encode_uint32(xdr, args->sa_what);
335}
336
337static void encode_layoutstats(struct xdr_stream *xdr,
338 const struct nfs42_layoutstat_args *args,
339 struct nfs42_layoutstat_devinfo *devinfo,
340 struct compound_hdr *hdr)
341{
342 __be32 *p;
343
344 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
345 p = reserve_space(xdr, 8 + 8);
346 p = xdr_encode_hyper(p, devinfo->offset);
347 p = xdr_encode_hyper(p, devinfo->length);
348 encode_nfs4_stateid(xdr, &args->stateid);
349 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
350 p = xdr_encode_hyper(p, devinfo->read_count);
351 p = xdr_encode_hyper(p, devinfo->read_bytes);
352 p = xdr_encode_hyper(p, devinfo->write_count);
353 p = xdr_encode_hyper(p, devinfo->write_bytes);
354 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
355 NFS4_DEVICEID4_SIZE);
356 /* Encode layoutupdate4 */
357 *p++ = cpu_to_be32(devinfo->layout_type);
358 if (devinfo->ld_private.ops)
359 devinfo->ld_private.ops->encode(xdr, args,
360 &devinfo->ld_private);
361 else
362 encode_uint32(xdr, 0);
363}
364
365static void encode_clone(struct xdr_stream *xdr,
366 const struct nfs42_clone_args *args,
367 struct compound_hdr *hdr)
368{
369 __be32 *p;
370
371 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
372 encode_nfs4_stateid(xdr, &args->src_stateid);
373 encode_nfs4_stateid(xdr, &args->dst_stateid);
374 p = reserve_space(xdr, 3*8);
375 p = xdr_encode_hyper(p, args->src_offset);
376 p = xdr_encode_hyper(p, args->dst_offset);
377 xdr_encode_hyper(p, args->count);
378}
379
380static void encode_device_error(struct xdr_stream *xdr,
381 const struct nfs42_device_error *error)
382{
383 __be32 *p;
384
385 p = reserve_space(xdr, NFS4_DEVICEID4_SIZE + 2*4);
386 p = xdr_encode_opaque_fixed(p, error->dev_id.data,
387 NFS4_DEVICEID4_SIZE);
388 *p++ = cpu_to_be32(error->status);
389 *p = cpu_to_be32(error->opnum);
390}
391
392static void encode_layouterror(struct xdr_stream *xdr,
393 const struct nfs42_layout_error *args,
394 struct compound_hdr *hdr)
395{
396 __be32 *p;
397
398 encode_op_hdr(xdr, OP_LAYOUTERROR, decode_layouterror_maxsz, hdr);
399 p = reserve_space(xdr, 8 + 8);
400 p = xdr_encode_hyper(p, args->offset);
401 p = xdr_encode_hyper(p, args->length);
402 encode_nfs4_stateid(xdr, &args->stateid);
403 p = reserve_space(xdr, 4);
404 *p = cpu_to_be32(1);
405 encode_device_error(xdr, &args->errors[0]);
406}
407
408static void encode_setxattr(struct xdr_stream *xdr,
409 const struct nfs42_setxattrargs *arg,
410 struct compound_hdr *hdr)
411{
412 __be32 *p;
413
414 BUILD_BUG_ON(XATTR_CREATE != SETXATTR4_CREATE);
415 BUILD_BUG_ON(XATTR_REPLACE != SETXATTR4_REPLACE);
416
417 encode_op_hdr(xdr, OP_SETXATTR, decode_setxattr_maxsz, hdr);
418 p = reserve_space(xdr, 4);
419 *p = cpu_to_be32(arg->xattr_flags);
420 encode_string(xdr, strlen(arg->xattr_name), arg->xattr_name);
421 p = reserve_space(xdr, 4);
422 *p = cpu_to_be32(arg->xattr_len);
423 if (arg->xattr_len)
424 xdr_write_pages(xdr, arg->xattr_pages, 0, arg->xattr_len);
425}
426
427static int decode_setxattr(struct xdr_stream *xdr,
428 struct nfs4_change_info *cinfo)
429{
430 int status;
431
432 status = decode_op_hdr(xdr, OP_SETXATTR);
433 if (status)
434 goto out;
435 status = decode_change_info(xdr, cinfo);
436out:
437 return status;
438}
439
440
441static void encode_getxattr(struct xdr_stream *xdr, const char *name,
442 struct compound_hdr *hdr)
443{
444 encode_op_hdr(xdr, OP_GETXATTR, decode_getxattr_maxsz, hdr);
445 encode_string(xdr, strlen(name), name);
446}
447
448static int decode_getxattr(struct xdr_stream *xdr,
449 struct nfs42_getxattrres *res,
450 struct rpc_rqst *req)
451{
452 int status;
453 __be32 *p;
454 u32 len, rdlen;
455
456 status = decode_op_hdr(xdr, OP_GETXATTR);
457 if (status)
458 return status;
459
460 p = xdr_inline_decode(xdr, 4);
461 if (unlikely(!p))
462 return -EIO;
463
464 len = be32_to_cpup(p);
465 if (len > req->rq_rcv_buf.page_len)
466 return -ERANGE;
467
468 res->xattr_len = len;
469
470 if (len > 0) {
471 rdlen = xdr_read_pages(xdr, len);
472 if (rdlen < len)
473 return -EIO;
474 }
475
476 return 0;
477}
478
479static void encode_removexattr(struct xdr_stream *xdr, const char *name,
480 struct compound_hdr *hdr)
481{
482 encode_op_hdr(xdr, OP_REMOVEXATTR, decode_removexattr_maxsz, hdr);
483 encode_string(xdr, strlen(name), name);
484}
485
486
487static int decode_removexattr(struct xdr_stream *xdr,
488 struct nfs4_change_info *cinfo)
489{
490 int status;
491
492 status = decode_op_hdr(xdr, OP_REMOVEXATTR);
493 if (status)
494 goto out;
495
496 status = decode_change_info(xdr, cinfo);
497out:
498 return status;
499}
500
501static void encode_listxattrs(struct xdr_stream *xdr,
502 const struct nfs42_listxattrsargs *arg,
503 struct compound_hdr *hdr)
504{
505 __be32 *p;
506
507 encode_op_hdr(xdr, OP_LISTXATTRS, decode_listxattrs_maxsz + 1, hdr);
508
509 p = reserve_space(xdr, 12);
510 if (unlikely(!p))
511 return;
512
513 p = xdr_encode_hyper(p, arg->cookie);
514 /*
515 * RFC 8276 says to specify the full max length of the LISTXATTRS
516 * XDR reply. Count is set to the XDR length of the names array
517 * plus the EOF marker. So, add the cookie and the names count.
518 */
519 *p = cpu_to_be32(arg->count + 8 + 4);
520}
521
522static int decode_listxattrs(struct xdr_stream *xdr,
523 struct nfs42_listxattrsres *res)
524{
525 int status;
526 __be32 *p;
527 u32 count, len, ulen;
528 size_t left, copied;
529 char *buf;
530
531 status = decode_op_hdr(xdr, OP_LISTXATTRS);
532 if (status) {
533 /*
534 * Special case: for LISTXATTRS, NFS4ERR_TOOSMALL
535 * should be translated to ERANGE.
536 */
537 if (status == -ETOOSMALL)
538 status = -ERANGE;
539 goto out;
540 }
541
542 p = xdr_inline_decode(xdr, 8);
543 if (unlikely(!p))
544 return -EIO;
545
546 xdr_decode_hyper(p, &res->cookie);
547
548 p = xdr_inline_decode(xdr, 4);
549 if (unlikely(!p))
550 return -EIO;
551
552 left = res->xattr_len;
553 buf = res->xattr_buf;
554
555 count = be32_to_cpup(p);
556 copied = 0;
557
558 /*
559 * We have asked for enough room to encode the maximum number
560 * of possible attribute names, so everything should fit.
561 *
562 * But, don't rely on that assumption. Just decode entries
563 * until they don't fit anymore, just in case the server did
564 * something odd.
565 */
566 while (count--) {
567 p = xdr_inline_decode(xdr, 4);
568 if (unlikely(!p))
569 return -EIO;
570
571 len = be32_to_cpup(p);
572 if (len > (XATTR_NAME_MAX - XATTR_USER_PREFIX_LEN)) {
573 status = -ERANGE;
574 goto out;
575 }
576
577 p = xdr_inline_decode(xdr, len);
578 if (unlikely(!p))
579 return -EIO;
580
581 ulen = len + XATTR_USER_PREFIX_LEN + 1;
582 if (buf) {
583 if (ulen > left) {
584 status = -ERANGE;
585 goto out;
586 }
587
588 memcpy(buf, XATTR_USER_PREFIX, XATTR_USER_PREFIX_LEN);
589 memcpy(buf + XATTR_USER_PREFIX_LEN, p, len);
590
591 buf[ulen - 1] = 0;
592 buf += ulen;
593 left -= ulen;
594 }
595 copied += ulen;
596 }
597
598 p = xdr_inline_decode(xdr, 4);
599 if (unlikely(!p))
600 return -EIO;
601
602 res->eof = be32_to_cpup(p);
603 res->copied = copied;
604
605out:
606 if (status == -ERANGE && res->xattr_len == XATTR_LIST_MAX)
607 status = -E2BIG;
608
609 return status;
610}
611
612/*
613 * Encode ALLOCATE request
614 */
615static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
616 struct xdr_stream *xdr,
617 const void *data)
618{
619 const struct nfs42_falloc_args *args = data;
620 struct compound_hdr hdr = {
621 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
622 };
623
624 encode_compound_hdr(xdr, req, &hdr);
625 encode_sequence(xdr, &args->seq_args, &hdr);
626 encode_putfh(xdr, args->falloc_fh, &hdr);
627 encode_allocate(xdr, args, &hdr);
628 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
629 encode_nops(&hdr);
630}
631
632static void encode_copy_commit(struct xdr_stream *xdr,
633 const struct nfs42_copy_args *args,
634 struct compound_hdr *hdr)
635{
636 __be32 *p;
637
638 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr);
639 p = reserve_space(xdr, 12);
640 p = xdr_encode_hyper(p, args->dst_pos);
641 *p = cpu_to_be32(args->count);
642}
643
644/*
645 * Encode COPY request
646 */
647static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
648 struct xdr_stream *xdr,
649 const void *data)
650{
651 const struct nfs42_copy_args *args = data;
652 struct compound_hdr hdr = {
653 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
654 };
655
656 encode_compound_hdr(xdr, req, &hdr);
657 encode_sequence(xdr, &args->seq_args, &hdr);
658 encode_putfh(xdr, args->src_fh, &hdr);
659 encode_savefh(xdr, &hdr);
660 encode_putfh(xdr, args->dst_fh, &hdr);
661 encode_copy(xdr, args, &hdr);
662 if (args->sync)
663 encode_copy_commit(xdr, args, &hdr);
664 encode_nops(&hdr);
665}
666
667/*
668 * Encode OFFLOAD_CANEL request
669 */
670static void nfs4_xdr_enc_offload_cancel(struct rpc_rqst *req,
671 struct xdr_stream *xdr,
672 const void *data)
673{
674 const struct nfs42_offload_status_args *args = data;
675 struct compound_hdr hdr = {
676 .minorversion = nfs4_xdr_minorversion(&args->osa_seq_args),
677 };
678
679 encode_compound_hdr(xdr, req, &hdr);
680 encode_sequence(xdr, &args->osa_seq_args, &hdr);
681 encode_putfh(xdr, args->osa_src_fh, &hdr);
682 encode_offload_cancel(xdr, args, &hdr);
683 encode_nops(&hdr);
684}
685
686/*
687 * Encode COPY_NOTIFY request
688 */
689static void nfs4_xdr_enc_copy_notify(struct rpc_rqst *req,
690 struct xdr_stream *xdr,
691 const void *data)
692{
693 const struct nfs42_copy_notify_args *args = data;
694 struct compound_hdr hdr = {
695 .minorversion = nfs4_xdr_minorversion(&args->cna_seq_args),
696 };
697
698 encode_compound_hdr(xdr, req, &hdr);
699 encode_sequence(xdr, &args->cna_seq_args, &hdr);
700 encode_putfh(xdr, args->cna_src_fh, &hdr);
701 encode_copy_notify(xdr, args, &hdr);
702 encode_nops(&hdr);
703}
704
705/*
706 * Encode DEALLOCATE request
707 */
708static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
709 struct xdr_stream *xdr,
710 const void *data)
711{
712 const struct nfs42_falloc_args *args = data;
713 struct compound_hdr hdr = {
714 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
715 };
716
717 encode_compound_hdr(xdr, req, &hdr);
718 encode_sequence(xdr, &args->seq_args, &hdr);
719 encode_putfh(xdr, args->falloc_fh, &hdr);
720 encode_deallocate(xdr, args, &hdr);
721 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
722 encode_nops(&hdr);
723}
724
725/*
726 * Encode SEEK request
727 */
728static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
729 struct xdr_stream *xdr,
730 const void *data)
731{
732 const struct nfs42_seek_args *args = data;
733 struct compound_hdr hdr = {
734 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
735 };
736
737 encode_compound_hdr(xdr, req, &hdr);
738 encode_sequence(xdr, &args->seq_args, &hdr);
739 encode_putfh(xdr, args->sa_fh, &hdr);
740 encode_seek(xdr, args, &hdr);
741 encode_nops(&hdr);
742}
743
744/*
745 * Encode LAYOUTSTATS request
746 */
747static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
748 struct xdr_stream *xdr,
749 const void *data)
750{
751 const struct nfs42_layoutstat_args *args = data;
752 int i;
753
754 struct compound_hdr hdr = {
755 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
756 };
757
758 encode_compound_hdr(xdr, req, &hdr);
759 encode_sequence(xdr, &args->seq_args, &hdr);
760 encode_putfh(xdr, args->fh, &hdr);
761 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
762 for (i = 0; i < args->num_dev; i++)
763 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
764 encode_nops(&hdr);
765}
766
767/*
768 * Encode CLONE request
769 */
770static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
771 struct xdr_stream *xdr,
772 const void *data)
773{
774 const struct nfs42_clone_args *args = data;
775 struct compound_hdr hdr = {
776 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
777 };
778
779 encode_compound_hdr(xdr, req, &hdr);
780 encode_sequence(xdr, &args->seq_args, &hdr);
781 encode_putfh(xdr, args->src_fh, &hdr);
782 encode_savefh(xdr, &hdr);
783 encode_putfh(xdr, args->dst_fh, &hdr);
784 encode_clone(xdr, args, &hdr);
785 encode_getfattr(xdr, args->dst_bitmask, &hdr);
786 encode_nops(&hdr);
787}
788
789/*
790 * Encode LAYOUTERROR request
791 */
792static void nfs4_xdr_enc_layouterror(struct rpc_rqst *req,
793 struct xdr_stream *xdr,
794 const void *data)
795{
796 const struct nfs42_layouterror_args *args = data;
797 struct compound_hdr hdr = {
798 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
799 };
800 int i;
801
802 encode_compound_hdr(xdr, req, &hdr);
803 encode_sequence(xdr, &args->seq_args, &hdr);
804 encode_putfh(xdr, NFS_FH(args->inode), &hdr);
805 for (i = 0; i < args->num_errors; i++)
806 encode_layouterror(xdr, &args->errors[i], &hdr);
807 encode_nops(&hdr);
808}
809
810static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
811{
812 return decode_op_hdr(xdr, OP_ALLOCATE);
813}
814
815static int decode_write_response(struct xdr_stream *xdr,
816 struct nfs42_write_res *res)
817{
818 __be32 *p;
819 int status, count;
820
821 p = xdr_inline_decode(xdr, 4);
822 if (unlikely(!p))
823 return -EIO;
824 count = be32_to_cpup(p);
825 if (count > 1)
826 return -EREMOTEIO;
827 else if (count == 1) {
828 status = decode_opaque_fixed(xdr, &res->stateid,
829 NFS4_STATEID_SIZE);
830 if (unlikely(status))
831 return -EIO;
832 }
833 p = xdr_inline_decode(xdr, 8 + 4);
834 if (unlikely(!p))
835 return -EIO;
836 p = xdr_decode_hyper(p, &res->count);
837 res->verifier.committed = be32_to_cpup(p);
838 return decode_verifier(xdr, &res->verifier.verifier);
839}
840
841static int decode_nl4_server(struct xdr_stream *xdr, struct nl4_server *ns)
842{
843 struct nfs42_netaddr *naddr;
844 uint32_t dummy;
845 char *dummy_str;
846 __be32 *p;
847 int status;
848
849 /* nl_type */
850 p = xdr_inline_decode(xdr, 4);
851 if (unlikely(!p))
852 return -EIO;
853 ns->nl4_type = be32_to_cpup(p);
854 switch (ns->nl4_type) {
855 case NL4_NAME:
856 case NL4_URL:
857 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
858 if (unlikely(status))
859 return status;
860 if (unlikely(dummy > NFS4_OPAQUE_LIMIT))
861 return -EIO;
862 memcpy(&ns->u.nl4_str, dummy_str, dummy);
863 ns->u.nl4_str_sz = dummy;
864 break;
865 case NL4_NETADDR:
866 naddr = &ns->u.nl4_addr;
867
868 /* netid string */
869 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
870 if (unlikely(status))
871 return status;
872 if (unlikely(dummy > RPCBIND_MAXNETIDLEN))
873 return -EIO;
874 naddr->netid_len = dummy;
875 memcpy(naddr->netid, dummy_str, naddr->netid_len);
876
877 /* uaddr string */
878 status = decode_opaque_inline(xdr, &dummy, &dummy_str);
879 if (unlikely(status))
880 return status;
881 if (unlikely(dummy > RPCBIND_MAXUADDRLEN))
882 return -EIO;
883 naddr->addr_len = dummy;
884 memcpy(naddr->addr, dummy_str, naddr->addr_len);
885 break;
886 default:
887 WARN_ON_ONCE(1);
888 return -EIO;
889 }
890 return 0;
891}
892
893static int decode_copy_requirements(struct xdr_stream *xdr,
894 struct nfs42_copy_res *res) {
895 __be32 *p;
896
897 p = xdr_inline_decode(xdr, 4 + 4);
898 if (unlikely(!p))
899 return -EIO;
900
901 res->consecutive = be32_to_cpup(p++);
902 res->synchronous = be32_to_cpup(p++);
903 return 0;
904}
905
906static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
907{
908 int status;
909
910 status = decode_op_hdr(xdr, OP_COPY);
911 if (status == NFS4ERR_OFFLOAD_NO_REQS) {
912 status = decode_copy_requirements(xdr, res);
913 if (status)
914 return status;
915 return NFS4ERR_OFFLOAD_NO_REQS;
916 } else if (status)
917 return status;
918
919 status = decode_write_response(xdr, &res->write_res);
920 if (status)
921 return status;
922
923 return decode_copy_requirements(xdr, res);
924}
925
926static int decode_offload_cancel(struct xdr_stream *xdr,
927 struct nfs42_offload_status_res *res)
928{
929 return decode_op_hdr(xdr, OP_OFFLOAD_CANCEL);
930}
931
932static int decode_copy_notify(struct xdr_stream *xdr,
933 struct nfs42_copy_notify_res *res)
934{
935 __be32 *p;
936 int status, count;
937
938 status = decode_op_hdr(xdr, OP_COPY_NOTIFY);
939 if (status)
940 return status;
941 /* cnr_lease_time */
942 p = xdr_inline_decode(xdr, 12);
943 if (unlikely(!p))
944 return -EIO;
945 p = xdr_decode_hyper(p, &res->cnr_lease_time.seconds);
946 res->cnr_lease_time.nseconds = be32_to_cpup(p);
947
948 status = decode_opaque_fixed(xdr, &res->cnr_stateid, NFS4_STATEID_SIZE);
949 if (unlikely(status))
950 return -EIO;
951
952 /* number of source addresses */
953 p = xdr_inline_decode(xdr, 4);
954 if (unlikely(!p))
955 return -EIO;
956
957 count = be32_to_cpup(p);
958 if (count > 1)
959 pr_warn("NFS: %s: nsvr %d > Supported. Use first servers\n",
960 __func__, count);
961
962 status = decode_nl4_server(xdr, &res->cnr_src);
963 if (unlikely(status))
964 return -EIO;
965 return 0;
966}
967
968static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
969{
970 return decode_op_hdr(xdr, OP_DEALLOCATE);
971}
972
973static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
974{
975 int status;
976 __be32 *p;
977
978 status = decode_op_hdr(xdr, OP_SEEK);
979 if (status)
980 return status;
981
982 p = xdr_inline_decode(xdr, 4 + 8);
983 if (unlikely(!p))
984 return -EIO;
985
986 res->sr_eof = be32_to_cpup(p++);
987 p = xdr_decode_hyper(p, &res->sr_offset);
988 return 0;
989}
990
991static int decode_layoutstats(struct xdr_stream *xdr)
992{
993 return decode_op_hdr(xdr, OP_LAYOUTSTATS);
994}
995
996static int decode_clone(struct xdr_stream *xdr)
997{
998 return decode_op_hdr(xdr, OP_CLONE);
999}
1000
1001static int decode_layouterror(struct xdr_stream *xdr)
1002{
1003 return decode_op_hdr(xdr, OP_LAYOUTERROR);
1004}
1005
1006/*
1007 * Decode ALLOCATE request
1008 */
1009static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
1010 struct xdr_stream *xdr,
1011 void *data)
1012{
1013 struct nfs42_falloc_res *res = data;
1014 struct compound_hdr hdr;
1015 int status;
1016
1017 status = decode_compound_hdr(xdr, &hdr);
1018 if (status)
1019 goto out;
1020 status = decode_sequence(xdr, &res->seq_res, rqstp);
1021 if (status)
1022 goto out;
1023 status = decode_putfh(xdr);
1024 if (status)
1025 goto out;
1026 status = decode_allocate(xdr, res);
1027 if (status)
1028 goto out;
1029 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1030out:
1031 return status;
1032}
1033
1034/*
1035 * Decode COPY response
1036 */
1037static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
1038 struct xdr_stream *xdr,
1039 void *data)
1040{
1041 struct nfs42_copy_res *res = data;
1042 struct compound_hdr hdr;
1043 int status;
1044
1045 status = decode_compound_hdr(xdr, &hdr);
1046 if (status)
1047 goto out;
1048 status = decode_sequence(xdr, &res->seq_res, rqstp);
1049 if (status)
1050 goto out;
1051 status = decode_putfh(xdr);
1052 if (status)
1053 goto out;
1054 status = decode_savefh(xdr);
1055 if (status)
1056 goto out;
1057 status = decode_putfh(xdr);
1058 if (status)
1059 goto out;
1060 status = decode_copy(xdr, res);
1061 if (status)
1062 goto out;
1063 if (res->commit_res.verf)
1064 status = decode_commit(xdr, &res->commit_res);
1065out:
1066 return status;
1067}
1068
1069/*
1070 * Decode OFFLOAD_CANCEL response
1071 */
1072static int nfs4_xdr_dec_offload_cancel(struct rpc_rqst *rqstp,
1073 struct xdr_stream *xdr,
1074 void *data)
1075{
1076 struct nfs42_offload_status_res *res = data;
1077 struct compound_hdr hdr;
1078 int status;
1079
1080 status = decode_compound_hdr(xdr, &hdr);
1081 if (status)
1082 goto out;
1083 status = decode_sequence(xdr, &res->osr_seq_res, rqstp);
1084 if (status)
1085 goto out;
1086 status = decode_putfh(xdr);
1087 if (status)
1088 goto out;
1089 status = decode_offload_cancel(xdr, res);
1090
1091out:
1092 return status;
1093}
1094
1095/*
1096 * Decode COPY_NOTIFY response
1097 */
1098static int nfs4_xdr_dec_copy_notify(struct rpc_rqst *rqstp,
1099 struct xdr_stream *xdr,
1100 void *data)
1101{
1102 struct nfs42_copy_notify_res *res = data;
1103 struct compound_hdr hdr;
1104 int status;
1105
1106 status = decode_compound_hdr(xdr, &hdr);
1107 if (status)
1108 goto out;
1109 status = decode_sequence(xdr, &res->cnr_seq_res, rqstp);
1110 if (status)
1111 goto out;
1112 status = decode_putfh(xdr);
1113 if (status)
1114 goto out;
1115 status = decode_copy_notify(xdr, res);
1116
1117out:
1118 return status;
1119}
1120
1121/*
1122 * Decode DEALLOCATE request
1123 */
1124static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
1125 struct xdr_stream *xdr,
1126 void *data)
1127{
1128 struct nfs42_falloc_res *res = data;
1129 struct compound_hdr hdr;
1130 int status;
1131
1132 status = decode_compound_hdr(xdr, &hdr);
1133 if (status)
1134 goto out;
1135 status = decode_sequence(xdr, &res->seq_res, rqstp);
1136 if (status)
1137 goto out;
1138 status = decode_putfh(xdr);
1139 if (status)
1140 goto out;
1141 status = decode_deallocate(xdr, res);
1142 if (status)
1143 goto out;
1144 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
1145out:
1146 return status;
1147}
1148
1149/*
1150 * Decode SEEK request
1151 */
1152static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
1153 struct xdr_stream *xdr,
1154 void *data)
1155{
1156 struct nfs42_seek_res *res = data;
1157 struct compound_hdr hdr;
1158 int status;
1159
1160 status = decode_compound_hdr(xdr, &hdr);
1161 if (status)
1162 goto out;
1163 status = decode_sequence(xdr, &res->seq_res, rqstp);
1164 if (status)
1165 goto out;
1166 status = decode_putfh(xdr);
1167 if (status)
1168 goto out;
1169 status = decode_seek(xdr, res);
1170out:
1171 return status;
1172}
1173
1174/*
1175 * Decode LAYOUTSTATS request
1176 */
1177static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
1178 struct xdr_stream *xdr,
1179 void *data)
1180{
1181 struct nfs42_layoutstat_res *res = data;
1182 struct compound_hdr hdr;
1183 int status, i;
1184
1185 status = decode_compound_hdr(xdr, &hdr);
1186 if (status)
1187 goto out;
1188 status = decode_sequence(xdr, &res->seq_res, rqstp);
1189 if (status)
1190 goto out;
1191 status = decode_putfh(xdr);
1192 if (status)
1193 goto out;
1194 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
1195 for (i = 0; i < res->num_dev; i++) {
1196 status = decode_layoutstats(xdr);
1197 if (status)
1198 goto out;
1199 }
1200out:
1201 res->rpc_status = status;
1202 return status;
1203}
1204
1205/*
1206 * Decode CLONE request
1207 */
1208static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
1209 struct xdr_stream *xdr,
1210 void *data)
1211{
1212 struct nfs42_clone_res *res = data;
1213 struct compound_hdr hdr;
1214 int status;
1215
1216 status = decode_compound_hdr(xdr, &hdr);
1217 if (status)
1218 goto out;
1219 status = decode_sequence(xdr, &res->seq_res, rqstp);
1220 if (status)
1221 goto out;
1222 status = decode_putfh(xdr);
1223 if (status)
1224 goto out;
1225 status = decode_savefh(xdr);
1226 if (status)
1227 goto out;
1228 status = decode_putfh(xdr);
1229 if (status)
1230 goto out;
1231 status = decode_clone(xdr);
1232 if (status)
1233 goto out;
1234 status = decode_getfattr(xdr, res->dst_fattr, res->server);
1235
1236out:
1237 res->rpc_status = status;
1238 return status;
1239}
1240
1241/*
1242 * Decode LAYOUTERROR request
1243 */
1244static int nfs4_xdr_dec_layouterror(struct rpc_rqst *rqstp,
1245 struct xdr_stream *xdr,
1246 void *data)
1247{
1248 struct nfs42_layouterror_res *res = data;
1249 struct compound_hdr hdr;
1250 int status, i;
1251
1252 status = decode_compound_hdr(xdr, &hdr);
1253 if (status)
1254 goto out;
1255 status = decode_sequence(xdr, &res->seq_res, rqstp);
1256 if (status)
1257 goto out;
1258 status = decode_putfh(xdr);
1259
1260 for (i = 0; i < res->num_errors && status == 0; i++)
1261 status = decode_layouterror(xdr);
1262out:
1263 res->rpc_status = status;
1264 return status;
1265}
1266
1267#ifdef CONFIG_NFS_V4_2
1268static void nfs4_xdr_enc_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1269 const void *data)
1270{
1271 const struct nfs42_setxattrargs *args = data;
1272 struct compound_hdr hdr = {
1273 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1274 };
1275
1276 encode_compound_hdr(xdr, req, &hdr);
1277 encode_sequence(xdr, &args->seq_args, &hdr);
1278 encode_putfh(xdr, args->fh, &hdr);
1279 encode_setxattr(xdr, args, &hdr);
1280 encode_nops(&hdr);
1281}
1282
1283static int nfs4_xdr_dec_setxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1284 void *data)
1285{
1286 struct nfs42_setxattrres *res = data;
1287 struct compound_hdr hdr;
1288 int status;
1289
1290 status = decode_compound_hdr(xdr, &hdr);
1291 if (status)
1292 goto out;
1293 status = decode_sequence(xdr, &res->seq_res, req);
1294 if (status)
1295 goto out;
1296 status = decode_putfh(xdr);
1297 if (status)
1298 goto out;
1299
1300 status = decode_setxattr(xdr, &res->cinfo);
1301out:
1302 return status;
1303}
1304
1305static void nfs4_xdr_enc_getxattr(struct rpc_rqst *req, struct xdr_stream *xdr,
1306 const void *data)
1307{
1308 const struct nfs42_getxattrargs *args = data;
1309 struct compound_hdr hdr = {
1310 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1311 };
1312 size_t plen;
1313
1314 encode_compound_hdr(xdr, req, &hdr);
1315 encode_sequence(xdr, &args->seq_args, &hdr);
1316 encode_putfh(xdr, args->fh, &hdr);
1317 encode_getxattr(xdr, args->xattr_name, &hdr);
1318
1319 plen = args->xattr_len ? args->xattr_len : XATTR_SIZE_MAX;
1320
1321 rpc_prepare_reply_pages(req, args->xattr_pages, 0, plen,
1322 hdr.replen);
1323 req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1324
1325 encode_nops(&hdr);
1326}
1327
1328static int nfs4_xdr_dec_getxattr(struct rpc_rqst *rqstp,
1329 struct xdr_stream *xdr, void *data)
1330{
1331 struct nfs42_getxattrres *res = data;
1332 struct compound_hdr hdr;
1333 int status;
1334
1335 status = decode_compound_hdr(xdr, &hdr);
1336 if (status)
1337 goto out;
1338 status = decode_sequence(xdr, &res->seq_res, rqstp);
1339 if (status)
1340 goto out;
1341 status = decode_putfh(xdr);
1342 if (status)
1343 goto out;
1344 status = decode_getxattr(xdr, res, rqstp);
1345out:
1346 return status;
1347}
1348
1349static void nfs4_xdr_enc_listxattrs(struct rpc_rqst *req,
1350 struct xdr_stream *xdr, const void *data)
1351{
1352 const struct nfs42_listxattrsargs *args = data;
1353 struct compound_hdr hdr = {
1354 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1355 };
1356
1357 encode_compound_hdr(xdr, req, &hdr);
1358 encode_sequence(xdr, &args->seq_args, &hdr);
1359 encode_putfh(xdr, args->fh, &hdr);
1360 encode_listxattrs(xdr, args, &hdr);
1361
1362 rpc_prepare_reply_pages(req, args->xattr_pages, 0, args->count,
1363 hdr.replen);
1364 req->rq_rcv_buf.flags |= XDRBUF_SPARSE_PAGES;
1365
1366 encode_nops(&hdr);
1367}
1368
1369static int nfs4_xdr_dec_listxattrs(struct rpc_rqst *rqstp,
1370 struct xdr_stream *xdr, void *data)
1371{
1372 struct nfs42_listxattrsres *res = data;
1373 struct compound_hdr hdr;
1374 int status;
1375
1376 xdr_set_scratch_buffer(xdr, page_address(res->scratch), PAGE_SIZE);
1377
1378 status = decode_compound_hdr(xdr, &hdr);
1379 if (status)
1380 goto out;
1381 status = decode_sequence(xdr, &res->seq_res, rqstp);
1382 if (status)
1383 goto out;
1384 status = decode_putfh(xdr);
1385 if (status)
1386 goto out;
1387 status = decode_listxattrs(xdr, res);
1388out:
1389 return status;
1390}
1391
1392static void nfs4_xdr_enc_removexattr(struct rpc_rqst *req,
1393 struct xdr_stream *xdr, const void *data)
1394{
1395 const struct nfs42_removexattrargs *args = data;
1396 struct compound_hdr hdr = {
1397 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
1398 };
1399
1400 encode_compound_hdr(xdr, req, &hdr);
1401 encode_sequence(xdr, &args->seq_args, &hdr);
1402 encode_putfh(xdr, args->fh, &hdr);
1403 encode_removexattr(xdr, args->xattr_name, &hdr);
1404 encode_nops(&hdr);
1405}
1406
1407static int nfs4_xdr_dec_removexattr(struct rpc_rqst *req,
1408 struct xdr_stream *xdr, void *data)
1409{
1410 struct nfs42_removexattrres *res = data;
1411 struct compound_hdr hdr;
1412 int status;
1413
1414 status = decode_compound_hdr(xdr, &hdr);
1415 if (status)
1416 goto out;
1417 status = decode_sequence(xdr, &res->seq_res, req);
1418 if (status)
1419 goto out;
1420 status = decode_putfh(xdr);
1421 if (status)
1422 goto out;
1423
1424 status = decode_removexattr(xdr, &res->cinfo);
1425out:
1426 return status;
1427}
1428#endif
1429#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */
1/*
2 * Copyright (c) 2014 Anna Schumaker <Anna.Schumaker@Netapp.com>
3 */
4#ifndef __LINUX_FS_NFS_NFS4_2XDR_H
5#define __LINUX_FS_NFS_NFS4_2XDR_H
6
7#include "nfs42.h"
8
9#define encode_fallocate_maxsz (encode_stateid_maxsz + \
10 2 /* offset */ + \
11 2 /* length */)
12#define NFS42_WRITE_RES_SIZE (1 /* wr_callback_id size */ +\
13 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
14 2 /* wr_count */ + \
15 1 /* wr_committed */ + \
16 XDR_QUADLEN(NFS4_VERIFIER_SIZE))
17#define encode_allocate_maxsz (op_encode_hdr_maxsz + \
18 encode_fallocate_maxsz)
19#define decode_allocate_maxsz (op_decode_hdr_maxsz)
20#define encode_copy_maxsz (op_encode_hdr_maxsz + \
21 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
22 XDR_QUADLEN(NFS4_STATEID_SIZE) + \
23 2 + 2 + 2 + 1 + 1 + 1)
24#define decode_copy_maxsz (op_decode_hdr_maxsz + \
25 NFS42_WRITE_RES_SIZE + \
26 1 /* cr_consecutive */ + \
27 1 /* cr_synchronous */)
28#define encode_deallocate_maxsz (op_encode_hdr_maxsz + \
29 encode_fallocate_maxsz)
30#define decode_deallocate_maxsz (op_decode_hdr_maxsz)
31#define encode_seek_maxsz (op_encode_hdr_maxsz + \
32 encode_stateid_maxsz + \
33 2 /* offset */ + \
34 1 /* whence */)
35#define decode_seek_maxsz (op_decode_hdr_maxsz + \
36 1 /* eof */ + \
37 1 /* whence */ + \
38 2 /* offset */ + \
39 2 /* length */)
40#define encode_io_info_maxsz 4
41#define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \
42 2 /* offset */ + \
43 2 /* length */ + \
44 encode_stateid_maxsz + \
45 encode_io_info_maxsz + \
46 encode_io_info_maxsz + \
47 1 /* opaque devaddr4 length */ + \
48 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE))
49#define decode_layoutstats_maxsz (op_decode_hdr_maxsz)
50#define encode_clone_maxsz (encode_stateid_maxsz + \
51 encode_stateid_maxsz + \
52 2 /* src offset */ + \
53 2 /* dst offset */ + \
54 2 /* count */)
55#define decode_clone_maxsz (op_decode_hdr_maxsz)
56
57#define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \
58 encode_putfh_maxsz + \
59 encode_allocate_maxsz + \
60 encode_getattr_maxsz)
61#define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \
62 decode_putfh_maxsz + \
63 decode_allocate_maxsz + \
64 decode_getattr_maxsz)
65#define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \
66 encode_putfh_maxsz + \
67 encode_savefh_maxsz + \
68 encode_putfh_maxsz + \
69 encode_copy_maxsz)
70#define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \
71 decode_putfh_maxsz + \
72 decode_savefh_maxsz + \
73 decode_putfh_maxsz + \
74 decode_copy_maxsz)
75#define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \
76 encode_putfh_maxsz + \
77 encode_deallocate_maxsz + \
78 encode_getattr_maxsz)
79#define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \
80 decode_putfh_maxsz + \
81 decode_deallocate_maxsz + \
82 decode_getattr_maxsz)
83#define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \
84 encode_putfh_maxsz + \
85 encode_seek_maxsz)
86#define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \
87 decode_putfh_maxsz + \
88 decode_seek_maxsz)
89#define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \
90 encode_sequence_maxsz + \
91 encode_putfh_maxsz + \
92 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz)
93#define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \
94 decode_sequence_maxsz + \
95 decode_putfh_maxsz + \
96 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz)
97#define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \
98 encode_sequence_maxsz + \
99 encode_putfh_maxsz + \
100 encode_savefh_maxsz + \
101 encode_putfh_maxsz + \
102 encode_clone_maxsz + \
103 encode_getattr_maxsz)
104#define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \
105 decode_sequence_maxsz + \
106 decode_putfh_maxsz + \
107 decode_savefh_maxsz + \
108 decode_putfh_maxsz + \
109 decode_clone_maxsz + \
110 decode_getattr_maxsz)
111
112static void encode_fallocate(struct xdr_stream *xdr,
113 struct nfs42_falloc_args *args)
114{
115 encode_nfs4_stateid(xdr, &args->falloc_stateid);
116 encode_uint64(xdr, args->falloc_offset);
117 encode_uint64(xdr, args->falloc_length);
118}
119
120static void encode_allocate(struct xdr_stream *xdr,
121 struct nfs42_falloc_args *args,
122 struct compound_hdr *hdr)
123{
124 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr);
125 encode_fallocate(xdr, args);
126}
127
128static void encode_copy(struct xdr_stream *xdr,
129 struct nfs42_copy_args *args,
130 struct compound_hdr *hdr)
131{
132 encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr);
133 encode_nfs4_stateid(xdr, &args->src_stateid);
134 encode_nfs4_stateid(xdr, &args->dst_stateid);
135
136 encode_uint64(xdr, args->src_pos);
137 encode_uint64(xdr, args->dst_pos);
138 encode_uint64(xdr, args->count);
139
140 encode_uint32(xdr, 1); /* consecutive = true */
141 encode_uint32(xdr, 1); /* synchronous = true */
142 encode_uint32(xdr, 0); /* src server list */
143}
144
145static void encode_deallocate(struct xdr_stream *xdr,
146 struct nfs42_falloc_args *args,
147 struct compound_hdr *hdr)
148{
149 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr);
150 encode_fallocate(xdr, args);
151}
152
153static void encode_seek(struct xdr_stream *xdr,
154 struct nfs42_seek_args *args,
155 struct compound_hdr *hdr)
156{
157 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr);
158 encode_nfs4_stateid(xdr, &args->sa_stateid);
159 encode_uint64(xdr, args->sa_offset);
160 encode_uint32(xdr, args->sa_what);
161}
162
163static void encode_layoutstats(struct xdr_stream *xdr,
164 struct nfs42_layoutstat_args *args,
165 struct nfs42_layoutstat_devinfo *devinfo,
166 struct compound_hdr *hdr)
167{
168 __be32 *p;
169
170 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr);
171 p = reserve_space(xdr, 8 + 8);
172 p = xdr_encode_hyper(p, devinfo->offset);
173 p = xdr_encode_hyper(p, devinfo->length);
174 encode_nfs4_stateid(xdr, &args->stateid);
175 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4);
176 p = xdr_encode_hyper(p, devinfo->read_count);
177 p = xdr_encode_hyper(p, devinfo->read_bytes);
178 p = xdr_encode_hyper(p, devinfo->write_count);
179 p = xdr_encode_hyper(p, devinfo->write_bytes);
180 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data,
181 NFS4_DEVICEID4_SIZE);
182 /* Encode layoutupdate4 */
183 *p++ = cpu_to_be32(devinfo->layout_type);
184 if (devinfo->ld_private.ops)
185 devinfo->ld_private.ops->encode(xdr, args,
186 &devinfo->ld_private);
187 else
188 encode_uint32(xdr, 0);
189}
190
191static void encode_clone(struct xdr_stream *xdr,
192 struct nfs42_clone_args *args,
193 struct compound_hdr *hdr)
194{
195 __be32 *p;
196
197 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr);
198 encode_nfs4_stateid(xdr, &args->src_stateid);
199 encode_nfs4_stateid(xdr, &args->dst_stateid);
200 p = reserve_space(xdr, 3*8);
201 p = xdr_encode_hyper(p, args->src_offset);
202 p = xdr_encode_hyper(p, args->dst_offset);
203 xdr_encode_hyper(p, args->count);
204}
205
206/*
207 * Encode ALLOCATE request
208 */
209static void nfs4_xdr_enc_allocate(struct rpc_rqst *req,
210 struct xdr_stream *xdr,
211 struct nfs42_falloc_args *args)
212{
213 struct compound_hdr hdr = {
214 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
215 };
216
217 encode_compound_hdr(xdr, req, &hdr);
218 encode_sequence(xdr, &args->seq_args, &hdr);
219 encode_putfh(xdr, args->falloc_fh, &hdr);
220 encode_allocate(xdr, args, &hdr);
221 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
222 encode_nops(&hdr);
223}
224
225/*
226 * Encode COPY request
227 */
228static void nfs4_xdr_enc_copy(struct rpc_rqst *req,
229 struct xdr_stream *xdr,
230 struct nfs42_copy_args *args)
231{
232 struct compound_hdr hdr = {
233 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
234 };
235
236 encode_compound_hdr(xdr, req, &hdr);
237 encode_sequence(xdr, &args->seq_args, &hdr);
238 encode_putfh(xdr, args->src_fh, &hdr);
239 encode_savefh(xdr, &hdr);
240 encode_putfh(xdr, args->dst_fh, &hdr);
241 encode_copy(xdr, args, &hdr);
242 encode_nops(&hdr);
243}
244
245/*
246 * Encode DEALLOCATE request
247 */
248static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req,
249 struct xdr_stream *xdr,
250 struct nfs42_falloc_args *args)
251{
252 struct compound_hdr hdr = {
253 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
254 };
255
256 encode_compound_hdr(xdr, req, &hdr);
257 encode_sequence(xdr, &args->seq_args, &hdr);
258 encode_putfh(xdr, args->falloc_fh, &hdr);
259 encode_deallocate(xdr, args, &hdr);
260 encode_getfattr(xdr, args->falloc_bitmask, &hdr);
261 encode_nops(&hdr);
262}
263
264/*
265 * Encode SEEK request
266 */
267static void nfs4_xdr_enc_seek(struct rpc_rqst *req,
268 struct xdr_stream *xdr,
269 struct nfs42_seek_args *args)
270{
271 struct compound_hdr hdr = {
272 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
273 };
274
275 encode_compound_hdr(xdr, req, &hdr);
276 encode_sequence(xdr, &args->seq_args, &hdr);
277 encode_putfh(xdr, args->sa_fh, &hdr);
278 encode_seek(xdr, args, &hdr);
279 encode_nops(&hdr);
280}
281
282/*
283 * Encode LAYOUTSTATS request
284 */
285static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req,
286 struct xdr_stream *xdr,
287 struct nfs42_layoutstat_args *args)
288{
289 int i;
290
291 struct compound_hdr hdr = {
292 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
293 };
294
295 encode_compound_hdr(xdr, req, &hdr);
296 encode_sequence(xdr, &args->seq_args, &hdr);
297 encode_putfh(xdr, args->fh, &hdr);
298 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
299 for (i = 0; i < args->num_dev; i++)
300 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr);
301 encode_nops(&hdr);
302}
303
304/*
305 * Encode CLONE request
306 */
307static void nfs4_xdr_enc_clone(struct rpc_rqst *req,
308 struct xdr_stream *xdr,
309 struct nfs42_clone_args *args)
310{
311 struct compound_hdr hdr = {
312 .minorversion = nfs4_xdr_minorversion(&args->seq_args),
313 };
314
315 encode_compound_hdr(xdr, req, &hdr);
316 encode_sequence(xdr, &args->seq_args, &hdr);
317 encode_putfh(xdr, args->src_fh, &hdr);
318 encode_savefh(xdr, &hdr);
319 encode_putfh(xdr, args->dst_fh, &hdr);
320 encode_clone(xdr, args, &hdr);
321 encode_getfattr(xdr, args->dst_bitmask, &hdr);
322 encode_nops(&hdr);
323}
324
325static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
326{
327 return decode_op_hdr(xdr, OP_ALLOCATE);
328}
329
330static int decode_write_response(struct xdr_stream *xdr,
331 struct nfs42_write_res *res)
332{
333 __be32 *p;
334
335 p = xdr_inline_decode(xdr, 4 + 8 + 4);
336 if (unlikely(!p))
337 goto out_overflow;
338
339 /*
340 * We never use asynchronous mode, so warn if a server returns
341 * a stateid.
342 */
343 if (unlikely(*p != 0)) {
344 pr_err_once("%s: server has set unrequested "
345 "asynchronous mode\n", __func__);
346 return -EREMOTEIO;
347 }
348 p++;
349 p = xdr_decode_hyper(p, &res->count);
350 res->verifier.committed = be32_to_cpup(p);
351 return decode_verifier(xdr, &res->verifier.verifier);
352
353out_overflow:
354 print_overflow_msg(__func__, xdr);
355 return -EIO;
356}
357
358static int decode_copy_requirements(struct xdr_stream *xdr,
359 struct nfs42_copy_res *res) {
360 __be32 *p;
361
362 p = xdr_inline_decode(xdr, 4 + 4);
363 if (unlikely(!p))
364 goto out_overflow;
365
366 res->consecutive = be32_to_cpup(p++);
367 res->synchronous = be32_to_cpup(p++);
368 return 0;
369out_overflow:
370 print_overflow_msg(__func__, xdr);
371 return -EIO;
372}
373
374static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res)
375{
376 int status;
377
378 status = decode_op_hdr(xdr, OP_COPY);
379 if (status == NFS4ERR_OFFLOAD_NO_REQS) {
380 status = decode_copy_requirements(xdr, res);
381 if (status)
382 return status;
383 return NFS4ERR_OFFLOAD_NO_REQS;
384 } else if (status)
385 return status;
386
387 status = decode_write_response(xdr, &res->write_res);
388 if (status)
389 return status;
390
391 return decode_copy_requirements(xdr, res);
392}
393
394static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res)
395{
396 return decode_op_hdr(xdr, OP_DEALLOCATE);
397}
398
399static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res)
400{
401 int status;
402 __be32 *p;
403
404 status = decode_op_hdr(xdr, OP_SEEK);
405 if (status)
406 return status;
407
408 p = xdr_inline_decode(xdr, 4 + 8);
409 if (unlikely(!p))
410 goto out_overflow;
411
412 res->sr_eof = be32_to_cpup(p++);
413 p = xdr_decode_hyper(p, &res->sr_offset);
414 return 0;
415
416out_overflow:
417 print_overflow_msg(__func__, xdr);
418 return -EIO;
419}
420
421static int decode_layoutstats(struct xdr_stream *xdr)
422{
423 return decode_op_hdr(xdr, OP_LAYOUTSTATS);
424}
425
426static int decode_clone(struct xdr_stream *xdr)
427{
428 return decode_op_hdr(xdr, OP_CLONE);
429}
430
431/*
432 * Decode ALLOCATE request
433 */
434static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp,
435 struct xdr_stream *xdr,
436 struct nfs42_falloc_res *res)
437{
438 struct compound_hdr hdr;
439 int status;
440
441 status = decode_compound_hdr(xdr, &hdr);
442 if (status)
443 goto out;
444 status = decode_sequence(xdr, &res->seq_res, rqstp);
445 if (status)
446 goto out;
447 status = decode_putfh(xdr);
448 if (status)
449 goto out;
450 status = decode_allocate(xdr, res);
451 if (status)
452 goto out;
453 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
454out:
455 return status;
456}
457
458/*
459 * Decode COPY response
460 */
461static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp,
462 struct xdr_stream *xdr,
463 struct nfs42_copy_res *res)
464{
465 struct compound_hdr hdr;
466 int status;
467
468 status = decode_compound_hdr(xdr, &hdr);
469 if (status)
470 goto out;
471 status = decode_sequence(xdr, &res->seq_res, rqstp);
472 if (status)
473 goto out;
474 status = decode_putfh(xdr);
475 if (status)
476 goto out;
477 status = decode_savefh(xdr);
478 if (status)
479 goto out;
480 status = decode_putfh(xdr);
481 if (status)
482 goto out;
483 status = decode_copy(xdr, res);
484out:
485 return status;
486}
487
488/*
489 * Decode DEALLOCATE request
490 */
491static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp,
492 struct xdr_stream *xdr,
493 struct nfs42_falloc_res *res)
494{
495 struct compound_hdr hdr;
496 int status;
497
498 status = decode_compound_hdr(xdr, &hdr);
499 if (status)
500 goto out;
501 status = decode_sequence(xdr, &res->seq_res, rqstp);
502 if (status)
503 goto out;
504 status = decode_putfh(xdr);
505 if (status)
506 goto out;
507 status = decode_deallocate(xdr, res);
508 if (status)
509 goto out;
510 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server);
511out:
512 return status;
513}
514
515/*
516 * Decode SEEK request
517 */
518static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp,
519 struct xdr_stream *xdr,
520 struct nfs42_seek_res *res)
521{
522 struct compound_hdr hdr;
523 int status;
524
525 status = decode_compound_hdr(xdr, &hdr);
526 if (status)
527 goto out;
528 status = decode_sequence(xdr, &res->seq_res, rqstp);
529 if (status)
530 goto out;
531 status = decode_putfh(xdr);
532 if (status)
533 goto out;
534 status = decode_seek(xdr, res);
535out:
536 return status;
537}
538
539/*
540 * Decode LAYOUTSTATS request
541 */
542static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp,
543 struct xdr_stream *xdr,
544 struct nfs42_layoutstat_res *res)
545{
546 struct compound_hdr hdr;
547 int status, i;
548
549 status = decode_compound_hdr(xdr, &hdr);
550 if (status)
551 goto out;
552 status = decode_sequence(xdr, &res->seq_res, rqstp);
553 if (status)
554 goto out;
555 status = decode_putfh(xdr);
556 if (status)
557 goto out;
558 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV);
559 for (i = 0; i < res->num_dev; i++) {
560 status = decode_layoutstats(xdr);
561 if (status)
562 goto out;
563 }
564out:
565 res->rpc_status = status;
566 return status;
567}
568
569/*
570 * Decode CLONE request
571 */
572static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp,
573 struct xdr_stream *xdr,
574 struct nfs42_clone_res *res)
575{
576 struct compound_hdr hdr;
577 int status;
578
579 status = decode_compound_hdr(xdr, &hdr);
580 if (status)
581 goto out;
582 status = decode_sequence(xdr, &res->seq_res, rqstp);
583 if (status)
584 goto out;
585 status = decode_putfh(xdr);
586 if (status)
587 goto out;
588 status = decode_savefh(xdr);
589 if (status)
590 goto out;
591 status = decode_putfh(xdr);
592 if (status)
593 goto out;
594 status = decode_clone(xdr);
595 if (status)
596 goto out;
597 status = decode_getfattr(xdr, res->dst_fattr, res->server);
598
599out:
600 res->rpc_status = status;
601 return status;
602}
603
604#endif /* __LINUX_FS_NFS_NFS4_2XDR_H */