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 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 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 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 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 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 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 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 struct nfs42_falloc_args *args) 214 { 215 struct compound_hdr hdr = { 216 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 217 }; 218 219 encode_compound_hdr(xdr, req, &hdr); 220 encode_sequence(xdr, &args->seq_args, &hdr); 221 encode_putfh(xdr, args->falloc_fh, &hdr); 222 encode_allocate(xdr, args, &hdr); 223 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 224 encode_nops(&hdr); 225 } 226 227 static void encode_copy_commit(struct xdr_stream *xdr, 228 struct nfs42_copy_args *args, 229 struct compound_hdr *hdr) 230 { 231 __be32 *p; 232 233 encode_op_hdr(xdr, OP_COMMIT, decode_commit_maxsz, hdr); 234 p = reserve_space(xdr, 12); 235 p = xdr_encode_hyper(p, args->dst_pos); 236 *p = cpu_to_be32(args->count); 237 } 238 239 /* 240 * Encode COPY request 241 */ 242 static void nfs4_xdr_enc_copy(struct rpc_rqst *req, 243 struct xdr_stream *xdr, 244 struct nfs42_copy_args *args) 245 { 246 struct compound_hdr hdr = { 247 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 248 }; 249 250 encode_compound_hdr(xdr, req, &hdr); 251 encode_sequence(xdr, &args->seq_args, &hdr); 252 encode_putfh(xdr, args->src_fh, &hdr); 253 encode_savefh(xdr, &hdr); 254 encode_putfh(xdr, args->dst_fh, &hdr); 255 encode_copy(xdr, args, &hdr); 256 encode_copy_commit(xdr, args, &hdr); 257 encode_nops(&hdr); 258 } 259 260 /* 261 * Encode DEALLOCATE request 262 */ 263 static void nfs4_xdr_enc_deallocate(struct rpc_rqst *req, 264 struct xdr_stream *xdr, 265 struct nfs42_falloc_args *args) 266 { 267 struct compound_hdr hdr = { 268 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 269 }; 270 271 encode_compound_hdr(xdr, req, &hdr); 272 encode_sequence(xdr, &args->seq_args, &hdr); 273 encode_putfh(xdr, args->falloc_fh, &hdr); 274 encode_deallocate(xdr, args, &hdr); 275 encode_getfattr(xdr, args->falloc_bitmask, &hdr); 276 encode_nops(&hdr); 277 } 278 279 /* 280 * Encode SEEK request 281 */ 282 static void nfs4_xdr_enc_seek(struct rpc_rqst *req, 283 struct xdr_stream *xdr, 284 struct nfs42_seek_args *args) 285 { 286 struct compound_hdr hdr = { 287 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 288 }; 289 290 encode_compound_hdr(xdr, req, &hdr); 291 encode_sequence(xdr, &args->seq_args, &hdr); 292 encode_putfh(xdr, args->sa_fh, &hdr); 293 encode_seek(xdr, args, &hdr); 294 encode_nops(&hdr); 295 } 296 297 /* 298 * Encode LAYOUTSTATS request 299 */ 300 static void nfs4_xdr_enc_layoutstats(struct rpc_rqst *req, 301 struct xdr_stream *xdr, 302 struct nfs42_layoutstat_args *args) 303 { 304 int i; 305 306 struct compound_hdr hdr = { 307 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 308 }; 309 310 encode_compound_hdr(xdr, req, &hdr); 311 encode_sequence(xdr, &args->seq_args, &hdr); 312 encode_putfh(xdr, args->fh, &hdr); 313 WARN_ON(args->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 314 for (i = 0; i < args->num_dev; i++) 315 encode_layoutstats(xdr, args, &args->devinfo[i], &hdr); 316 encode_nops(&hdr); 317 } 318 319 /* 320 * Encode CLONE request 321 */ 322 static void nfs4_xdr_enc_clone(struct rpc_rqst *req, 323 struct xdr_stream *xdr, 324 struct nfs42_clone_args *args) 325 { 326 struct compound_hdr hdr = { 327 .minorversion = nfs4_xdr_minorversion(&args->seq_args), 328 }; 329 330 encode_compound_hdr(xdr, req, &hdr); 331 encode_sequence(xdr, &args->seq_args, &hdr); 332 encode_putfh(xdr, args->src_fh, &hdr); 333 encode_savefh(xdr, &hdr); 334 encode_putfh(xdr, args->dst_fh, &hdr); 335 encode_clone(xdr, args, &hdr); 336 encode_getfattr(xdr, args->dst_bitmask, &hdr); 337 encode_nops(&hdr); 338 } 339 340 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 341 { 342 return decode_op_hdr(xdr, OP_ALLOCATE); 343 } 344 345 static int decode_write_response(struct xdr_stream *xdr, 346 struct nfs42_write_res *res) 347 { 348 __be32 *p; 349 350 p = xdr_inline_decode(xdr, 4 + 8 + 4); 351 if (unlikely(!p)) 352 goto out_overflow; 353 354 /* 355 * We never use asynchronous mode, so warn if a server returns 356 * a stateid. 357 */ 358 if (unlikely(*p != 0)) { 359 pr_err_once("%s: server has set unrequested " 360 "asynchronous mode\n", __func__); 361 return -EREMOTEIO; 362 } 363 p++; 364 p = xdr_decode_hyper(p, &res->count); 365 res->verifier.committed = be32_to_cpup(p); 366 return decode_verifier(xdr, &res->verifier.verifier); 367 368 out_overflow: 369 print_overflow_msg(__func__, xdr); 370 return -EIO; 371 } 372 373 static int decode_copy_requirements(struct xdr_stream *xdr, 374 struct nfs42_copy_res *res) { 375 __be32 *p; 376 377 p = xdr_inline_decode(xdr, 4 + 4); 378 if (unlikely(!p)) 379 goto out_overflow; 380 381 res->consecutive = be32_to_cpup(p++); 382 res->synchronous = be32_to_cpup(p++); 383 return 0; 384 out_overflow: 385 print_overflow_msg(__func__, xdr); 386 return -EIO; 387 } 388 389 static int decode_copy(struct xdr_stream *xdr, struct nfs42_copy_res *res) 390 { 391 int status; 392 393 status = decode_op_hdr(xdr, OP_COPY); 394 if (status == NFS4ERR_OFFLOAD_NO_REQS) { 395 status = decode_copy_requirements(xdr, res); 396 if (status) 397 return status; 398 return NFS4ERR_OFFLOAD_NO_REQS; 399 } else if (status) 400 return status; 401 402 status = decode_write_response(xdr, &res->write_res); 403 if (status) 404 return status; 405 406 return decode_copy_requirements(xdr, res); 407 } 408 409 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 410 { 411 return decode_op_hdr(xdr, OP_DEALLOCATE); 412 } 413 414 static int decode_seek(struct xdr_stream *xdr, struct nfs42_seek_res *res) 415 { 416 int status; 417 __be32 *p; 418 419 status = decode_op_hdr(xdr, OP_SEEK); 420 if (status) 421 return status; 422 423 p = xdr_inline_decode(xdr, 4 + 8); 424 if (unlikely(!p)) 425 goto out_overflow; 426 427 res->sr_eof = be32_to_cpup(p++); 428 p = xdr_decode_hyper(p, &res->sr_offset); 429 return 0; 430 431 out_overflow: 432 print_overflow_msg(__func__, xdr); 433 return -EIO; 434 } 435 436 static int decode_layoutstats(struct xdr_stream *xdr) 437 { 438 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 439 } 440 441 static int decode_clone(struct xdr_stream *xdr) 442 { 443 return decode_op_hdr(xdr, OP_CLONE); 444 } 445 446 /* 447 * Decode ALLOCATE request 448 */ 449 static int nfs4_xdr_dec_allocate(struct rpc_rqst *rqstp, 450 struct xdr_stream *xdr, 451 struct nfs42_falloc_res *res) 452 { 453 struct compound_hdr hdr; 454 int status; 455 456 status = decode_compound_hdr(xdr, &hdr); 457 if (status) 458 goto out; 459 status = decode_sequence(xdr, &res->seq_res, rqstp); 460 if (status) 461 goto out; 462 status = decode_putfh(xdr); 463 if (status) 464 goto out; 465 status = decode_allocate(xdr, res); 466 if (status) 467 goto out; 468 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 469 out: 470 return status; 471 } 472 473 /* 474 * Decode COPY response 475 */ 476 static int nfs4_xdr_dec_copy(struct rpc_rqst *rqstp, 477 struct xdr_stream *xdr, 478 struct nfs42_copy_res *res) 479 { 480 struct compound_hdr hdr; 481 int status; 482 483 status = decode_compound_hdr(xdr, &hdr); 484 if (status) 485 goto out; 486 status = decode_sequence(xdr, &res->seq_res, rqstp); 487 if (status) 488 goto out; 489 status = decode_putfh(xdr); 490 if (status) 491 goto out; 492 status = decode_savefh(xdr); 493 if (status) 494 goto out; 495 status = decode_putfh(xdr); 496 if (status) 497 goto out; 498 status = decode_copy(xdr, res); 499 if (status) 500 goto out; 501 status = decode_commit(xdr, &res->commit_res); 502 out: 503 return status; 504 } 505 506 /* 507 * Decode DEALLOCATE request 508 */ 509 static int nfs4_xdr_dec_deallocate(struct rpc_rqst *rqstp, 510 struct xdr_stream *xdr, 511 struct nfs42_falloc_res *res) 512 { 513 struct compound_hdr hdr; 514 int status; 515 516 status = decode_compound_hdr(xdr, &hdr); 517 if (status) 518 goto out; 519 status = decode_sequence(xdr, &res->seq_res, rqstp); 520 if (status) 521 goto out; 522 status = decode_putfh(xdr); 523 if (status) 524 goto out; 525 status = decode_deallocate(xdr, res); 526 if (status) 527 goto out; 528 decode_getfattr(xdr, res->falloc_fattr, res->falloc_server); 529 out: 530 return status; 531 } 532 533 /* 534 * Decode SEEK request 535 */ 536 static int nfs4_xdr_dec_seek(struct rpc_rqst *rqstp, 537 struct xdr_stream *xdr, 538 struct nfs42_seek_res *res) 539 { 540 struct compound_hdr hdr; 541 int status; 542 543 status = decode_compound_hdr(xdr, &hdr); 544 if (status) 545 goto out; 546 status = decode_sequence(xdr, &res->seq_res, rqstp); 547 if (status) 548 goto out; 549 status = decode_putfh(xdr); 550 if (status) 551 goto out; 552 status = decode_seek(xdr, res); 553 out: 554 return status; 555 } 556 557 /* 558 * Decode LAYOUTSTATS request 559 */ 560 static int nfs4_xdr_dec_layoutstats(struct rpc_rqst *rqstp, 561 struct xdr_stream *xdr, 562 struct nfs42_layoutstat_res *res) 563 { 564 struct compound_hdr hdr; 565 int status, i; 566 567 status = decode_compound_hdr(xdr, &hdr); 568 if (status) 569 goto out; 570 status = decode_sequence(xdr, &res->seq_res, rqstp); 571 if (status) 572 goto out; 573 status = decode_putfh(xdr); 574 if (status) 575 goto out; 576 WARN_ON(res->num_dev > PNFS_LAYOUTSTATS_MAXDEV); 577 for (i = 0; i < res->num_dev; i++) { 578 status = decode_layoutstats(xdr); 579 if (status) 580 goto out; 581 } 582 out: 583 res->rpc_status = status; 584 return status; 585 } 586 587 /* 588 * Decode CLONE request 589 */ 590 static int nfs4_xdr_dec_clone(struct rpc_rqst *rqstp, 591 struct xdr_stream *xdr, 592 struct nfs42_clone_res *res) 593 { 594 struct compound_hdr hdr; 595 int status; 596 597 status = decode_compound_hdr(xdr, &hdr); 598 if (status) 599 goto out; 600 status = decode_sequence(xdr, &res->seq_res, rqstp); 601 if (status) 602 goto out; 603 status = decode_putfh(xdr); 604 if (status) 605 goto out; 606 status = decode_savefh(xdr); 607 if (status) 608 goto out; 609 status = decode_putfh(xdr); 610 if (status) 611 goto out; 612 status = decode_clone(xdr); 613 if (status) 614 goto out; 615 status = decode_getfattr(xdr, res->dst_fattr, res->server); 616 617 out: 618 res->rpc_status = status; 619 return status; 620 } 621 622 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ 623