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 112 static 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 120 static 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 128 static 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 145 static 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 153 static 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 163 static 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 191 static 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 */ 209 static 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 */ 228 static 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 */ 248 static 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 */ 267 static 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 */ 285 static 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 */ 307 static 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 325 static int decode_allocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 326 { 327 return decode_op_hdr(xdr, OP_ALLOCATE); 328 } 329 330 static 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 353 out_overflow: 354 print_overflow_msg(__func__, xdr); 355 return -EIO; 356 } 357 358 static 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; 369 out_overflow: 370 print_overflow_msg(__func__, xdr); 371 return -EIO; 372 } 373 374 static 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 394 static int decode_deallocate(struct xdr_stream *xdr, struct nfs42_falloc_res *res) 395 { 396 return decode_op_hdr(xdr, OP_DEALLOCATE); 397 } 398 399 static 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 416 out_overflow: 417 print_overflow_msg(__func__, xdr); 418 return -EIO; 419 } 420 421 static int decode_layoutstats(struct xdr_stream *xdr) 422 { 423 return decode_op_hdr(xdr, OP_LAYOUTSTATS); 424 } 425 426 static int decode_clone(struct xdr_stream *xdr) 427 { 428 return decode_op_hdr(xdr, OP_CLONE); 429 } 430 431 /* 432 * Decode ALLOCATE request 433 */ 434 static 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); 454 out: 455 return status; 456 } 457 458 /* 459 * Decode COPY response 460 */ 461 static 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); 484 out: 485 return status; 486 } 487 488 /* 489 * Decode DEALLOCATE request 490 */ 491 static 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); 511 out: 512 return status; 513 } 514 515 /* 516 * Decode SEEK request 517 */ 518 static 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); 535 out: 536 return status; 537 } 538 539 /* 540 * Decode LAYOUTSTATS request 541 */ 542 static 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 } 564 out: 565 res->rpc_status = status; 566 return status; 567 } 568 569 /* 570 * Decode CLONE request 571 */ 572 static 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 599 out: 600 res->rpc_status = status; 601 return status; 602 } 603 604 #endif /* __LINUX_FS_NFS_NFS4_2XDR_H */ 605