1# SPDX-License-Identifier: BSD-2-Clause 2# 3# Copyright (c) 2026 voidanix <voidanix@FreeBSD.org> 4# 5 6. $(atf_get_srcdir)/conf.sh 7 8atf_test_case create cleanup 9create_head() 10{ 11 atf_set "descr" "Basic gzoned device creation" 12 atf_set "require.user" "root" 13} 14create_body() 15{ 16 gzoned_test_setup 17 18 zoned_backing_md 19 atf_check gzoned create -s 256m ${md} 20 atf_check test -c /dev/${md}.zoned 21} 22create_cleanup() 23{ 24 gzoned_test_cleanup 25} 26 27atf_test_case is_zoned cleanup 28is_zoned_head() 29{ 30 atf_set "descr" "gzoned creates a host-managed zoned device" 31 atf_set "require.user" "root" 32} 33is_zoned_body() 34{ 35 gzoned_test_setup 36 37 zoned_backing_md 38 atf_check gzoned create ${md} 39 atf_check_equal "Host Managed" \ 40 "$(zonectl -d /dev/${md}.zoned -c params | \ 41 awk -F': ' '/Zone Mode/ {print $2}')" 42} 43is_zoned_cleanup() 44{ 45 gzoned_test_cleanup 46} 47 48atf_test_case conventional cleanup 49conventional_head() 50{ 51 atf_set "descr" "gzoned device has a few conventional zones" 52 atf_set "require.user" "root" 53} 54conventional_body() 55{ 56 gzoned_test_setup 57 58 zoned_backing_md 59 atf_check gzoned create -s 256m -c 1,3 ${md} 60 atf_check_equal "2" "$(zone_count nonwp)" 61} 62conventional_cleanup() 63{ 64 gzoned_test_cleanup 65} 66 67atf_test_case conventional_single cleanup 68conventional_single_head() 69{ 70 atf_set "descr" "gzoned create -c accepts a single zone" 71 atf_set "require.user" "root" 72} 73conventional_single_body() 74{ 75 gzoned_test_setup 76 77 zoned_backing_md 78 atf_check gzoned create -s 256m -c 2 ${md} 79 atf_check_equal "1" "$(zone_count nonwp)" 80 # The conventional zone is zone 2. At LBA 512m / 512 = 0x100000. 81 atf_check_equal "0x100000" \ 82 "$(zonectl -d /dev/${md}.zoned -c rz -o nonwp -P script | \ 83 awk -F',' 'NR == 1 {gsub(/ /, "", $1); print $1}')" 84} 85conventional_single_cleanup() 86{ 87 gzoned_test_cleanup 88} 89 90atf_test_case conventional_range cleanup 91conventional_range_head() 92{ 93 atf_set "descr" "gzoned device has a range of conventional zones" 94 atf_set "require.user" "root" 95} 96conventional_range_body() 97{ 98 gzoned_test_setup 99 100 zoned_backing_md 101 atf_check gzoned create -s 256m -c 0-2 ${md} 102 atf_check_equal "3" "$(zone_count nonwp)" 103} 104conventional_range_cleanup() 105{ 106 gzoned_test_cleanup 107} 108 109atf_test_case all_zones_same cleanup 110all_zones_same_head() 111{ 112 atf_set "descr" "gzoned device has all zones of the same type" 113 atf_set "require.user" "root" 114} 115all_zones_same_body() 116{ 117 gzoned_test_setup 118 119 zoned_backing_md 120 atf_check gzoned create -s 256m -c 0-3 ${md} 121 atf_check -o match:"^4 zones," \ 122 -o match:"Zone lengths and types are all the same" \ 123 zonectl -d /dev/${md}.zoned -c rz -P summary 124} 125all_zones_same_cleanup() 126{ 127 gzoned_test_cleanup 128} 129 130atf_test_case conventional_ranges cleanup 131conventional_ranges_head() 132{ 133 atf_set "descr" "gzoned create -c accepts a list of zone ranges" 134 atf_set "require.user" "root" 135} 136conventional_ranges_body() 137{ 138 gzoned_test_setup 139 140 zoned_backing_md 141 atf_check gzoned create -s 256m -c 0,2-3 ${md} 142 atf_check_equal "3" "$(zone_count nonwp)" 143 # Zone 1 alone stays sequential: the second conventional zone 144 # reported must be zone 2, at LBA 512m / 512 = 0x100000. 145 atf_check_equal "0x100000" \ 146 "$(zonectl -d /dev/${md}.zoned -c rz -o nonwp -P script | \ 147 awk -F',' 'NR == 2 {gsub(/ /, "", $1); print $1}')" 148} 149conventional_ranges_cleanup() 150{ 151 gzoned_test_cleanup 152} 153 154atf_test_case zone_size cleanup 155zone_size_head() 156{ 157 atf_set "descr" "gzoned create -s adjusts the zone size" 158 atf_set "require.user" "root" 159} 160zone_size_body() 161{ 162 gzoned_test_setup 163 164 zoned_backing_md 165 atf_check gzoned create -s 128m ${md} 166 # 1024m of zone space now holds eight 128m zones instead of four. 167 atf_check -o match:"^8 zones," \ 168 zonectl -d /dev/${md}.zoned -c rz -P summary 169 # Zone 1 starts at LBA 128m / 512 = 0x40000. 170 atf_check_equal "0x40000" "$(zone_start 1)" 171} 172zone_size_cleanup() 173{ 174 gzoned_test_cleanup 175} 176 177atf_test_case zone_count_derived cleanup 178zone_count_derived_head() 179{ 180 atf_set "descr" "gzoned obtains the same zone count at every taste" 181 atf_set "require.user" "root" 182} 183zone_count_derived_body() 184{ 185 gzoned_test_setup 186 187 zoned_backing_md 188 atf_check gzoned create -s 128m ${md} 189 atf_check -o match:"^8 zones," \ 190 zonectl -d /dev/${md}.zoned -c rz -P summary 191 last_start=$(zone_start 7) 192 193 atf_check gzoned stop ${md}.zoned 194 wait_dev_gone /dev/${md}.zoned 195 true > /dev/${md} 196 wait_dev /dev/${md}.zoned 197 atf_check -o match:"^8 zones," \ 198 zonectl -d /dev/${md}.zoned -c rz -P summary 199 atf_check_equal "${last_start}" "$(zone_start 7)" 200} 201zone_count_derived_cleanup() 202{ 203 gzoned_test_cleanup 204} 205 206atf_test_case create_readonly cleanup 207create_readonly_head() 208{ 209 atf_set "descr" "gzoned refuses a provider it cannot write to" 210 atf_set "require.user" "root" 211} 212create_readonly_body() 213{ 214 gzoned_test_setup 215 216 atf_check truncate -s 1025m backing_file 217 attach_md md -t vnode -f backing_file -o readonly 218 atf_check -s not-exit:0 -e ignore gzoned create -s 256m ${md} 219 atf_check test ! -c /dev/${md}.zoned 220} 221create_readonly_cleanup() 222{ 223 gzoned_test_cleanup 224} 225 226atf_test_case zone_size_too_large cleanup 227zone_size_too_large_head() 228{ 229 atf_set "descr" "gzoned refuses a zone size larger than the provider" 230 atf_set "require.user" "root" 231} 232zone_size_too_large_body() 233{ 234 gzoned_test_setup 235 236 zoned_backing_md 237 atf_check -s not-exit:0 -e match:"unusable" \ 238 gzoned create -s 2g ${md} 239 atf_check test ! -c /dev/${md}.zoned 240} 241zone_size_too_large_cleanup() 242{ 243 gzoned_test_cleanup 244} 245 246atf_test_case zone_size_too_many cleanup 247zone_size_too_many_head() 248{ 249 atf_set "descr" "gzoned refuses a zone size yielding too many zones" 250 atf_set "require.user" "root" 251} 252zone_size_too_many_body() 253{ 254 gzoned_test_setup 255 256 # One zone per sector on a sparse 8T provider overflows the 32-bit zone 257 # count. 258 atf_check truncate -s 8t backing_file 259 attach_md md -t vnode -f backing_file 260 atf_check -s not-exit:0 -e match:"unusable" \ 261 gzoned create -s 512 ${md} 262 atf_check test ! -c /dev/${md}.zoned 263} 264zone_size_too_many_cleanup() 265{ 266 gzoned_test_cleanup 267} 268 269atf_test_case reset_wp cleanup 270reset_wp_head() 271{ 272 atf_set "descr" \ 273 "gzoned write pointer can be reset inside a seq-write-req zone" 274 atf_set "require.user" "root" 275} 276reset_wp_body() 277{ 278 gzoned_test_setup 279 280 zoned_backing_md 281 atf_check gzoned create -s 256m ${md} 282 283 # Advance the write pointer of zone 0 by 1m (2048 512-byte LBAs). 284 atf_check -e ignore \ 285 dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 286 atf_check_equal "0x800" "$(zone_wp 0)" 287 288 atf_check zonectl -d /dev/${md}.zoned -c rwp -l 0 289 atf_check_equal "0" "$(zone_wp 0)" 290} 291reset_wp_cleanup() 292{ 293 gzoned_test_cleanup 294} 295 296atf_test_case reset_wp_conv cleanup 297reset_wp_conv_head() 298{ 299 atf_set "descr" \ 300 "gzoned write pointer cannot be reset inside a conventional zone" 301 atf_set "require.user" "root" 302} 303reset_wp_conv_body() 304{ 305 gzoned_test_setup 306 307 zoned_backing_md 308 atf_check gzoned create -s 256m -c 0 ${md} 309 atf_check test -c /dev/${md}.zoned 310 atf_check_equal "1" "$(zone_count nonwp)" 311 atf_check -s not-exit:0 -e ignore \ 312 zonectl -d /dev/${md}.zoned -c rwp -l 0 313} 314reset_wp_conv_cleanup() 315{ 316 gzoned_test_cleanup 317} 318 319atf_test_case reset_wp_empty cleanup 320reset_wp_empty_head() 321{ 322 atf_set "descr" \ 323 "gzoned accepts a write pointer reset of an already-empty zone" 324 atf_set "require.user" "root" 325} 326reset_wp_empty_body() 327{ 328 gzoned_test_setup 329 330 zoned_backing_md 331 atf_check gzoned create -s 256m ${md} 332 atf_check_equal "0" "$(zone_wp 0)" 333 atf_check zonectl -d /dev/${md}.zoned -c rwp -l 0 334 atf_check_equal "0" "$(zone_wp 0)" 335 atf_check_equal "4" "$(zone_count empty)" 336} 337reset_wp_empty_cleanup() 338{ 339 gzoned_test_cleanup 340} 341 342atf_test_case reset_wp_finished cleanup 343reset_wp_finished_head() 344{ 345 atf_set "descr" "gzoned resets a finished zone back to empty" 346 atf_set "require.user" "root" 347} 348reset_wp_finished_body() 349{ 350 gzoned_test_setup 351 352 zoned_backing_md 353 atf_check gzoned create -s 256m ${md} 354 atf_check zonectl -d /dev/${md}.zoned -c finish -l 0 355 atf_check_equal "1" "$(zone_count full)" 356 357 atf_check zonectl -d /dev/${md}.zoned -c rwp -l 0 358 atf_check_equal "0" "$(zone_count full)" 359 atf_check_equal "0" "$(zone_wp 0)" 360 atf_check_equal "4" "$(zone_count empty)" 361} 362reset_wp_finished_cleanup() 363{ 364 gzoned_test_cleanup 365} 366 367atf_test_case reset_wp_all_readonly cleanup 368reset_wp_all_readonly_head() 369{ 370 atf_set "descr" \ 371 "gzoned keeps the contents of a zone reset all did not reset" 372 atf_set "require.user" "root" 373} 374reset_wp_all_readonly_body() 375{ 376 gzoned_test_setup 377 378 zoned_backing_md 379 atf_check gzoned create -s 256m ${md} 380 381 # Fill the start of zone 1 with something unrecognizable. 382 atf_check -e ignore dd if=/dev/random of=pattern bs=1m count=1 383 atf_check -e ignore \ 384 dd if=pattern of=/dev/${md}.zoned bs=1m oseek=256 count=1 385 atf_check gzoned fault -z 1 -s ro ${md}.zoned 386 387 atf_check zonectl -d /dev/${md}.zoned -c rwp -a 388 atf_check_equal "1" "$(zone_count ro)" 389 # Read-only zone reports no write pointer. Clear the fault to see 390 # whether the pointer was left where it was beforehand. 391 atf_check gzoned fault -z 1 -s clear ${md}.zoned 392 atf_check_equal "0x80800" "$(zone_wp 524288)" 393 atf_check -e ignore \ 394 dd if=/dev/${md}.zoned of=after bs=1m iseek=256 count=1 395 atf_check cmp pattern after 396} 397reset_wp_all_readonly_cleanup() 398{ 399 gzoned_test_cleanup 400} 401 402atf_test_case zone_id_lowest_lba cleanup 403zone_id_lowest_lba_head() 404{ 405 atf_set "descr" \ 406 "gzoned only takes a zone ID that is a zone's lowest LBA" 407 atf_set "require.user" "root" 408} 409zone_id_lowest_lba_body() 410{ 411 gzoned_test_setup 412 413 zoned_backing_md 414 atf_check gzoned create -s 256m ${md} 415 416 atf_check zonectl -d /dev/${md}.zoned -c rwp -l 0x80000 417 atf_check -s not-exit:0 -e ignore \ 418 zonectl -d /dev/${md}.zoned -c rwp -l 0x80001 419 atf_check -s not-exit:0 -e ignore \ 420 zonectl -d /dev/${md}.zoned -c open -l 1 421 atf_check -s not-exit:0 -e ignore \ 422 zonectl -d /dev/${md}.zoned -c finish -l 0x7ffff 423 atf_check_equal "4" "$(zone_count empty)" 424 425 atf_check zonectl -d /dev/${md}.zoned -c rwp -a 426} 427zone_id_lowest_lba_cleanup() 428{ 429 gzoned_test_cleanup 430} 431 432atf_test_case unrestricted_reads cleanup 433unrestricted_reads_head() 434{ 435 atf_set "descr" \ 436 "gzoned device allows reads above the write pointer by default" 437 atf_set "require.user" "root" 438} 439unrestricted_reads_body() 440{ 441 gzoned_test_setup 442 443 zoned_backing_md 444 atf_check gzoned create -s 256m ${md} 445 atf_check -o match:"URSWRZ.*: Yes" \ 446 zonectl -d /dev/${md}.zoned -c params 447 # Reading an empty sequential zone is fine. 448 atf_check -e ignore \ 449 dd if=/dev/${md}.zoned of=/dev/null bs=512 count=1 450 # So is one 768k read straddling the 256m mark, as in write_boundary: 451 # spanning zones of the same type is what URSWRZ lifts. 452 atf_check -e ignore \ 453 dd if=/dev/${md}.zoned of=/dev/null bs=768k iseek=341 count=1 454} 455unrestricted_reads_cleanup() 456{ 457 gzoned_test_cleanup 458} 459 460atf_test_case read_zone_types cleanup 461read_zone_types_head() 462{ 463 atf_set "descr" \ 464 "Reads may not cross between zone types even when unrestricted" 465 atf_set "require.user" "root" 466} 467read_zone_types_body() 468{ 469 gzoned_test_setup 470 471 zoned_backing_md 472 atf_check gzoned create -s 256m -c 0 ${md} 473 atf_check -o match:"URSWRZ.*: Yes" \ 474 zonectl -d /dev/${md}.zoned -c params 475 476 # The 768k read straddling the 256m mark reaches the kernel as one 477 # bio, running from a conventional zone into the sequential. 478 atf_check -s not-exit:0 -e ignore \ 479 dd if=/dev/${md}.zoned of=/dev/null bs=768k iseek=341 count=1 480 # Preceding block lies within the conventional zone: it's fine. 481 atf_check -e ignore \ 482 dd if=/dev/${md}.zoned of=/dev/null bs=768k iseek=340 count=1 483} 484read_zone_types_cleanup() 485{ 486 gzoned_test_cleanup 487} 488 489atf_test_case restricted_reads cleanup 490restricted_reads_head() 491{ 492 atf_set "descr" \ 493 "gzoned -u device rejects reads beyond the write pointer" 494 atf_set "require.user" "root" 495} 496restricted_reads_body() 497{ 498 gzoned_test_setup 499 500 zoned_backing_md 501 atf_check gzoned create -s 256m -u ${md} 502 atf_check -o match:"URSWRZ.*: No" \ 503 zonectl -d /dev/${md}.zoned -c params 504 505 # Reading an empty sequential zone must fail... 506 atf_check -s not-exit:0 -e ignore \ 507 dd if=/dev/${md}.zoned of=/dev/null bs=512 count=1 508 509 # ...until data has been written. 510 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 511 atf_check -e ignore \ 512 dd if=/dev/${md}.zoned of=/dev/null bs=1m count=1 513 atf_check -s not-exit:0 -e ignore \ 514 dd if=/dev/${md}.zoned of=/dev/null bs=1m count=2 515} 516restricted_reads_cleanup() 517{ 518 gzoned_test_cleanup 519} 520 521atf_test_case write_at_wp cleanup 522write_at_wp_head() 523{ 524 atf_set "descr" "gzoned accepts writes at the write pointer" 525 atf_set "require.user" "root" 526} 527write_at_wp_body() 528{ 529 gzoned_test_setup 530 531 zoned_backing_md 532 atf_check gzoned create -s 256m ${md} 533 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 534 atf_check_equal "0x800" "$(zone_wp 0)" 535 # A second write at the advanced write pointer is accepted too. 536 atf_check -e ignore \ 537 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=1 count=1 538 atf_check_equal "0x1000" "$(zone_wp 0)" 539} 540write_at_wp_cleanup() 541{ 542 gzoned_test_cleanup 543} 544 545atf_test_case write_out_of_order cleanup 546write_out_of_order_head() 547{ 548 atf_set "descr" "gzoned rejects writes that skip the write pointer" 549 atf_set "require.user" "root" 550} 551write_out_of_order_body() 552{ 553 gzoned_test_setup 554 555 zoned_backing_md 556 atf_check gzoned create -s 256m ${md} 557 # Zone 0 write pointer is at LBA 0; writing at 1m shall fail. 558 atf_check -s not-exit:0 -e ignore \ 559 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=1 count=1 560 atf_check_equal "0" "$(zone_wp 0)" 561} 562write_out_of_order_cleanup() 563{ 564 gzoned_test_cleanup 565} 566 567atf_test_case write_boundary cleanup 568write_boundary_head() 569{ 570 atf_set "descr" "gzoned rejects writes crossing a zone boundary" 571 atf_set "require.user" "root" 572} 573write_boundary_body() 574{ 575 gzoned_test_setup 576 577 zoned_backing_md 578 atf_check gzoned create -s 256m -c 0 ${md} 579 # One 768k write straddling the 256m mark (768k does not divide 580 # 256m, so the request reaches the kernel as a single bio going 581 # from the conventional zone 0 into the sequential zone 1). 582 atf_check -s not-exit:0 -e ignore \ 583 dd if=/dev/zero of=/dev/${md}.zoned bs=768k oseek=341 count=1 584 # The preceding block lies within the conventional zone and is fine. 585 atf_check -e ignore \ 586 dd if=/dev/zero of=/dev/${md}.zoned bs=768k oseek=340 count=1 587} 588write_boundary_cleanup() 589{ 590 gzoned_test_cleanup 591} 592 593atf_test_case write_conv_boundary cleanup 594write_conv_boundary_head() 595{ 596 atf_set "descr" \ 597 "gzoned allows writes crossing two conventional zones" 598 atf_set "require.user" "root" 599} 600write_conv_boundary_body() 601{ 602 gzoned_test_setup 603 604 zoned_backing_md 605 atf_check gzoned create -s 256m -c 0-1 ${md} 606 # The same straddling write rejected in write_boundary is fine 607 # when the zones on both sides are conventional. 608 atf_check -e ignore \ 609 dd if=/dev/zero of=/dev/${md}.zoned bs=768k oseek=341 count=1 610} 611write_conv_boundary_cleanup() 612{ 613 gzoned_test_cleanup 614} 615 616atf_test_case write_conv_anywhere cleanup 617write_conv_anywhere_head() 618{ 619 atf_set "descr" "gzoned conventional zones accept writes at any offset" 620 atf_set "require.user" "root" 621} 622write_conv_anywhere_body() 623{ 624 gzoned_test_setup 625 626 zoned_backing_md 627 atf_check gzoned create -s 256m -c 0 ${md} 628 # No write pointer: writing far into the zone and then again before 629 # the previous write must both succeed, and the zone never opens. 630 atf_check -e ignore \ 631 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=10 count=1 632 atf_check -e ignore \ 633 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=2 count=1 634 atf_check_equal "0" "$(zone_count imp_open)" 635} 636write_conv_anywhere_cleanup() 637{ 638 gzoned_test_cleanup 639} 640 641atf_test_case write_full cleanup 642write_full_head() 643{ 644 atf_set "descr" "gzoned rejects writes to a full zone" 645 atf_set "require.user" "root" 646} 647write_full_body() 648{ 649 gzoned_test_setup 650 651 zoned_backing_md 652 atf_check gzoned create -s 256m ${md} 653 atf_check zonectl -d /dev/${md}.zoned -c finish -l 0 654 atf_check_equal "1" "$(zone_count full)" 655 atf_check -s not-exit:0 -e ignore \ 656 dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 657} 658write_full_cleanup() 659{ 660 gzoned_test_cleanup 661} 662 663atf_test_case write_closed_zone cleanup 664write_closed_zone_head() 665{ 666 atf_set "descr" "gzoned writes to a closed zone implicitly reopen it" 667 atf_set "require.user" "root" 668} 669write_closed_zone_body() 670{ 671 gzoned_test_setup 672 673 zoned_backing_md 674 atf_check gzoned create -s 256m ${md} 675 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 676 atf_check zonectl -d /dev/${md}.zoned -c close -l 0 677 atf_check_equal "1" "$(zone_count closed)" 678 679 atf_check -e ignore \ 680 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=1 count=1 681 atf_check_equal "0" "$(zone_count closed)" 682 atf_check_equal "1" "$(zone_count imp_open)" 683} 684write_closed_zone_cleanup() 685{ 686 gzoned_test_cleanup 687} 688 689atf_test_case persistence cleanup 690persistence_head() 691{ 692 atf_set "descr" "gzoned zone state survives a stop and re-taste" 693 atf_set "require.user" "root" 694} 695persistence_body() 696{ 697 gzoned_test_setup 698 699 zoned_backing_md 700 atf_check gzoned create -s 256m ${md} 701 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 702 atf_check_equal "0x800" "$(zone_wp 0)" 703 704 # Stopping will commit the zone state; re-tasting the backing provider 705 # brings the device back with its write pointers restored. 706 atf_check gzoned stop ${md}.zoned 707 wait_dev_gone /dev/${md}.zoned 708 true > /dev/${md} 709 wait_dev /dev/${md}.zoned 710 atf_check_equal "0x800" "$(zone_wp 0)" 711} 712persistence_cleanup() 713{ 714 gzoned_test_cleanup 715} 716 717atf_test_case clear_clears_metadata cleanup 718clear_clears_metadata_head() 719{ 720 atf_set "descr" "gzoned clear erases the on-disk metadata" 721 atf_set "require.user" "root" 722} 723clear_clears_metadata_body() 724{ 725 gzoned_test_setup 726 727 zoned_backing_md 728 atf_check gzoned create -s 256m ${md} 729 # The backing provider is held open for as long as the device exists, 730 # so its metadata can only be cleared once the device is gone. 731 atf_check -s not-exit:0 -e ignore gzoned clear /dev/${md} 732 atf_check gzoned stop ${md}.zoned 733 wait_dev_gone /dev/${md}.zoned 734 atf_check gzoned clear /dev/${md} 735 true > /dev/${md} 736 sleep 1 737 atf_check test ! -c /dev/${md}.zoned 738} 739clear_clears_metadata_cleanup() 740{ 741 gzoned_test_cleanup 742} 743 744atf_test_case max_open cleanup 745max_open_head() 746{ 747 atf_set "descr" "gzoned enforces the open-zone limit" 748 atf_set "require.user" "root" 749} 750max_open_body() 751{ 752 gzoned_test_setup 753 754 zoned_backing_md 755 atf_check gzoned create -s 256m -m 1 ${md} 756 atf_check -o match:"Open Sequential Write Required Zones: 1" \ 757 zonectl -d /dev/${md}.zoned -c params 758 759 # A write into a second zone implicitly closes the first. 760 atf_check -e ignore dd if=/dev/zero of=/dev/${md}.zoned bs=1m count=1 761 atf_check -e ignore \ 762 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=256 count=1 763 atf_check_equal "1" "$(zone_count closed)" 764 atf_check_equal "1" "$(zone_count imp_open)" 765 766 # Explicitly opening zone 0 closes the implicitly open zone 1; a second 767 # explicit open will exceed the limit. 768 atf_check zonectl -d /dev/${md}.zoned -c open -l 0 769 atf_check_equal "1" "$(zone_count exp_open)" 770 atf_check -s not-exit:0 -e ignore \ 771 zonectl -d /dev/${md}.zoned -c open -l 0x80000 772} 773max_open_cleanup() 774{ 775 gzoned_test_cleanup 776} 777 778atf_test_case max_open_limit cleanup 779max_open_limit_head() 780{ 781 atf_set "descr" "gzoned rejects explicit opens beyond the open limit" 782 atf_set "require.user" "root" 783} 784max_open_limit_body() 785{ 786 gzoned_test_setup 787 788 zoned_backing_md 789 atf_check gzoned create -s 256m -m 2 ${md} 790 atf_check zonectl -d /dev/${md}.zoned -c open -l 0 791 atf_check zonectl -d /dev/${md}.zoned -c open -l 0x80000 792 atf_check_equal "2" "$(zone_count exp_open)" 793 794 # Explicitly open zones cannot be implicitly closed. A third open 795 # exceeds the limit until one of them is closed. 796 atf_check -s not-exit:0 -e ignore \ 797 zonectl -d /dev/${md}.zoned -c open -l 0x100000 798 atf_check zonectl -d /dev/${md}.zoned -c close -l 0 799 atf_check zonectl -d /dev/${md}.zoned -c open -l 0x100000 800 atf_check_equal "2" "$(zone_count exp_open)" 801} 802max_open_limit_cleanup() 803{ 804 gzoned_test_cleanup 805} 806 807atf_test_case stop_force cleanup 808stop_force_head() 809{ 810 atf_set "descr" "gzoned stop -f stops a busy device" 811 atf_set "require.user" "root" 812} 813stop_force_body() 814{ 815 gzoned_test_setup 816 817 zoned_backing_md 818 atf_check gzoned create -s 256m ${md} 819 820 # Keep the device open; a plain stop must fail, a forced one work. 821 sleep 5 < /dev/${md}.zoned & 822 spid=$! 823 sleep 0.5 824 atf_check -s not-exit:0 -e ignore gzoned stop ${md}.zoned 825 atf_check gzoned stop -f ${md}.zoned 826 wait_dev_gone /dev/${md}.zoned 827 kill $spid 2>/dev/null 828 wait $spid 2>/dev/null || true 829} 830stop_force_cleanup() 831{ 832 gzoned_test_cleanup 833} 834 835atf_test_case create_on_zoned cleanup 836create_on_zoned_head() 837{ 838 atf_set "descr" \ 839 "gzoned create on an already-zoned device fails gracefully" 840 atf_set "require.user" "root" 841} 842create_on_zoned_body() 843{ 844 gzoned_test_setup 845 846 zoned_backing_md 847 atf_check gzoned create -s 256m ${md} 848 # The metadata of the second device cannot land in the sequential zones 849 # of the first; creation must be refused and leave the first device 850 # intact, with all zones still empty. 851 atf_check -s not-exit:0 -e match:"host-managed" \ 852 gzoned create -s 256m ${md}.zoned 853 atf_check test -c /dev/${md}.zoned 854 atf_check -o match:"^4 zones," \ 855 zonectl -d /dev/${md}.zoned -c rz -P summary 856 atf_check_equal "4" "$(zone_count empty)" 857} 858create_on_zoned_cleanup() 859{ 860 gzoned_test_cleanup 861} 862 863atf_test_case fault_injection cleanup 864fault_injection_head() 865{ 866 atf_set "descr" "gzoned faulted zones reject writes until cleared" 867 atf_set "require.user" "root" 868} 869fault_injection_body() 870{ 871 gzoned_test_setup 872 873 zoned_backing_md 874 atf_check gzoned create -s 256m ${md} 875 876 atf_check gzoned fault -z 1 -s ro ${md}.zoned 877 atf_check_equal "1" "$(zone_count ro)" 878 atf_check -s not-exit:0 -e ignore \ 879 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=256 count=1 880 881 atf_check gzoned fault -z 1 -s clear ${md}.zoned 882 atf_check_equal "0" "$(zone_count ro)" 883 atf_check -e ignore \ 884 dd if=/dev/zero of=/dev/${md}.zoned bs=1m oseek=256 count=1 885 886 atf_check gzoned fault -z 2 -s offline ${md}.zoned 887 atf_check_equal "1" "$(zone_count offline)" 888 # A read only zone stays readable; an offline one does not. 889 atf_check gzoned fault -z 1 -s ro ${md}.zoned 890 atf_check -e ignore \ 891 dd if=/dev/${md}.zoned of=/dev/null bs=1m iseek=256 count=1 892 atf_check -s not-exit:0 -e ignore \ 893 dd if=/dev/${md}.zoned of=/dev/null bs=1m iseek=512 count=1 894 atf_check gzoned fault -z 1 -s clear ${md}.zoned 895 atf_check gzoned fault -z 3 -s reset ${md}.zoned 896 atf_check_equal "1" "$(zone_count reset)" 897} 898fault_injection_cleanup() 899{ 900 gzoned_test_cleanup 901} 902 903atf_test_case reset_wp_clears_fault cleanup 904reset_wp_clears_fault_head() 905{ 906 atf_set "descr" "gzoned reset write pointer clears an injected reset fault" 907 atf_set "require.user" "root" 908} 909reset_wp_clears_fault_body() 910{ 911 gzoned_test_setup 912 913 zoned_attach_md 914 915 # Freshly created zone is already empty: the injected fault is the only 916 # thing a reset has to clear. 917 atf_check gzoned fault -z 3 -s reset ${md}.zoned 918 atf_check_equal "1" "$(zone_count reset)" 919 atf_check zonectl -d /dev/${md}.zoned -c rwp -l $(zone_start 3) 920 atf_check_equal "0" "$(zone_count reset)" 921 922 # ALso holds when every zone is reset at once. 923 atf_check gzoned fault -z 3 -s reset ${md}.zoned 924 atf_check_equal "1" "$(zone_count reset)" 925 atf_check zonectl -d /dev/${md}.zoned -c rwp -a 926 atf_check_equal "0" "$(zone_count reset)" 927} 928reset_wp_clears_fault_cleanup() 929{ 930 gzoned_test_cleanup 931} 932 933atf_test_case delete_rejected cleanup 934delete_rejected_head() 935{ 936 atf_set "descr" "gzoned rejects BIO_DELETE, hides TRIM support" 937 atf_set "require.user" "root" 938} 939delete_rejected_body() 940{ 941 gzoned_test_setup 942 943 zoned_backing_md 944 atf_check gzoned create -s 256m ${md} 945 atf_check_equal "No" \ 946 "$(diskinfo -v /dev/${md}.zoned | \ 947 awk '/TRIM\/UNMAP support/ {print $1}')" 948 atf_check -s not-exit:0 -e ignore -o ignore \ 949 trim -f /dev/${md}.zoned 950} 951delete_rejected_cleanup() 952{ 953 gzoned_test_cleanup 954} 955 956atf_test_case conventional_overlap cleanup 957conventional_overlap_head() 958{ 959 atf_set "descr" "gzoned create -c refuses overlapping zone ranges" 960 atf_set "require.user" "root" 961} 962conventional_overlap_body() 963{ 964 gzoned_test_setup 965 966 zoned_backing_md 967 atf_check -s not-exit:0 -e match:"overlaps" \ 968 gzoned create -s 256m -c 0-2,1-3 ${md} 969 atf_check test ! -c /dev/${md}.zoned 970 atf_check -s not-exit:0 -e match:"overlaps" \ 971 gzoned create -s 256m -c 1,1 ${md} 972 atf_check -s not-exit:0 -e match:"overlaps" \ 973 gzoned create -s 256m -c 0-3,2 ${md} 974 atf_check gzoned create -s 256m -c 0-1,2-3 ${md} 975 atf_check_equal "4" "$(zone_count nonwp)" 976} 977conventional_overlap_cleanup() 978{ 979 gzoned_test_cleanup 980} 981 982atf_test_case resize cleanup 983resize_head() 984{ 985 atf_set "descr" "Resizing the backing provider destroys the device" 986 atf_set "require.user" "root" 987} 988resize_body() 989{ 990 gzoned_test_setup 991 992 zoned_backing_md 993 atf_check gzoned create -s 256m ${md} 994 atf_check test -c /dev/${md}.zoned 995 996 # The zone layout is fixed at creation, with the metadata sitting at the 997 # end of the provider: neither survives the provider changing size. The 998 # device is destroyed rather than left describing a disk that is no 999 # longer there. 1000 atf_check truncate -s 2049m backing_file 1001 atf_check mdconfig -r -u ${md} -s 2049m 1002 wait_dev_gone /dev/${md}.zoned 1003 1004 # Stale metadata is out of reach of the taste, at its new size: the 1005 # device does not come back on its own. 1006 true > /dev/${md} 1007 sleep 1 1008 atf_check test ! -c /dev/${md}.zoned 1009} 1010resize_cleanup() 1011{ 1012 gzoned_test_cleanup 1013} 1014 1015atf_init_test_cases() 1016{ 1017 atf_add_test_case create 1018 atf_add_test_case create_on_zoned 1019 atf_add_test_case is_zoned 1020 atf_add_test_case conventional 1021 atf_add_test_case conventional_single 1022 atf_add_test_case conventional_range 1023 atf_add_test_case conventional_ranges 1024 atf_add_test_case conventional_overlap 1025 atf_add_test_case all_zones_same 1026 atf_add_test_case zone_size 1027 atf_add_test_case zone_count_derived 1028 atf_add_test_case create_readonly 1029 atf_add_test_case zone_size_too_large 1030 atf_add_test_case zone_size_too_many 1031 atf_add_test_case reset_wp 1032 atf_add_test_case reset_wp_conv 1033 atf_add_test_case reset_wp_empty 1034 atf_add_test_case reset_wp_finished 1035 atf_add_test_case reset_wp_all_readonly 1036 atf_add_test_case zone_id_lowest_lba 1037 atf_add_test_case unrestricted_reads 1038 atf_add_test_case read_zone_types 1039 atf_add_test_case restricted_reads 1040 atf_add_test_case write_at_wp 1041 atf_add_test_case write_out_of_order 1042 atf_add_test_case write_boundary 1043 atf_add_test_case write_conv_boundary 1044 atf_add_test_case write_conv_anywhere 1045 atf_add_test_case write_full 1046 atf_add_test_case write_closed_zone 1047 atf_add_test_case persistence 1048 atf_add_test_case clear_clears_metadata 1049 atf_add_test_case max_open 1050 atf_add_test_case max_open_limit 1051 atf_add_test_case stop_force 1052 atf_add_test_case fault_injection 1053 atf_add_test_case reset_wp_clears_fault 1054 atf_add_test_case delete_rejected 1055 atf_add_test_case resize 1056} 1057