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 #define decode_copy_maxsz (op_decode_hdr_maxsz + \ 26 NFS42_WRITE_RES_SIZE + \ 27 1 /* cr_consecutive */ + \ 28 1 /* cr_synchronous */) 29 #define encode_deallocate_maxsz (op_encode_hdr_maxsz + \ 30 encode_fallocate_maxsz) 31 #define decode_deallocate_maxsz (op_decode_hdr_maxsz) 32 #define encode_seek_maxsz (op_encode_hdr_maxsz + \ 33 encode_stateid_maxsz + \ 34 2 /* offset */ + \ 35 1 /* whence */) 36 #define decode_seek_maxsz (op_decode_hdr_maxsz + \ 37 1 /* eof */ + \ 38 1 /* whence */ + \ 39 2 /* offset */ + \ 40 2 /* length */) 41 #define encode_io_info_maxsz 4 42 #define encode_layoutstats_maxsz (op_decode_hdr_maxsz + \ 43 2 /* offset */ + \ 44 2 /* length */ + \ 45 encode_stateid_maxsz + \ 46 encode_io_info_maxsz + \ 47 encode_io_info_maxsz + \ 48 1 /* opaque devaddr4 length */ + \ 49 XDR_QUADLEN(PNFS_LAYOUTSTATS_MAXSIZE)) 50 #define decode_layoutstats_maxsz (op_decode_hdr_maxsz) 51 #define encode_clone_maxsz (encode_stateid_maxsz + \ 52 encode_stateid_maxsz + \ 53 2 /* src offset */ + \ 54 2 /* dst offset */ + \ 55 2 /* count */) 56 #define decode_clone_maxsz (op_decode_hdr_maxsz) 57 58 #define NFS4_enc_allocate_sz (compound_encode_hdr_maxsz + \ 59 encode_putfh_maxsz + \ 60 encode_allocate_maxsz + \ 61 encode_getattr_maxsz) 62 #define NFS4_dec_allocate_sz (compound_decode_hdr_maxsz + \ 63 decode_putfh_maxsz + \ 64 decode_allocate_maxsz + \ 65 decode_getattr_maxsz) 66 #define NFS4_enc_copy_sz (compound_encode_hdr_maxsz + \ 67 encode_putfh_maxsz + \ 68 encode_savefh_maxsz + \ 69 encode_putfh_maxsz + \ 70 encode_copy_maxsz + \ 71 encode_commit_maxsz) 72 #define NFS4_dec_copy_sz (compound_decode_hdr_maxsz + \ 73 decode_putfh_maxsz + \ 74 decode_savefh_maxsz + \ 75 decode_putfh_maxsz + \ 76 decode_copy_maxsz + \ 77 decode_commit_maxsz) 78 #define NFS4_enc_deallocate_sz (compound_encode_hdr_maxsz + \ 79 encode_putfh_maxsz + \ 80 encode_deallocate_maxsz + \ 81 encode_getattr_maxsz) 82 #define NFS4_dec_deallocate_sz (compound_decode_hdr_maxsz + \ 83 decode_putfh_maxsz + \ 84 decode_deallocate_maxsz + \ 85 decode_getattr_maxsz) 86 #define NFS4_enc_seek_sz (compound_encode_hdr_maxsz + \ 87 encode_putfh_maxsz + \ 88 encode_seek_maxsz) 89 #define NFS4_dec_seek_sz (compound_decode_hdr_maxsz + \ 90 decode_putfh_maxsz + \ 91 decode_seek_maxsz) 92 #define NFS4_enc_layoutstats_sz (compound_encode_hdr_maxsz + \ 93 encode_sequence_maxsz + \ 94 encode_putfh_maxsz + \ 95 PNFS_LAYOUTSTATS_MAXDEV * encode_layoutstats_maxsz) 96 #define NFS4_dec_layoutstats_sz (compound_decode_hdr_maxsz + \ 97 decode_sequence_maxsz + \ 98 decode_putfh_maxsz + \ 99 PNFS_LAYOUTSTATS_MAXDEV * decode_layoutstats_maxsz) 100 #define NFS4_enc_clone_sz (compound_encode_hdr_maxsz + \ 101 encode_sequence_maxsz + \ 102 encode_putfh_maxsz + \ 103 encode_savefh_maxsz + \ 104 encode_putfh_maxsz + \ 105 encode_clone_maxsz + \ 106 encode_getattr_maxsz) 107 #define NFS4_dec_clone_sz (compound_decode_hdr_maxsz + \ 108 decode_sequence_maxsz + \ 109 decode_putfh_maxsz + \ 110 decode_savefh_maxsz + \ 111 decode_putfh_maxsz + \ 112 decode_clone_maxsz + \ 113 decode_getattr_maxsz) 114 115 static void encode_fallocate(struct xdr_stream *xdr, 116 const struct nfs42_falloc_args *args) 117 { 118 encode_nfs4_stateid(xdr, &args->falloc_stateid); 119 encode_uint64(xdr, args->falloc_offset); 120 encode_uint64(xdr, args->falloc_length); 121 } 122 123 static void encode_allocate(struct xdr_stream *xdr, 124 const struct nfs42_falloc_args *args, 125 struct compound_hdr *hdr) 126 { 127 encode_op_hdr(xdr, OP_ALLOCATE, decode_allocate_maxsz, hdr); 128 encode_fallocate(xdr, args); 129 } 130 131 static void encode_copy(struct xdr_stream *xdr, 132 const struct nfs42_copy_args *args, 133 struct compound_hdr *hdr) 134 { 135 encode_op_hdr(xdr, OP_COPY, decode_copy_maxsz, hdr); 136 encode_nfs4_stateid(xdr, &args->src_stateid); 137 encode_nfs4_stateid(xdr, &args->dst_stateid); 138 139 encode_uint64(xdr, args->src_pos); 140 encode_uint64(xdr, args->dst_pos); 141 encode_uint64(xdr, args->count); 142 143 encode_uint32(xdr, 1); /* consecutive = true */ 144 encode_uint32(xdr, 1); /* synchronous = true */ 145 encode_uint32(xdr, 0); /* src server list */ 146 } 147 148 static void encode_deallocate(struct xdr_stream *xdr, 149 const struct nfs42_falloc_args *args, 150 struct compound_hdr *hdr) 151 { 152 encode_op_hdr(xdr, OP_DEALLOCATE, decode_deallocate_maxsz, hdr); 153 encode_fallocate(xdr, args); 154 } 155 156 static void encode_seek(struct xdr_stream *xdr, 157 const struct nfs42_seek_args *args, 158 struct compound_hdr *hdr) 159 { 160 encode_op_hdr(xdr, OP_SEEK, decode_seek_maxsz, hdr); 161 encode_nfs4_stateid(xdr, &args->sa_stateid); 162 encode_uint64(xdr, args->sa_offset); 163 encode_uint32(xdr, args->sa_what); 164 } 165 166 static void encode_layoutstats(struct xdr_stream *xdr, 167 const struct nfs42_layoutstat_args *args, 168 struct nfs42_layoutstat_devinfo *devinfo, 169 struct compound_hdr *hdr) 170 { 171 __be32 *p; 172 173 encode_op_hdr(xdr, OP_LAYOUTSTATS, decode_layoutstats_maxsz, hdr); 174 p = reserve_space(xdr, 8 + 8); 175 p = xdr_encode_hyper(p, devinfo->offset); 176 p = xdr_encode_hyper(p, devinfo->length); 177 encode_nfs4_stateid(xdr, &args->stateid); 178 p = reserve_space(xdr, 4*8 + NFS4_DEVICEID4_SIZE + 4); 179 p = xdr_encode_hyper(p, devinfo->read_count); 180 p = xdr_encode_hyper(p, devinfo->read_bytes); 181 p = xdr_encode_hyper(p, devinfo->write_count); 182 p = xdr_encode_hyper(p, devinfo->write_bytes); 183 p = xdr_encode_opaque_fixed(p, devinfo->dev_id.data, 184 NFS4_DEVICEID4_SIZE); 185 /* Encode layoutupdate4 */ 186 *p++ = cpu_to_be32(devinfo->layout_type); 187 if (devinfo->ld_private.ops) 188 devinfo->ld_private.ops->encode(xdr, args, 189 &devinfo->ld_private); 190 else 191 encode_uint32(xdr, 0); 192 } 193 194 static void encode_clone(struct xdr_stream *xdr, 195 const struct nfs42_clone_args *args, 196 struct compound_hdr *hdr) 197 { 198 __be32 *p; 199 200 encode_op_hdr(xdr, OP_CLONE, decode_clone_maxsz, hdr); 201 encode_nfs4_stateid(xdr, &args->src_stateid); 202 encode_nfs4_stateid(xdr, &args->dst_stateid); 203 p = reserve_space(xdr, 3*8); 204 p = xdr_encode_hyper(p, args->src_offset); 205 p = xdr_encode_hyper(p, args->dst_offset); 206 xdr_encode_hyper(p, args->count); 207 } 208 209 /* 210 * Encode ALLOCATE request 211 */ 212 static void nfs4_xdr_enc_allocate(struct rpc_rqst *req, 213 struct xdr_stream *xdr, 214 const void *data) 215 { 216 const struct nfs42_falloc_args *args = data; 217 struct compound_hdr hdr = { 218 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 219 }; 220 221 encode_compound_hdr(xdr, req, &hdr); 222 encode_sequence(xdr, &args->seq_args, &hdr); 223 encode_putfh(xdr, args->falloc_fh, &hdr); 224 encode_allocate(xdr, args, &hdr); 225 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 226 encode_nops(&hdr); 227 } 228 229 static void encode_copy_commit(struct xdr_stream *xdr, 230 const struct nfs42_copy_args *args, 231 struct compound_hdr *hdr) 232 { 233 __be32 *p; 234 235 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 236 p = reserve_space(xdr, 12); 237 p = xdr_encode_hyper(p, args->dst_pos); 238 *p = cpu_to_be32(args->count); 239 } 240 241 /* 242 * Encode COPY request 243 */ 244 static void nfs4_xdr_enc_copy(struct rpc_rqst *req, 245 struct xdr_stream *xdr, 246 const void *data) 247 { 248 const struct nfs42_copy_args *args = data; 249 struct compound_hdr hdr = { 250 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 251 }; 252 253 encode_compound_hdr(xdr, req, &hdr); 254 encode_sequence(xdr, &args->seq_args, &hdr); 255 encode_putfh(xdr, args->src_fh, &hdr); 256 encode_savefh(xdr, &hdr); 257 encode_putfh(xdr, args->dst_fh, &hdr); 258 encode_copy(xdr, args, &hdr); 259 encode_copy_commit(xdr, args, &hdr); 260 encode_nops(&hdr); 261 } 262 263 /* 264 * Encode DEALLOCATE request 265 */ 266 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, 267 struct xdr_stream *xdr, 268 const void *data) 269 { 270 const struct nfs42_falloc_args *args = data; 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->falloc_fh, &hdr); 278 encode_deallocate(xdr, args, &hdr); 279 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 280 encode_nops(&hdr); 281 } 282 283 /* 284 * Encode SEEK request 285 */ 286 static void nfs4_xdr_enc_seek(struct rpc_rqst *req, 287 struct xdr_stream *xdr, 288 const void *data) 289 { 290 const struct nfs42_seek_args *args = data; 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->sa_fh, &hdr); 298 encode_seek(xdr, args, &hdr); 299 encode_nops(&hdr); 300 } 301 302 /* 303 * Encode LAYOUTSTATS request 304 */ 305 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, 306 struct xdr_stream *xdr, 307 const void *data) 308 { 309 const struct nfs42_layoutstat_args *args = data; 310 int i; 311 312 struct compound_hdr hdr = { 313 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 314 }; 315 316 encode_compound_hdr(xdr, req, &hdr); 317 encode_sequence(xdr, &args->seq_args, &hdr); 318 encode_putfh(xdr, args->fh, &hdr); 319 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 320 for (i = 0; i < args->num_dev; i++) 321 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); 322 encode_nops(&hdr); 323 } 324 325 /* 326 * Encode CLONE request 327 */ 328 static void nfs4_xdr_enc_clone(struct rpc_rqst *req, 329 struct xdr_stream *xdr, 330 const void *data) 331 { 332 const struct nfs42_clone_args *args = data; 333 struct compound_hdr hdr = { 334 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 335 }; 336 337 encode_compound_hdr(xdr, req, &hdr); 338 encode_sequence(xdr, &args->seq_args, &hdr); 339 encode_putfh(xdr, args->src_fh, &hdr); 340 encode_savefh(xdr, &hdr); 341 encode_putfh(xdr, args->dst_fh, &hdr); 342 encode_clone(xdr, args, &hdr); 343 encode_getfattr(xdr, args->dst_bitmask, &hdr); 344 encode_nops(&hdr); 345 } 346 347 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 348 { 349 return decode_op_hdr(xdr, OP_ALLOCATE); 350 } 351 352 static int decode_write_response(struct xdr_stream *xdr, 353 struct nfs42_write_res *res) 354 { 355 __be32 *p; 356 357 p = xdr_inline_decode(xdr, 4 + 8 + 4); 358 if (unlikely(!p)) 359 goto out_overflow; 360 361 /* 362 * We never use asynchronous mode, so warn if a server returns 363 * a stateid. 364 */ 365 if (unlikely(*p != 0)) { 366 pr_err_once("%s: server has set unrequested " 367 "asynchronous mode\n", __func__); 368 return -EREMOTEIO; 369 } 370 p++; 371 p = xdr_decode_hyper(p, &res->count); 372 res->verifier.committed = be32_to_cpup(p); 373 return decode_verifier(xdr, &res->verifier.verifier); 374 375 out_overflow: 376 print_overflow_msg(__func__, xdr); 377 return -EIO; 378 } 379 380 static int decode_copy_requirements(struct xdr_stream *xdr, 381 struct nfs42_copy_res *res) { 382 __be32 *p; 383 384 p = xdr_inline_decode(xdr, 4 + 4); 385 if (unlikely(!p)) 386 goto out_overflow; 387 388 res->consecutive = be32_to_cpup(p++); 389 res->synchronous = be32_to_cpup(p++); 390 return 0; 391 out_overflow: 392 print_overflow_msg(__func__, xdr); 393 return -EIO; 394 } 395 396 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) 397 { 398 int status; 399 400 status = decode_op_hdr(xdr, OP_COPY); 401 if (status == NFS4ERR_OFFLOAD_NO_REQS) { 402 status = decode_copy_requirements(xdr, res); 403 if (status) 404 return status; 405 return NFS4ERR_OFFLOAD_NO_REQS; 406 } else if (status) 407 return status; 408 409 status = decode_write_response(xdr, &res->write_res); 410 if (status) 411 return status; 412 413 return decode_copy_requirements(xdr, res); 414 } 415 416 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 417 { 418 return decode_op_hdr(xdr, OP_DEALLOCATE); 419 } 420 421 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) 422 { 423 int status; 424 __be32 *p; 425 426 status = decode_op_hdr(xdr, OP_SEEK); 427 if (status) 428 return status; 429 430 p = xdr_inline_decode(xdr, 4 + 8); 431 if (unlikely(!p)) 432 goto out_overflow; 433 434 res->sr_eof = be32_to_cpup(p++); 435 p = xdr_decode_hyper(p, &res->sr_offset); 436 return 0; 437 438 out_overflow: 439 print_overflow_msg(__func__, xdr); 440 return -EIO; 441 } 442 443 static int decode_layoutstats(struct xdr_stream *xdr) 444 { 445 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 446 } 447 448 static int decode_clone(struct xdr_stream *xdr) 449 { 450 return decode_op_hdr(xdr, OP_CLONE); 451 } 452 453 /* 454 * Decode ALLOCATE request 455 */ 456 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, 457 struct xdr_stream *xdr, 458 void *data) 459 { 460 struct nfs42_falloc_res *res = data; 461 struct compound_hdr hdr; 462 int status; 463 464 status = decode_compound_hdr(xdr, &hdr); 465 if (status) 466 goto out; 467 status = decode_sequence(xdr, &res->seq_res, rqstp); 468 if (status) 469 goto out; 470 status = decode_putfh(xdr); 471 if (status) 472 goto out; 473 status = decode_allocate(xdr, res); 474 if (status) 475 goto out; 476 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 477 out: 478 return status; 479 } 480 481 /* 482 * Decode COPY response 483 */ 484 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, 485 struct xdr_stream *xdr, 486 void *data) 487 { 488 struct nfs42_copy_res *res = data; 489 struct compound_hdr hdr; 490 int status; 491 492 status = decode_compound_hdr(xdr, &hdr); 493 if (status) 494 goto out; 495 status = decode_sequence(xdr, &res->seq_res, rqstp); 496 if (status) 497 goto out; 498 status = decode_putfh(xdr); 499 if (status) 500 goto out; 501 status = decode_savefh(xdr); 502 if (status) 503 goto out; 504 status = decode_putfh(xdr); 505 if (status) 506 goto out; 507 status = decode_copy(xdr, res); 508 if (status) 509 goto out; 510 status = decode_commit(xdr, &res->commit_res); 511 out: 512 return status; 513 } 514 515 /* 516 * Decode DEALLOCATE request 517 */ 518 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, 519 struct xdr_stream *xdr, 520 void *data) 521 { 522 struct nfs42_falloc_res *res = data; 523 struct compound_hdr hdr; 524 int status; 525 526 status = decode_compound_hdr(xdr, &hdr); 527 if (status) 528 goto out; 529 status = decode_sequence(xdr, &res->seq_res, rqstp); 530 if (status) 531 goto out; 532 status = decode_putfh(xdr); 533 if (status) 534 goto out; 535 status = decode_deallocate(xdr, res); 536 if (status) 537 goto out; 538 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 539 out: 540 return status; 541 } 542 543 /* 544 * Decode SEEK request 545 */ 546 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, 547 struct xdr_stream *xdr, 548 void *data) 549 { 550 struct nfs42_seek_res *res = data; 551 struct compound_hdr hdr; 552 int status; 553 554 status = decode_compound_hdr(xdr, &hdr); 555 if (status) 556 goto out; 557 status = decode_sequence(xdr, &res->seq_res, rqstp); 558 if (status) 559 goto out; 560 status = decode_putfh(xdr); 561 if (status) 562 goto out; 563 status = decode_seek(xdr, res); 564 out: 565 return status; 566 } 567 568 /* 569 * Decode LAYOUTSTATS request 570 */ 571 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, 572 struct xdr_stream *xdr, 573 void *data) 574 { 575 struct nfs42_layoutstat_res *res = data; 576 struct compound_hdr hdr; 577 int status, i; 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 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 589 for (i = 0; i < res->num_dev; i++) { 590 status = decode_layoutstats(xdr); 591 if (status) 592 goto out; 593 } 594 out: 595 res->rpc_status = status; 596 return status; 597 } 598 599 /* 600 * Decode CLONE request 601 */ 602 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, 603 struct xdr_stream *xdr, 604 void *data) 605 { 606 struct nfs42_clone_res *res = data; 607 struct compound_hdr hdr; 608 int status; 609 610 status = decode_compound_hdr(xdr, &hdr); 611 if (status) 612 goto out; 613 status = decode_sequence(xdr, &res->seq_res, rqstp); 614 if (status) 615 goto out; 616 status = decode_putfh(xdr); 617 if (status) 618 goto out; 619 status = decode_savefh(xdr); 620 if (status) 621 goto out; 622 status = decode_putfh(xdr); 623 if (status) 624 goto out; 625 status = decode_clone(xdr); 626 if (status) 627 goto out; 628 status = decode_getfattr(xdr, res->dst_fattr, res->server); 629 630 out: 631 res->rpc_status = status; 632 return status; 633 } 634 635 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ 636