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