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