1#- 2# SPDX-License-Identifier: BSD-2-Clause 3# 4# Copyright (c) 2022-2023 The FreeBSD Foundation 5# 6# This software was developed by Mark Johnston under sponsorship from 7# the FreeBSD Foundation. 8# 9# Redistribution and use in source and binary forms, with or without 10# modification, are permitted provided that the following conditions are 11# met: 12# 1. Redistributions of source code must retain the above copyright 13# notice, this list of conditions and the following disclaimer. 14# 2. Redistributions in binary form must reproduce the above copyright 15# notice, this list of conditions and the following disclaimer in 16# the documentation and/or other materials provided with the distribution. 17# 18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28# SUCH DAMAGE. 29# 30 31MAKEFS="makefs -t zfs -o verify-txgs=true -o poolguid=$$" 32ZFS_POOL_NAME="makefstest$$" 33TEST_ZFS_POOL_NAME="$TMPDIR/poolname" 34 35. "$(dirname "$0")/makefs_tests_common.sh" 36 37common_cleanup() 38{ 39 local pool md 40 41 # Try to force a TXG, this can help catch bugs by triggering a panic. 42 sync 43 44 if [ -f "$TEST_ZFS_POOL_NAME" ]; then 45 pool=$(cat $TEST_ZFS_POOL_NAME) 46 if zpool list "$pool" >/dev/null; then 47 zpool destroy "$pool" 48 fi 49 fi 50 51 if [ -f "$TEST_MD_DEVICE_FILE" ]; then 52 md=$(cat $TEST_MD_DEVICE_FILE) 53 if [ -c /dev/"$md" ]; then 54 mdconfig -o force -d -u "$md" 55 fi 56 fi 57} 58 59import_image() 60{ 61 atf_check -o save:$TEST_MD_DEVICE_FILE mdconfig -a -f $TEST_IMAGE 62 atf_check -o ignore \ 63 zdb -e -p /dev/$(cat $TEST_MD_DEVICE_FILE) -mmm -ddddd $ZFS_POOL_NAME 64 atf_check zpool import -R $TEST_MOUNT_DIR $ZFS_POOL_NAME 65 echo "$ZFS_POOL_NAME" > $TEST_ZFS_POOL_NAME 66} 67 68# 69# Test autoexpansion of the vdev. 70# 71# The pool is initially 10GB, so we get 10GB minus one metaslab's worth of 72# usable space for data. Then the pool is expanded to 50GB, and the amount of 73# usable space is 50GB minus one metaslab. 74# 75atf_test_case autoexpand cleanup 76autoexpand_body() 77{ 78 local mssize poolsize poolsize1 newpoolsize 79 80 create_test_inputs 81 82 mssize=$((128 * 1024 * 1024)) 83 poolsize=$((10 * 1024 * 1024 * 1024)) 84 atf_check $MAKEFS -s $poolsize -o mssize=$mssize -o rootpath=/ \ 85 -o poolname=$ZFS_POOL_NAME \ 86 $TEST_IMAGE $TEST_INPUTS_DIR 87 88 newpoolsize=$((50 * 1024 * 1024 * 1024)) 89 truncate -s $newpoolsize $TEST_IMAGE 90 91 import_image 92 93 check_image_contents 94 95 poolsize1=$(zpool list -Hp -o size $ZFS_POOL_NAME) 96 atf_check [ $((poolsize1 + $mssize)) -eq $poolsize ] 97 98 atf_check zpool online -e $ZFS_POOL_NAME /dev/$(cat $TEST_MD_DEVICE_FILE) 99 100 check_image_contents 101 102 poolsize1=$(zpool list -Hp -o size $ZFS_POOL_NAME) 103 atf_check [ $((poolsize1 + $mssize)) -eq $newpoolsize ] 104} 105autoexpand_cleanup() 106{ 107 common_cleanup 108} 109 110# 111# Test setting the autotrim pool property. 112# 113atf_test_case autotrim cleanup 114autotrim_body() 115{ 116 local src val 117 118 create_test_inputs 119 120 atf_check -s exit:1 -e match:"invalid value .foo. for autotrim" \ 121 $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 122 -o autotrim=foo $TEST_IMAGE $TEST_INPUTS_DIR 123 124 for val in on off; do 125 atf_check $MAKEFS -s 1g -o rootpath=/ \ 126 -o poolname=$ZFS_POOL_NAME \ 127 -o autotrim=$val \ 128 $TEST_IMAGE $TEST_INPUTS_DIR 129 130 import_image 131 132 check_image_contents 133 134 # OpenZFS reports a pool property whose value equals the 135 # default as coming from the default, even if it was set. 136 if [ $val = off ]; then 137 src=default 138 else 139 src=local 140 fi 141 atf_check -o inline:$val\\n \ 142 zpool get -H -o value autotrim $ZFS_POOL_NAME 143 atf_check -o inline:$src\\n \ 144 zpool get -H -o source autotrim $ZFS_POOL_NAME 145 146 atf_check zpool destroy ${ZFS_POOL_NAME} 147 atf_check rm -f ${TEST_ZFS_POOL_NAME} 148 atf_check mdconfig -d -u $(cat ${TEST_MD_DEVICE_FILE}) 149 atf_check rm -f ${TEST_MD_DEVICE_FILE} 150 done 151 152 # Without the option the property keeps its default value. 153 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 154 $TEST_IMAGE $TEST_INPUTS_DIR 155 156 import_image 157 158 atf_check -o inline:off\\n \ 159 zpool get -H -o value autotrim $ZFS_POOL_NAME 160 atf_check -o inline:default\\n \ 161 zpool get -H -o source autotrim $ZFS_POOL_NAME 162} 163autotrim_cleanup() 164{ 165 common_cleanup 166} 167 168# 169# Test with some default layout defined by the common code. 170# 171atf_test_case basic cleanup 172basic_body() 173{ 174 create_test_inputs 175 176 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 177 $TEST_IMAGE $TEST_INPUTS_DIR 178 179 import_image 180 181 check_image_contents 182} 183basic_cleanup() 184{ 185 common_cleanup 186} 187 188# 189# Try configuring various compression algorithms. 190# 191atf_test_case compression cleanup 192compression_head() 193{ 194 # Double the default timeout to make it pass on emulated architectures 195 # on ci.freebsd.org 196 atf_set "timeout" 600 197} 198compression_body() 199{ 200 create_test_inputs 201 202 cd $TEST_INPUTS_DIR 203 mkdir dir 204 mkdir dir2 205 cd - 206 207 for alg in off on lzjb gzip gzip-1 gzip-2 gzip-3 gzip-4 \ 208 gzip-5 gzip-6 gzip-7 gzip-8 gzip-9 zle lz4 zstd; do 209 atf_check $MAKEFS -s 1g -o rootpath=/ \ 210 -o poolname=$ZFS_POOL_NAME \ 211 -o fs=${ZFS_POOL_NAME}\;compression=$alg \ 212 -o fs=${ZFS_POOL_NAME}/dir \ 213 -o fs=${ZFS_POOL_NAME}/dir2\;compression=off \ 214 $TEST_IMAGE $TEST_INPUTS_DIR 215 216 import_image 217 218 check_image_contents 219 220 if [ $alg = gzip-6 ]; then 221 # ZFS reports gzip-6 as just gzip since it uses 222 # a default compression level of 6. 223 alg=gzip 224 fi 225 # The "dir" dataset's compression algorithm should be 226 # inherited from the root dataset. 227 atf_check -o inline:$alg\\n \ 228 zfs get -H -o value compression ${ZFS_POOL_NAME} 229 atf_check -o inline:$alg\\n \ 230 zfs get -H -o value compression ${ZFS_POOL_NAME}/dir 231 atf_check -o inline:off\\n \ 232 zfs get -H -o value compression ${ZFS_POOL_NAME}/dir2 233 234 atf_check -e ignore dd if=/dev/random \ 235 of=${TEST_MOUNT_DIR}/dir/random bs=1M count=10 236 atf_check -e ignore dd if=/dev/zero \ 237 of=${TEST_MOUNT_DIR}/dir/zero bs=1M count=10 238 atf_check -e ignore dd if=/dev/zero \ 239 of=${TEST_MOUNT_DIR}/dir2/zero bs=1M count=10 240 241 # Export and reimport to ensure that everything is 242 # flushed to disk. 243 atf_check zpool export ${ZFS_POOL_NAME} 244 atf_check -o ignore \ 245 zdb -e -p /dev/$(cat $TEST_MD_DEVICE_FILE) -mmm -ddddd \ 246 $ZFS_POOL_NAME 247 atf_check zpool import -R $TEST_MOUNT_DIR $ZFS_POOL_NAME 248 249 if [ $alg = off ]; then 250 # If compression is off, the files should be the 251 # same size as the input. 252 atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/random" \ 253 du -m ${TEST_MOUNT_DIR}/dir/random 254 atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/zero" \ 255 du -m ${TEST_MOUNT_DIR}/dir/zero 256 atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir2/zero" \ 257 du -m ${TEST_MOUNT_DIR}/dir2/zero 258 else 259 # If compression is on, the dir/zero file ought 260 # to be smaller. 261 atf_check -o match:"^1[[:space:]]+${TEST_MOUNT_DIR}/dir/zero" \ 262 du -m ${TEST_MOUNT_DIR}/dir/zero 263 atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir/random" \ 264 du -m ${TEST_MOUNT_DIR}/dir/random 265 atf_check -o match:"^11[[:space:]]+${TEST_MOUNT_DIR}/dir2/zero" \ 266 du -m ${TEST_MOUNT_DIR}/dir2/zero 267 fi 268 269 atf_check zpool destroy ${ZFS_POOL_NAME} 270 atf_check rm -f ${TEST_ZFS_POOL_NAME} 271 atf_check mdconfig -o force -d -u $(cat ${TEST_MD_DEVICE_FILE}) 272 atf_check rm -f ${TEST_MD_DEVICE_FILE} 273 done 274} 275compression_cleanup() 276{ 277 common_cleanup 278} 279 280# 281# Make sure that the link count and the size of the directories which are the 282# roots of datasets count "." and the directories which are the mountpoints 283# of other datasets. fts(3) trusts the link count of the directories of ZFS 284# and skips the subdirectories that it does not account for. 285# 286atf_test_case dataset_link_counts cleanup 287dataset_link_counts_body() 288{ 289 local dir entries subdirs 290 291 create_test_dirs 292 cd $TEST_INPUTS_DIR 293 294 mkdir -p dir1/sub1 dir1/sub2 dir1/dir2/sub3 dir1/dir2/dir3 dir4 295 echo a > dir1/a 296 echo b > dir1/dir2/b 297 echo c > dir1/sub1/c 298 echo d > dir1/sub2/d 299 echo e > dir1/dir2/sub3/e 300 301 cd - 302 303 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 304 -o fs=${ZFS_POOL_NAME}/dir1 -o fs=${ZFS_POOL_NAME}/dir1/dir2 \ 305 -o fs=${ZFS_POOL_NAME}/dir1/dir2/dir3 -o fs=${ZFS_POOL_NAME}/dir4 \ 306 -o fs=${ZFS_POOL_NAME}/dir5 \ 307 $TEST_IMAGE $TEST_INPUTS_DIR 308 309 import_image 310 311 # find(1) relies on the link counts to decide which entries may be 312 # directories, so it must see the whole tree. 313 (cd $TEST_INPUTS_DIR && find dir1 dir4 | sort) > ./expected 314 atf_check -o file:./expected -x \ 315 "cd $TEST_MOUNT_DIR && find dir1 dir4 | sort" 316 317 # The link count is the number of directories in the directory plus 318 # "." and "..", and the size is the number of entries plus the same. 319 for dir in . dir1 dir1/sub1 dir1/dir2 dir1/dir2/dir3 dir4 dir5; do 320 subdirs=$(ls -d $TEST_MOUNT_DIR/$dir/*/ 2>/dev/null | wc -l) 321 entries=$(ls -A $TEST_MOUNT_DIR/$dir | wc -l) 322 atf_check -o inline:$((subdirs + 2))\\n \ 323 stat -f %l $TEST_MOUNT_DIR/$dir 324 atf_check -o inline:$((entries + 2))\\n \ 325 stat -f %z $TEST_MOUNT_DIR/$dir 326 done 327} 328dataset_link_counts_cleanup() 329{ 330 common_cleanup 331} 332 333# 334# Try destroying a dataset that was created by makefs. 335# 336atf_test_case dataset_removal cleanup 337dataset_removal_body() 338{ 339 create_test_dirs 340 341 cd $TEST_INPUTS_DIR 342 mkdir dir 343 cd - 344 345 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 346 -o fs=${ZFS_POOL_NAME}/dir \ 347 $TEST_IMAGE $TEST_INPUTS_DIR 348 349 import_image 350 351 check_image_contents 352 353 atf_check zfs destroy ${ZFS_POOL_NAME}/dir 354} 355dataset_removal_cleanup() 356{ 357 common_cleanup 358} 359 360# 361# Make sure that we can handle some special file types. Anything other than 362# regular files, symlinks and directories are ignored. 363# 364atf_test_case devfs cleanup 365devfs_body() 366{ 367 atf_check mkdir dev 368 atf_check mount -t devfs none ./dev 369 370 atf_check -e match:"skipping unhandled" $MAKEFS -s 1g -o rootpath=/ \ 371 -o poolname=$ZFS_POOL_NAME $TEST_IMAGE ./dev 372 373 import_image 374} 375devfs_cleanup() 376{ 377 common_cleanup 378 umount -f ./dev 379} 380 381# 382# Make sure that we can create and remove an empty directory. 383# 384atf_test_case empty_dir cleanup 385empty_dir_body() 386{ 387 create_test_dirs 388 389 cd $TEST_INPUTS_DIR 390 mkdir dir 391 cd - 392 393 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 394 $TEST_IMAGE $TEST_INPUTS_DIR 395 396 import_image 397 398 check_image_contents 399 400 atf_check rmdir ${TEST_MOUNT_DIR}/dir 401} 402empty_dir_cleanup() 403{ 404 common_cleanup 405} 406 407atf_test_case empty_fs cleanup 408empty_fs_body() 409{ 410 create_test_dirs 411 412 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 413 $TEST_IMAGE $TEST_INPUTS_DIR 414 415 import_image 416 417 check_image_contents 418} 419empty_fs_cleanup() 420{ 421 common_cleanup 422} 423 424atf_test_case file_extend cleanup 425file_extend_head() 426{ 427 # Double the default timeout to make it pass on emulated architectures 428 # on ci.freebsd.org 429 atf_set "timeout" 600 430} 431file_extend_body() 432{ 433 local i start 434 435 create_test_dirs 436 437 # Create a file slightly longer than the maximum block size. 438 start=132 439 dd if=/dev/random of=${TEST_INPUTS_DIR}/foo bs=1k count=$start 440 md5 -q ${TEST_INPUTS_DIR}/foo > foo.md5 441 442 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 443 $TEST_IMAGE $TEST_INPUTS_DIR 444 445 import_image 446 447 check_image_contents 448 449 i=0 450 while [ $i -lt 1000 ]; do 451 dd if=/dev/random of=${TEST_MOUNT_DIR}/foo bs=1k count=1 \ 452 seek=$(($i + $start)) conv=notrunc 453 # Make sure that the first $start blocks are unmodified. 454 dd if=${TEST_MOUNT_DIR}/foo bs=1k count=$start of=foo.copy 455 atf_check -o file:foo.md5 md5 -q foo.copy 456 i=$(($i + 1)) 457 done 458} 459file_extend_cleanup() 460{ 461 common_cleanup 462} 463 464atf_test_case file_sizes cleanup 465file_sizes_body() 466{ 467 local i 468 469 create_test_dirs 470 cd $TEST_INPUTS_DIR 471 472 i=1 473 while [ $i -lt $((1 << 20)) ]; do 474 truncate -s $i ${i}.1 475 truncate -s $(($i - 1)) ${i}.2 476 truncate -s $(($i + 1)) ${i}.3 477 i=$(($i << 1)) 478 done 479 480 cd - 481 482 # XXXMJ this creates sparse files, make sure makefs doesn't 483 # preserve the sparseness. 484 # XXXMJ need to test with larger files (at least 128MB for L2 indirs) 485 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 486 $TEST_IMAGE $TEST_INPUTS_DIR 487 488 import_image 489 490 check_image_contents 491} 492file_sizes_cleanup() 493{ 494 common_cleanup 495} 496 497atf_test_case hard_links cleanup 498hard_links_body() 499{ 500 local f 501 502 create_test_dirs 503 cd $TEST_INPUTS_DIR 504 505 mkdir dir 506 echo "hello" > 1 507 ln 1 2 508 ln 1 dir/1 509 510 echo "goodbye" > dir/a 511 ln dir/a dir/b 512 ln dir/a a 513 514 cd - 515 516 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 517 $TEST_IMAGE $TEST_INPUTS_DIR 518 519 import_image 520 521 check_image_contents 522 523 stat -f '%i' ${TEST_MOUNT_DIR}/1 > ./ino 524 stat -f '%l' ${TEST_MOUNT_DIR}/1 > ./nlink 525 for f in 1 2 dir/1; do 526 atf_check -o file:./nlink stat -f '%l' ${TEST_MOUNT_DIR}/${f} 527 atf_check -o file:./ino stat -f '%i' ${TEST_MOUNT_DIR}/${f} 528 atf_check cmp -s ${TEST_INPUTS_DIR}/1 ${TEST_MOUNT_DIR}/${f} 529 done 530 531 stat -f '%i' ${TEST_MOUNT_DIR}/dir/a > ./ino 532 stat -f '%l' ${TEST_MOUNT_DIR}/dir/a > ./nlink 533 for f in dir/a dir/b a; do 534 atf_check -o file:./nlink stat -f '%l' ${TEST_MOUNT_DIR}/${f} 535 atf_check -o file:./ino stat -f '%i' ${TEST_MOUNT_DIR}/${f} 536 atf_check cmp -s ${TEST_INPUTS_DIR}/dir/a ${TEST_MOUNT_DIR}/${f} 537 done 538} 539hard_links_cleanup() 540{ 541 common_cleanup 542} 543 544# Allocate enough dnodes from an object set that the meta dnode needs to use 545# indirect blocks. 546atf_test_case indirect_dnode_array cleanup 547indirect_dnode_array_body() 548{ 549 local count i 550 551 # How many dnodes do we need to allocate? Well, the data block size 552 # for meta dnodes is always 16KB, so with a dnode size of 512B we get 553 # 32 dnodes per direct block. The maximum indirect block size is 128KB 554 # and that can fit 1024 block pointers, so we need at least 32 * 1024 555 # files to force the use of two levels of indirection. 556 # 557 # Unfortunately that number of files makes the test run quite slowly, 558 # so we settle for a single indirect block for now... 559 count=$(jot -r 1 32 1024) 560 561 create_test_dirs 562 cd $TEST_INPUTS_DIR 563 for i in $(seq 1 $count); do 564 touch $i 565 done 566 cd - 567 568 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 569 $TEST_IMAGE $TEST_INPUTS_DIR 570 571 import_image 572 573 check_image_contents 574} 575indirect_dnode_array_cleanup() 576{ 577 common_cleanup 578} 579 580# 581# Create some files with long names, so as to test fat ZAP handling. 582# 583atf_test_case long_file_name cleanup 584long_file_name_body() 585{ 586 local dir i 587 588 create_test_dirs 589 cd $TEST_INPUTS_DIR 590 591 # micro ZAP keys can be at most 50 bytes. 592 for i in $(seq 1 60); do 593 touch $(jot -s '' $i 1 1) 594 done 595 dir=$(jot -s '' 61 1 1) 596 mkdir $dir 597 for i in $(seq 1 60); do 598 touch ${dir}/$(jot -s '' $i 1 1) 599 done 600 601 cd - 602 603 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 604 $TEST_IMAGE $TEST_INPUTS_DIR 605 606 import_image 607 608 check_image_contents 609 610 # Add a directory entry in the hope that OpenZFS might catch a bug 611 # in makefs' fat ZAP encoding. 612 touch ${TEST_MOUNT_DIR}/foo 613} 614long_file_name_cleanup() 615{ 616 common_cleanup 617} 618 619# 620# Exercise handling of multiple datasets. 621# 622atf_test_case multi_dataset_1 cleanup 623multi_dataset_1_body() 624{ 625 create_test_dirs 626 cd $TEST_INPUTS_DIR 627 628 mkdir dir1 629 echo a > dir1/a 630 mkdir dir2 631 echo b > dir2/b 632 633 cd - 634 635 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 636 -o fs=${ZFS_POOL_NAME}/dir1 -o fs=${ZFS_POOL_NAME}/dir2 \ 637 $TEST_IMAGE $TEST_INPUTS_DIR 638 639 import_image 640 641 check_image_contents 642 643 # Make sure that we have three datasets with the expected mount points. 644 atf_check -o inline:${ZFS_POOL_NAME}\\n \ 645 zfs list -H -o name ${ZFS_POOL_NAME} 646 atf_check -o inline:${TEST_MOUNT_DIR}\\n \ 647 zfs list -H -o mountpoint ${ZFS_POOL_NAME} 648 649 atf_check -o inline:${ZFS_POOL_NAME}/dir1\\n \ 650 zfs list -H -o name ${ZFS_POOL_NAME}/dir1 651 atf_check -o inline:${TEST_MOUNT_DIR}/dir1\\n \ 652 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir1 653 654 atf_check -o inline:${ZFS_POOL_NAME}/dir2\\n \ 655 zfs list -H -o name ${ZFS_POOL_NAME}/dir2 656 atf_check -o inline:${TEST_MOUNT_DIR}/dir2\\n \ 657 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir2 658} 659multi_dataset_1_cleanup() 660{ 661 common_cleanup 662} 663 664# 665# Create a pool with two datasets, where the root dataset is mounted below 666# the child dataset. 667# 668atf_test_case multi_dataset_2 cleanup 669multi_dataset_2_body() 670{ 671 create_test_dirs 672 cd $TEST_INPUTS_DIR 673 674 mkdir dir1 675 echo a > dir1/a 676 mkdir dir2 677 echo b > dir2/b 678 679 cd - 680 681 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 682 -o fs=${ZFS_POOL_NAME}/dir1\;mountpoint=/ \ 683 -o fs=${ZFS_POOL_NAME}\;mountpoint=/dir1 \ 684 $TEST_IMAGE $TEST_INPUTS_DIR 685 686 import_image 687 688 check_image_contents 689} 690multi_dataset_2_cleanup() 691{ 692 common_cleanup 693} 694 695# 696# Create a dataset with a non-existent mount point. 697# 698atf_test_case multi_dataset_3 cleanup 699multi_dataset_3_body() 700{ 701 create_test_dirs 702 cd $TEST_INPUTS_DIR 703 704 mkdir dir1 705 echo a > dir1/a 706 707 cd - 708 709 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 710 -o fs=${ZFS_POOL_NAME}/dir1 \ 711 -o fs=${ZFS_POOL_NAME}/dir2 \ 712 $TEST_IMAGE $TEST_INPUTS_DIR 713 714 import_image 715 716 atf_check -o inline:${TEST_MOUNT_DIR}/dir2\\n \ 717 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir2 718 719 # Mounting dir2 should have created a directory called dir2. Go 720 # back and create it in the staging tree before comparing. 721 atf_check mkdir ${TEST_INPUTS_DIR}/dir2 722 723 check_image_contents 724} 725multi_dataset_3_cleanup() 726{ 727 common_cleanup 728} 729 730# 731# Create an unmounted dataset. 732# 733atf_test_case multi_dataset_4 cleanup 734multi_dataset_4_body() 735{ 736 create_test_dirs 737 cd $TEST_INPUTS_DIR 738 739 mkdir dir1 740 echo a > dir1/a 741 742 cd - 743 744 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 745 -o fs=${ZFS_POOL_NAME}/dir1\;canmount=noauto\;mountpoint=none \ 746 $TEST_IMAGE $TEST_INPUTS_DIR 747 748 import_image 749 750 atf_check -o inline:none\\n \ 751 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir1 752 753 check_image_contents 754 755 atf_check zfs set mountpoint=/dir1 ${ZFS_POOL_NAME}/dir1 756 atf_check zfs mount ${ZFS_POOL_NAME}/dir1 757 atf_check -o inline:${TEST_MOUNT_DIR}/dir1\\n \ 758 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir1 759 760 # dir1/a should be part of the root dataset, not dir1. 761 atf_check -s not-exit:0 -e not-empty stat ${TEST_MOUNT_DIR}/dir1/a 762} 763multi_dataset_4_cleanup() 764{ 765 common_cleanup 766} 767 768# 769# Create a legacy dataset. 770# 771atf_test_case multi_dataset_5 cleanup 772multi_dataset_5_body() 773{ 774 create_test_dirs 775 cd $TEST_INPUTS_DIR 776 777 mkdir dir1 778 echo a > dir1/a 779 780 cd - 781 782 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 783 -o fs=${ZFS_POOL_NAME}/dir1\;canmount=noauto\;mountpoint=legacy \ 784 $TEST_IMAGE $TEST_INPUTS_DIR 785 786 import_image 787 788 atf_check -o inline:legacy\\n \ 789 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir1 790 791 check_image_contents 792 793 atf_check zfs set mountpoint=/dir1 ${ZFS_POOL_NAME}/dir1 794 atf_check zfs mount ${ZFS_POOL_NAME}/dir1 795 atf_check -o inline:${TEST_MOUNT_DIR}/dir1\\n \ 796 zfs list -H -o mountpoint ${ZFS_POOL_NAME}/dir1 797 798 # dir1/a should be part of the root dataset, not dir1. 799 atf_check -s not-exit:0 -e not-empty stat ${TEST_MOUNT_DIR}/dir1/a 800} 801multi_dataset_5_cleanup() 802{ 803 common_cleanup 804} 805 806# 807# Validate handling of multiple staging directories. 808# 809atf_test_case multi_staging_1 cleanup 810multi_staging_1_body() 811{ 812 local tmpdir 813 814 create_test_dirs 815 cd $TEST_INPUTS_DIR 816 817 mkdir dir1 818 echo a > a 819 echo a > dir1/a 820 echo z > z 821 822 cd - 823 824 tmpdir=$(mktemp -d) 825 cd $tmpdir 826 827 mkdir dir2 dir2/dir3 828 echo b > dir2/b 829 echo c > dir2/dir3/c 830 ln -s dir2/dir3c s 831 832 cd - 833 834 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 835 $TEST_IMAGE ${TEST_INPUTS_DIR} $tmpdir 836 837 import_image 838 839 check_image_contents -d $tmpdir 840} 841multi_staging_1_cleanup() 842{ 843 common_cleanup 844} 845 846atf_test_case multi_staging_2 cleanup 847multi_staging_2_body() 848{ 849 local tmpdir 850 851 create_test_dirs 852 cd $TEST_INPUTS_DIR 853 854 mkdir dir 855 echo a > dir/foo 856 echo b > dir/bar 857 858 cd - 859 860 tmpdir=$(mktemp -d) 861 cd $tmpdir 862 863 mkdir dir 864 echo c > dir/baz 865 866 cd - 867 868 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 869 $TEST_IMAGE ${TEST_INPUTS_DIR} $tmpdir 870 871 import_image 872 873 # check_image_contents can't easily handle merged directories, so 874 # just check that the merged directory contains the files we expect. 875 atf_check -o not-empty stat ${TEST_MOUNT_DIR}/dir/foo 876 atf_check -o not-empty stat ${TEST_MOUNT_DIR}/dir/bar 877 atf_check -o not-empty stat ${TEST_MOUNT_DIR}/dir/baz 878 879 if [ "$(ls ${TEST_MOUNT_DIR}/dir | wc -l)" -ne 3 ]; then 880 atf_fail "Expected 3 files in ${TEST_MOUNT_DIR}/dir" 881 fi 882} 883multi_staging_2_cleanup() 884{ 885 common_cleanup 886} 887 888# 889# Rudimentary test to verify that two ZFS images created using the same 890# parameters and input hierarchy are byte-identical. In particular, makefs(1) 891# does not preserve file access times. 892# 893atf_test_case reproducible cleanup 894reproducible_body() 895{ 896 create_test_inputs 897 898 atf_check $MAKEFS -s 512m -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 899 ${TEST_IMAGE}.1 $TEST_INPUTS_DIR 900 901 atf_check $MAKEFS -s 512m -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 902 ${TEST_IMAGE}.2 $TEST_INPUTS_DIR 903 904 # XXX-MJ cmp(1) is really slow 905 atf_check cmp ${TEST_IMAGE}.1 ${TEST_IMAGE}.2 906} 907reproducible_cleanup() 908{ 909} 910 911# 912# Verify that we can take a snapshot of a generated dataset. 913# 914atf_test_case snapshot cleanup 915snapshot_body() 916{ 917 create_test_dirs 918 cd $TEST_INPUTS_DIR 919 920 mkdir dir 921 echo "hello" > dir/hello 922 echo "goodbye" > goodbye 923 924 cd - 925 926 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 927 $TEST_IMAGE $TEST_INPUTS_DIR 928 929 import_image 930 931 atf_check zfs snapshot ${ZFS_POOL_NAME}@1 932} 933snapshot_cleanup() 934{ 935 common_cleanup 936} 937 938# 939# Check handling of symbolic links. 940# 941atf_test_case soft_links cleanup 942soft_links_body() 943{ 944 create_test_dirs 945 cd $TEST_INPUTS_DIR 946 947 mkdir dir 948 ln -s a a 949 ln -s dir/../a a 950 ln -s dir/b b 951 echo 'c' > dir 952 ln -s dir/c c 953 # XXX-MJ overflows bonus buffer ln -s $(jot -s '' 320 1 1) 1 954 955 cd - 956 957 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 958 $TEST_IMAGE $TEST_INPUTS_DIR 959 960 import_image 961 962 check_image_contents 963} 964soft_links_cleanup() 965{ 966 common_cleanup 967} 968 969# 970# Verify that we can set properties on the root dataset. 971# 972atf_test_case root_props cleanup 973root_props_body() 974{ 975 create_test_inputs 976 977 atf_check $MAKEFS -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 978 -o fs=${ZFS_POOL_NAME}\;atime=off\;setuid=off \ 979 $TEST_IMAGE $TEST_INPUTS_DIR 980 981 import_image 982 983 check_image_contents 984 985 atf_check -o inline:off\\n zfs get -H -o value atime $ZFS_POOL_NAME 986 atf_check -o inline:local\\n zfs get -H -o source atime $ZFS_POOL_NAME 987 atf_check -o inline:off\\n zfs get -H -o value setuid $ZFS_POOL_NAME 988 atf_check -o inline:local\\n zfs get -H -o source setuid $ZFS_POOL_NAME 989} 990root_props_cleanup() 991{ 992 common_cleanup 993} 994 995# 996# Verify that usedds and usedchild props are set properly. 997# 998atf_test_case used_space_props cleanup 999used_space_props_body() 1000{ 1001 local used usedds usedchild 1002 local rootmb childmb totalmb fudge 1003 local status 1004 1005 create_test_dirs 1006 cd $TEST_INPUTS_DIR 1007 mkdir dir 1008 1009 rootmb=17 1010 childmb=39 1011 totalmb=$(($rootmb + $childmb)) 1012 fudge=$((2 * 1024 * 1024)) 1013 1014 atf_check -e ignore dd if=/dev/random of=foo bs=1M count=$rootmb 1015 atf_check -e ignore dd if=/dev/random of=dir/bar bs=1M count=$childmb 1016 1017 cd - 1018 1019 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 1020 -o fs=${ZFS_POOL_NAME}/dir \ 1021 $TEST_IMAGE $TEST_INPUTS_DIR 1022 1023 import_image 1024 1025 # Make sure that each dataset's space usage is no more than 2MB larger 1026 # than their files. This number is magic and might need to change 1027 # someday. 1028 usedds=$(zfs list -o usedds -Hp ${ZFS_POOL_NAME}) 1029 atf_check test $usedds -gt $(($rootmb * 1024 * 1024)) -a \ 1030 $usedds -le $(($rootmb * 1024 * 1024 + $fudge)) 1031 usedds=$(zfs list -o usedds -Hp ${ZFS_POOL_NAME}/dir) 1032 atf_check test $usedds -gt $(($childmb * 1024 * 1024)) -a \ 1033 $usedds -le $(($childmb * 1024 * 1024 + $fudge)) 1034 1035 # Make sure that the usedchild property value makes sense: the parent's 1036 # value corresponds to the size of the child, and the child has no 1037 # children. 1038 usedchild=$(zfs list -o usedchild -Hp ${ZFS_POOL_NAME}) 1039 atf_check test $usedchild -gt $(($childmb * 1024 * 1024)) -a \ 1040 $usedchild -le $(($childmb * 1024 * 1024 + $fudge)) 1041 atf_check -o inline:'0\n' zfs list -Hp -o usedchild ${ZFS_POOL_NAME}/dir 1042 1043 # Make sure that the used property value makes sense: the parent's 1044 # value is the sum of the two sizes, and the child's value is the 1045 # same as its usedds value, which has already been checked. 1046 used=$(zfs list -o used -Hp ${ZFS_POOL_NAME}) 1047 atf_check test $used -gt $(($totalmb * 1024 * 1024)) -a \ 1048 $used -le $(($totalmb * 1024 * 1024 + 2 * $fudge)) 1049 used=$(zfs list -o used -Hp ${ZFS_POOL_NAME}/dir) 1050 atf_check -o inline:$used'\n' zfs list -Hp -o usedds ${ZFS_POOL_NAME}/dir 1051 1052 # Both datasets do not have snapshots. 1053 atf_check -o inline:'0\n' zfs list -Hp -o usedsnap ${ZFS_POOL_NAME} 1054 atf_check -o inline:'0\n' zfs list -Hp -o usedsnap ${ZFS_POOL_NAME}/dir 1055} 1056used_space_props_cleanup() 1057{ 1058 common_cleanup 1059} 1060 1061# 1062# Test setting the path of the vdev. 1063# 1064# The pool is associated to /dev/md0 by default, i.e., when no path is specified. 1065# When the path vdevprops(7) is specified, verify it gets set. 1066# 1067atf_test_case path_vdev_props cleanup 1068path_vdev_props_body() 1069{ 1070 local md zdb_path 1071 local vdev_path="/dev/gpt/testdisk" 1072 1073 create_test_inputs 1074 1075 atf_check $MAKEFS -s 1g -o rootpath=/ \ 1076 -o poolname=$ZFS_POOL_NAME \ 1077 -o path=${vdev_path} \ 1078 $TEST_IMAGE $TEST_INPUTS_DIR 1079 1080 # Check the raw path property before import_image. 1081 atf_check -o save:$TEST_MD_DEVICE_FILE mdconfig -a -f $TEST_IMAGE 1082 zdb_path=$(zdb -C -e -p /dev/$(cat $TEST_MD_DEVICE_FILE) \ 1083 $ZFS_POOL_NAME 2>/dev/null | awk -F"'" '/path:/ {print $2; exit}') 1084 atf_check -o inline:"${vdev_path}\n" echo "$zdb_path" 1085 1086 # Cleanup before import_image. 1087 if [ -f "$TEST_MD_DEVICE_FILE" ]; then 1088 md=$(cat $TEST_MD_DEVICE_FILE) 1089 if [ -c /dev/"$md" ]; then 1090 mdconfig -o force -d -u "$md" 1091 fi 1092 fi 1093 1094 # Once imported, the path will be /dev/$(cat $TEST_MD_DEVICE_FILE), 1095 # as /dev/gpt/testdisk does not really exist. 1096 import_image 1097 1098 check_image_contents 1099} 1100path_vdev_props_cleanup() 1101{ 1102 common_cleanup 1103} 1104 1105# Verify that file permissions are set properly. Make sure that non-executable 1106# files can't be executed. 1107atf_test_case perms cleanup 1108perms_body() 1109{ 1110 local mode 1111 1112 create_test_dirs 1113 cd $TEST_INPUTS_DIR 1114 1115 for mode in $(seq 0 511); do 1116 mode=$(printf "%04o\n" $mode) 1117 echo 'echo a' > $mode 1118 atf_check chmod $mode $mode 1119 done 1120 1121 cd - 1122 1123 atf_check $MAKEFS -s 1g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 1124 $TEST_IMAGE $TEST_INPUTS_DIR 1125 1126 import_image 1127 1128 check_image_contents 1129 1130 for mode in $(seq 0 511); do 1131 mode=$(printf "%04o\n" $mode) 1132 if [ $(($mode & 0111)) -eq 0 ]; then 1133 atf_check -s not-exit:0 -e match:"Permission denied" \ 1134 ${TEST_INPUTS_DIR}/$mode 1135 fi 1136 if [ $(($mode & 0001)) -eq 0 ]; then 1137 atf_check -s not-exit:0 -e match:"Permission denied" \ 1138 su -m tests -c ${TEST_INPUTS_DIR}/$mode 1139 fi 1140 done 1141} 1142perms_cleanup() 1143{ 1144 common_cleanup 1145} 1146 1147# 1148# Verify that -T timestamps are honored. 1149# 1150atf_test_case T_flag_dir cleanup 1151T_flag_dir_body() 1152{ 1153 timestamp=1742574909 1154 create_test_dirs 1155 mkdir -p $TEST_INPUTS_DIR/dir1 1156 1157 atf_check $MAKEFS -T $timestamp -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 1158 $TEST_IMAGE $TEST_INPUTS_DIR 1159 1160 import_image 1161 eval $(stat -s $TEST_MOUNT_DIR/dir1) 1162 atf_check_equal $st_atime $timestamp 1163 atf_check_equal $st_mtime $timestamp 1164 atf_check_equal $st_ctime $timestamp 1165} 1166 1167T_flag_dir_cleanup() 1168{ 1169 common_cleanup 1170} 1171 1172atf_test_case T_flag_F_flag cleanup 1173T_flag_F_flag_body() 1174{ 1175 timestamp_F=1742574909 1176 timestamp_T=1742574910 1177 create_test_dirs 1178 mkdir -p $TEST_INPUTS_DIR/dir1 1179 1180 atf_check -o save:$TEST_SPEC_FILE $MTREE -c -p $TEST_INPUTS_DIR 1181 change_mtree_timestamp $TEST_SPEC_FILE $timestamp_F 1182 atf_check \ 1183 $MAKEFS -F $TEST_SPEC_FILE -T $timestamp_T -s 10g -o rootpath=/ \ 1184 -o poolname=$ZFS_POOL_NAME $TEST_IMAGE $TEST_INPUTS_DIR 1185 1186 import_image 1187 eval $(stat -s $TEST_MOUNT_DIR/dir1) 1188 atf_check_equal $st_atime $timestamp_F 1189 atf_check_equal $st_mtime $timestamp_F 1190 # atf_check_equal $st_ctime $timestamp_F 1191} 1192 1193T_flag_F_flag_cleanup() 1194{ 1195 common_cleanup 1196} 1197 1198atf_test_case T_flag_mtree cleanup 1199T_flag_mtree_body() 1200{ 1201 timestamp=1742574909 1202 create_test_dirs 1203 mkdir -p $TEST_INPUTS_DIR/dir1 1204 1205 atf_check -o save:$TEST_SPEC_FILE $MTREE -c -p $TEST_INPUTS_DIR 1206 atf_check $MAKEFS -T $timestamp -s 10g -o rootpath=/ -o poolname=$ZFS_POOL_NAME \ 1207 $TEST_IMAGE $TEST_SPEC_FILE 1208 1209 import_image 1210 eval $(stat -s $TEST_MOUNT_DIR/dir1) 1211 atf_check_equal $st_atime $timestamp 1212 atf_check_equal $st_mtime $timestamp 1213 atf_check_equal $st_ctime $timestamp 1214} 1215 1216T_flag_mtree_cleanup() 1217{ 1218 common_cleanup 1219} 1220 1221atf_init_test_cases() 1222{ 1223 atf_add_test_case autoexpand 1224 atf_add_test_case autotrim 1225 atf_add_test_case basic 1226 atf_add_test_case compression 1227 atf_add_test_case dataset_link_counts 1228 atf_add_test_case dataset_removal 1229 atf_add_test_case devfs 1230 atf_add_test_case empty_dir 1231 atf_add_test_case empty_fs 1232 atf_add_test_case file_extend 1233 atf_add_test_case file_sizes 1234 atf_add_test_case hard_links 1235 atf_add_test_case indirect_dnode_array 1236 atf_add_test_case long_file_name 1237 atf_add_test_case multi_dataset_1 1238 atf_add_test_case multi_dataset_2 1239 atf_add_test_case multi_dataset_3 1240 atf_add_test_case multi_dataset_4 1241 atf_add_test_case multi_dataset_5 1242 atf_add_test_case multi_staging_1 1243 atf_add_test_case multi_staging_2 1244 atf_add_test_case reproducible 1245 atf_add_test_case snapshot 1246 atf_add_test_case soft_links 1247 atf_add_test_case root_props 1248 atf_add_test_case used_space_props 1249 atf_add_test_case path_vdev_props 1250 atf_add_test_case perms 1251 atf_add_test_case T_flag_dir 1252 atf_add_test_case T_flag_F_flag 1253 atf_add_test_case T_flag_mtree 1254 1255 # XXXMJ tests: 1256 # - test with different ashifts (at least, 9 and 12), different image sizes 1257 # - create datasets in imported pool 1258} 1259