diff options
Diffstat (limited to 'sys/contrib/openzfs/tests')
51 files changed, 2884 insertions, 196 deletions
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run index 2da46458289a..9f531411fbe1 100644 --- a/sys/contrib/openzfs/tests/runfiles/common.run +++ b/sys/contrib/openzfs/tests/runfiles/common.run @@ -168,10 +168,10 @@ tags = ['functional', 'cli_root', 'zinject'] tests = ['zdb_002_pos', 'zdb_003_pos', 'zdb_004_pos', 'zdb_005_pos', 'zdb_006_pos', 'zdb_args_neg', 'zdb_args_pos', 'zdb_block_size_histogram', 'zdb_checksum', 'zdb_decompress', - 'zdb_display_block', 'zdb_encrypted', 'zdb_label_checksum', - 'zdb_object_range_neg', 'zdb_object_range_pos', 'zdb_objset_id', - 'zdb_decompress_zstd', 'zdb_recover', 'zdb_recover_2', 'zdb_backup', - 'zdb_tunables'] + 'zdb_display_block', 'zdb_encrypted', 'zdb_encrypted_raw', + 'zdb_label_checksum', 'zdb_object_range_neg', 'zdb_object_range_pos', + 'zdb_objset_id', 'zdb_decompress_zstd', 'zdb_recover', 'zdb_recover_2', + 'zdb_backup', 'zdb_tunables'] pre = post = tags = ['functional', 'cli_root', 'zdb'] @@ -323,6 +323,10 @@ tests = ['zfs_send_001_pos', 'zfs_send_002_pos', 'zfs_send_003_pos', 'zfs_send_raw', 'zfs_send_sparse', 'zfs_send-b', 'zfs_send_skip_missing'] tags = ['functional', 'cli_root', 'zfs_send'] +[tests/functional/cli_root/zfs_send_delegation] +tests = ['zfs_send_test'] +tags = ['functional', 'cli_root', 'zfs_send_delegation'] + [tests/functional/cli_root/zfs_set] tests = ['cache_001_pos', 'cache_002_neg', 'canmount_001_pos', 'canmount_002_pos', 'canmount_003_pos', 'canmount_004_pos', @@ -379,7 +383,7 @@ tags = ['functional', 'cli_root', 'zfs_wait'] [tests/functional/cli_root/zhack] tests = ['zhack_label_repair_001', 'zhack_label_repair_002', - 'zhack_label_repair_003', 'zhack_label_repair_004'] + 'zhack_label_repair_003', 'zhack_label_repair_004', 'zhack_metaslab_leak'] pre = post = tags = ['functional', 'cli_root', 'zhack'] @@ -391,8 +395,9 @@ tags = ['functional', 'cli_root', 'zpool'] [tests/functional/cli_root/zpool_add] tests = ['zpool_add_001_pos', 'zpool_add_002_pos', 'zpool_add_003_pos', 'zpool_add_004_pos', 'zpool_add_006_pos', 'zpool_add_007_neg', - 'zpool_add_008_neg', 'zpool_add_009_neg', 'zpool_add_010_pos', - 'add-o_ashift', 'add_prop_ashift', 'zpool_add_dryrun_output'] + 'zpool_add_008_neg', 'zpool_add_009_neg', 'zpool_add_warn_create', + 'zpool_add_warn_degraded', 'zpool_add_warn_removal', 'add-o_ashift', + 'add_prop_ashift', 'zpool_add_dryrun_output'] tags = ['functional', 'cli_root', 'zpool_add'] [tests/functional/cli_root/zpool_attach] @@ -486,6 +491,10 @@ tests = ['zpool_import_001_pos', 'zpool_import_002_pos', tags = ['functional', 'cli_root', 'zpool_import'] timeout = 1200 +[tests/functional/cli_root/zpool_iostat] +tests = ['zpool_iostat_interval_all', 'zpool_iostat_interval_some'] +tags = ['functional', 'cli_root', 'zpool_iostat'] + [tests/functional/cli_root/zpool_labelclear] tests = ['zpool_labelclear_active', 'zpool_labelclear_exported', 'zpool_labelclear_removed', 'zpool_labelclear_valid'] @@ -546,7 +555,7 @@ tests = ['zpool_scrub_001_neg', 'zpool_scrub_002_pos', 'zpool_scrub_003_pos', 'zpool_scrub_multiple_pools', 'zpool_error_scrub_001_pos', 'zpool_error_scrub_002_pos', 'zpool_error_scrub_003_pos', 'zpool_error_scrub_004_pos', - 'zpool_scrub_date_range_001'] + 'zpool_scrub_date_range_001', 'zpool_scrub_date_range_002'] tags = ['functional', 'cli_root', 'zpool_scrub'] [tests/functional/cli_root/zpool_set] @@ -624,8 +633,8 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg', 'zpool_history_001_neg', 'zpool_import_001_neg', 'zpool_import_002_neg', 'zpool_offline_001_neg', 'zpool_online_001_neg', 'zpool_remove_001_neg', 'zpool_replace_001_neg', 'zpool_scrub_001_neg', 'zpool_set_001_neg', - 'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'arcstat_001_pos', - 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege', + 'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'zarcstat_001_pos', + 'zarcsummary_001_pos', 'zarcsummary_002_neg', 'zpool_wait_privilege', 'zilstat_001_pos'] user = tags = ['functional', 'cli_user', 'misc'] @@ -637,6 +646,10 @@ tests = ['zfs_list_001_pos', 'zfs_list_002_pos', 'zfs_list_003_pos', user = tags = ['functional', 'cli_user', 'zfs_list'] +[tests/functional/cli_user/zfs_send_delegation_user] +tests = ['zfs_send_usertest'] +tags = ['functional', 'cli_user', 'zfs_send_delegation_user'] + [tests/functional/cli_user/zpool_iostat] tests = ['zpool_iostat_001_neg', 'zpool_iostat_002_pos', 'zpool_iostat_003_neg', 'zpool_iostat_004_pos', @@ -940,10 +953,11 @@ tags = ['functional', 'rename_dirs'] [tests/functional/replacement] tests = ['attach_import', 'attach_multiple', 'attach_rebuild', - 'attach_resilver', 'detach', 'rebuild_disabled_feature', - 'rebuild_multiple', 'rebuild_raidz', 'replace_import', 'replace_rebuild', - 'replace_resilver', 'resilver_restart_001', 'resilver_restart_002', - 'scrub_cancel'] + 'attach_resilver', 'attach_resilver_sit_out', 'detach', + 'rebuild_disabled_feature', 'rebuild_multiple', 'rebuild_raidz', + 'replace_import', 'replace_rebuild', 'replace_resilver', + 'replace_resilver_sit_out', 'resilver_restart_001', + 'resilver_restart_002', 'scrub_cancel'] tags = ['functional', 'replacement'] [tests/functional/reservation] @@ -1076,7 +1090,8 @@ tags = ['functional', 'write_dirs'] [tests/functional/xattr] tests = ['xattr_001_pos', 'xattr_002_neg', 'xattr_003_neg', 'xattr_004_pos', 'xattr_005_pos', 'xattr_006_pos', 'xattr_007_neg', - 'xattr_011_pos', 'xattr_012_pos', 'xattr_013_pos', 'xattr_compat'] + 'xattr_011_pos', 'xattr_012_pos', 'xattr_013_pos', 'xattr_014_pos', + 'xattr_compat'] tags = ['functional', 'xattr'] [tests/functional/zvol/zvol_ENOSPC] diff --git a/sys/contrib/openzfs/tests/runfiles/linux.run b/sys/contrib/openzfs/tests/runfiles/linux.run index f3d56acffde0..339361cc2762 100644 --- a/sys/contrib/openzfs/tests/runfiles/linux.run +++ b/sys/contrib/openzfs/tests/runfiles/linux.run @@ -109,7 +109,9 @@ tags = ['functional', 'direct'] [tests/functional/events:Linux] tests = ['events_001_pos', 'events_002_pos', 'zed_rc_filter', 'zed_fd_spill', 'zed_cksum_reported', 'zed_cksum_config', 'zed_io_config', - 'zed_slow_io', 'zed_slow_io_many_vdevs', 'zed_diagnose_multiple'] + 'zed_slow_io', 'zed_slow_io_many_vdevs', 'zed_diagnose_multiple', + 'zed_synchronous_zedlet', 'slow_vdev_sit_out', 'slow_vdev_sit_out_neg', + 'slow_vdev_degraded_sit_out'] tags = ['functional', 'events'] [tests/functional/fallocate:Linux] @@ -161,7 +163,7 @@ tests = ['mmp_on_thread', 'mmp_on_uberblocks', 'mmp_on_off', 'mmp_interval', tags = ['functional', 'mmp'] [tests/functional/mount:Linux] -tests = ['umount_unlinked_drain'] +tests = ['umount_unlinked_drain', 'mount_loopback'] tags = ['functional', 'mount'] [tests/functional/pam:Linux] diff --git a/sys/contrib/openzfs/tests/runfiles/sanity.run b/sys/contrib/openzfs/tests/runfiles/sanity.run index 7767c0c2d535..249b415029c4 100644 --- a/sys/contrib/openzfs/tests/runfiles/sanity.run +++ b/sys/contrib/openzfs/tests/runfiles/sanity.run @@ -400,8 +400,8 @@ tests = ['zdb_001_neg', 'zfs_001_neg', 'zfs_allow_001_neg', 'zpool_detach_001_neg', 'zpool_export_001_neg', 'zpool_get_001_neg', 'zpool_history_001_neg', 'zpool_offline_001_neg', 'zpool_online_001_neg', 'zpool_remove_001_neg', 'zpool_scrub_001_neg', 'zpool_set_001_neg', - 'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'arcstat_001_pos', - 'arc_summary_001_pos', 'arc_summary_002_neg', 'zpool_wait_privilege', + 'zpool_status_001_neg', 'zpool_upgrade_001_neg', 'zarcstat_001_pos', + 'zarcsummary_001_pos', 'zarcsummary_002_neg', 'zpool_wait_privilege', 'zilstat_001_pos'] user = tags = ['functional', 'cli_user', 'misc'] @@ -622,7 +622,7 @@ tags = ['functional', 'vdev_zaps'] [tests/functional/xattr] tests = ['xattr_001_pos', 'xattr_002_neg', 'xattr_003_neg', 'xattr_004_pos', 'xattr_005_pos', 'xattr_006_pos', 'xattr_007_neg', - 'xattr_011_pos', 'xattr_013_pos', 'xattr_compat'] + 'xattr_011_pos', 'xattr_013_pos', 'xattr_014_pos', 'xattr_compat'] tags = ['functional', 'xattr'] [tests/functional/zvol/zvol_ENOSPC] diff --git a/sys/contrib/openzfs/tests/test-runner/bin/test-runner.py.in b/sys/contrib/openzfs/tests/test-runner/bin/test-runner.py.in index 2158208be6e5..d2c1185e4a94 100755 --- a/sys/contrib/openzfs/tests/test-runner/bin/test-runner.py.in +++ b/sys/contrib/openzfs/tests/test-runner/bin/test-runner.py.in @@ -34,6 +34,7 @@ from select import select from subprocess import PIPE from subprocess import Popen from subprocess import check_output +from subprocess import run from threading import Timer from time import time, CLOCK_MONOTONIC from os.path import exists @@ -187,6 +188,63 @@ User: %s ''' % (self.pathname, self.identifier, self.outputdir, self.timeout, self.user) def kill_cmd(self, proc, options, kmemleak, keyboard_interrupt=False): + + """ + We're about to kill a command due to a timeout. + If we're running with the -O option, then dump debug info about the + process with the highest CPU usage to /dev/kmsg (Linux only). This can + help debug the timeout. + + Debug info includes: + - 30 lines from 'top' + - /proc/<PID>/stack output of process with highest CPU usage + - Last lines strace-ing process with highest CPU usage + """ + if exists("/dev/kmsg"): + c = """ +TOP_OUT="$(COLUMNS=160 top -b -n 1 | head -n 30)" +read -r PID CMD <<< $(echo "$TOP_OUT" | /usr/bin/awk \ +"/COMMAND/{ + print_next=1 + next +} +{ + if (print_next == 1) { + print \\$1\\" \\"\\$12 + exit + } +}") +echo "##### ZTS timeout debug #####" +echo "----- top -----" +echo "$TOP_OUT" +echo "----- /proc/$PID/stack ($CMD)) -----" +cat /proc/$PID/stack +echo "----- strace ($CMD) -----" +TMPFILE="$(mktemp --suffix=ZTS)" +/usr/bin/strace -k --stack-traces -p $PID &> "$TMPFILE" & +sleep 0.1 +killall strace +tail -n 30 $TMPFILE +rm "$TMPFILE" +echo "##### /proc/sysrq-trigger stack #####" +""" + c = "sudo bash -c '" + c + "'" + data = run(c, capture_output=True, shell=True, text=True) + out = data.stdout + try: + kp = Popen([SUDO, "sh", "-c", + "echo '" + out + "' > /dev/kmsg"]) + kp.wait() + + """ + Trigger kernel stack traces + """ + kp = Popen([SUDO, "sh", "-c", + "echo l > /proc/sysrq-trigger"]) + kp.wait() + except Exception: + pass + """ Kill a running command due to timeout, or ^C from the keyboard. If sudo is required, this user was verified previously. @@ -1129,6 +1187,9 @@ def parse_args(): parser.add_option('-o', action='callback', callback=options_cb, default=BASEDIR, dest='outputdir', type='string', metavar='outputdir', help='Specify an output directory.') + parser.add_option('-O', action='store_true', default=False, + dest='timeout_debug', + help='Dump debugging info to /dev/kmsg on test timeout') parser.add_option('-i', action='callback', callback=options_cb, default=TESTDIR, dest='testdir', type='string', metavar='testdir', help='Specify a test directory.') diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in index 001970120148..5bc65f993734 100755 --- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in +++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in @@ -232,7 +232,7 @@ maybe = { 'cli_root/zpool_trim/zpool_trim_fault_export_import_online': ['FAIL', known_reason], 'cli_root/zpool_upgrade/zpool_upgrade_004_pos': ['FAIL', 6141], - 'cli_user/misc/arc_summary_001_pos': ['FAIL', known_reason], + 'cli_user/misc/zarcsummary_001_pos': ['FAIL', known_reason], 'delegate/setup': ['SKIP', exec_reason], 'events/zed_cksum_config': ['FAIL', known_reason], 'fault/auto_replace_002_pos': ['FAIL', known_reason], diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/crypto_test.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/crypto_test.c index cbebd33e0bf6..c8d8622c7571 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/cmd/crypto_test.c +++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/crypto_test.c @@ -863,7 +863,8 @@ test_result(const crypto_test_t *test, int encrypt_rv, uint8_t *encrypt_buf, return (pass); /* print summary of test result */ - printf("%s[%lu]: encrypt=%s decrypt=%s\n", test->fileloc, test->id, + printf("%s[%ju]: encrypt=%s decrypt=%s\n", test->fileloc, + (uintmax_t)test->id, encrypt_pass ? "PASS" : "FAIL", decrypt_pass ? "PASS" : "FAIL"); diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg index 884a99d785bc..1c4d25e152a7 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg @@ -100,6 +100,7 @@ export SYSTEM_FILES_COMMON='awk uniq vmstat wc + which xargs xxh128sum' @@ -146,6 +147,7 @@ export SYSTEM_FILES_LINUX='attr lscpu lsmod lsscsi + mkfs.xfs mkswap modprobe mountpoint @@ -169,8 +171,8 @@ export ZFS_FILES='zdb zpool ztest raidz_test - arc_summary - arcstat + zarcsummary + zarcstat zilstat dbufstat mount.zfs diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib index 23e89599cae0..8b30b9b91641 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib +++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib @@ -1085,7 +1085,7 @@ function fill_fs # destdir dirnum filenum bytes num_writes data typeset -i filenum=${3:-50} typeset -i bytes=${4:-8192} typeset -i num_writes=${5:-10240} - typeset data=${6:-0} + typeset data=${6:-"R"} mkdir -p $destdir/{1..$dirnum} for f in $destdir/{1..$dirnum}/$TESTFILE{1..$filenum}; do @@ -1112,6 +1112,16 @@ function get_pool_prop # property pool zpool get -Hpo value "$prop" "$pool" || log_fail "zpool get $prop $pool" } +# Get the specified vdev property in parsable format or fail +function get_vdev_prop +{ + typeset prop="$1" + typeset pool="$2" + typeset vdev="$3" + + zpool get -Hpo value "$prop" "$pool" "$vdev" || log_fail "zpool get $prop $pool $vdev" +} + # Return 0 if a pool exists; $? otherwise # # $1 - pool name @@ -1971,6 +1981,28 @@ function wait_vdev_state # pool disk state timeout } # +# Wait for vdev 'sit_out' property to be cleared. +# +# $1 pool name +# $2 vdev name +# $3 timeout +# +function wait_sit_out #pool vdev timeout +{ + typeset pool=${1:-$TESTPOOL} + typeset vdev="$2" + typeset timeout=${3:-300} + for (( timer = 0; timer < $timeout; timer++ )); do + if [ "$(get_vdev_prop sit_out "$pool" "$vdev")" = "off" ]; then + return 0 + fi + sleep 1; + done + + return 1 +} + +# # Check the output of 'zpool status -v <pool>', # and to see if the content of <token> contain the <keyword> specified. # @@ -2881,6 +2913,28 @@ function user_run log_note "user: $user" log_note "cmd: $*" + if ! sudo -Eu $user test -x $PATH ; then + log_note "-------------------------------------------------" + log_note "Warning: $user doesn't have permissions on $PATH" + log_note "" + log_note "This usually happens when you're running ZTS locally" + log_note "from inside the ZFS source dir, and are attempting to" + log_note "run a test that calls user_run. The ephemeral user" + log_note "($user) that ZTS is creating does not have permission" + log_note "to traverse to $PATH, or the binaries in $PATH are" + log_note "not the right permissions." + log_note "" + log_note "To get around this, copy your ZFS source directory" + log_note "to a world-accessible location (like /tmp), and " + log_note "change the permissions on your ZFS source dir " + log_note "to allow access." + log_note "" + log_note "Also, verify that /dev/zfs is RW for others:" + log_note "" + log_note " sudo chmod o+rw /dev/zfs" + log_note "-------------------------------------------------" + fi + typeset out=$TEST_BASE_DIR/out typeset err=$TEST_BASE_DIR/err diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg index e273c9f85c28..127ea188f17f 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg +++ b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg @@ -72,6 +72,9 @@ MULTIHOST_INTERVAL multihost.interval zfs_multihost_interval OVERRIDE_ESTIMATE_RECORDSIZE send.override_estimate_recordsize zfs_override_estimate_recordsize PREFETCH_DISABLE prefetch.disable zfs_prefetch_disable RAIDZ_EXPAND_MAX_REFLOW_BYTES vdev.expand_max_reflow_bytes raidz_expand_max_reflow_bytes +READ_SIT_OUT_SECS vdev.read_sit_out_secs vdev_read_sit_out_secs +SIT_OUT_CHECK_INTERVAL vdev.raidz_outlier_check_interval_ms vdev_raidz_outlier_check_interval_ms +SIT_OUT_INSENSITIVITY vdev.raidz_outlier_insensitivity vdev_raidz_outlier_insensitivity REBUILD_SCRUB_ENABLED rebuild_scrub_enabled zfs_rebuild_scrub_enabled REMOVAL_SUSPEND_PROGRESS removal_suspend_progress zfs_removal_suspend_progress REMOVE_MAX_SEGMENT remove_max_segment zfs_remove_max_segment @@ -88,6 +91,7 @@ SPA_DISCARD_MEMORY_LIMIT spa.discard_memory_limit zfs_spa_discard_memory_limit SPA_LOAD_VERIFY_DATA spa.load_verify_data spa_load_verify_data SPA_LOAD_VERIFY_METADATA spa.load_verify_metadata spa_load_verify_metadata SPA_NOTE_TXG_TIME spa.note_txg_time spa_note_txg_time +SPA_FLUSH_TXG_TIME spa.flush_txg_time spa_flush_txg_time TRIM_EXTENT_BYTES_MIN trim.extent_bytes_min zfs_trim_extent_bytes_min TRIM_METASLAB_SKIP trim.metaslab_skip zfs_trim_metaslab_skip TRIM_TXG_BATCH trim.txg_batch zfs_trim_txg_batch diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am index 41e7b45ef4ec..678c01b58f94 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am @@ -197,6 +197,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \ functional/cli_root/zpool_import/blockfiles/unclean_export.dat.bz2 \ functional/cli_root/zpool_import/zpool_import.cfg \ functional/cli_root/zpool_import/zpool_import.kshlib \ + functional/cli_root/zpool_iostat/zpool_iostat.kshlib \ functional/cli_root/zpool_initialize/zpool_initialize.kshlib \ functional/cli_root/zpool_labelclear/labelclear.cfg \ functional/cli_root/zpool_remove/zpool_remove.cfg \ @@ -640,6 +641,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zdb/zdb_decompress_zstd.ksh \ functional/cli_root/zdb/zdb_display_block.ksh \ functional/cli_root/zdb/zdb_encrypted.ksh \ + functional/cli_root/zdb/zdb_encrypted_raw.ksh \ functional/cli_root/zdb/zdb_label_checksum.ksh \ functional/cli_root/zdb/zdb_object_range_neg.ksh \ functional/cli_root/zdb/zdb_object_range_pos.ksh \ @@ -892,6 +894,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zfs_send/zfs_send_raw.ksh \ functional/cli_root/zfs_send/zfs_send_skip_missing.ksh \ functional/cli_root/zfs_send/zfs_send_sparse.ksh \ + functional/cli_root/zfs_send_delegation/cleanup.ksh \ + functional/cli_root/zfs_send_delegation/setup.ksh \ + functional/cli_root/zfs_send_delegation/zfs_send_test.ksh \ functional/cli_root/zfs_set/cache_001_pos.ksh \ functional/cli_root/zfs_set/cache_002_neg.ksh \ functional/cli_root/zfs_set/canmount_001_pos.ksh \ @@ -1009,6 +1014,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zhack/zhack_label_repair_002.ksh \ functional/cli_root/zhack/zhack_label_repair_003.ksh \ functional/cli_root/zhack/zhack_label_repair_004.ksh \ + functional/cli_root/zhack/zhack_metaslab_leak.ksh \ functional/cli_root/zpool_add/add_nested_replacing_spare.ksh \ functional/cli_root/zpool_add/add-o_ashift.ksh \ functional/cli_root/zpool_add/add_prop_ashift.ksh \ @@ -1023,7 +1029,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_add/zpool_add_007_neg.ksh \ functional/cli_root/zpool_add/zpool_add_008_neg.ksh \ functional/cli_root/zpool_add/zpool_add_009_neg.ksh \ - functional/cli_root/zpool_add/zpool_add_010_pos.ksh \ + functional/cli_root/zpool_add/zpool_add_warn_create.ksh \ + functional/cli_root/zpool_add/zpool_add_warn_degraded.ksh \ + functional/cli_root/zpool_add/zpool_add_warn_removal.ksh \ functional/cli_root/zpool_add/zpool_add_dryrun_output.ksh \ functional/cli_root/zpool_attach/attach-o_ashift.ksh \ functional/cli_root/zpool_attach/cleanup.ksh \ @@ -1174,6 +1182,10 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_import/zpool_import_parallel_admin.ksh \ functional/cli_root/zpool_import/zpool_import_parallel_neg.ksh \ functional/cli_root/zpool_import/zpool_import_parallel_pos.ksh \ + functional/cli_root/zpool_iostat/setup.ksh \ + functional/cli_root/zpool_iostat/cleanup.ksh \ + functional/cli_root/zpool_iostat/zpool_iostat_interval_all.ksh \ + functional/cli_root/zpool_iostat/zpool_iostat_interval_some.ksh \ functional/cli_root/zpool_initialize/cleanup.ksh \ functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh \ functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh \ @@ -1247,6 +1259,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool_scrub/zpool_scrub_print_repairing.ksh \ functional/cli_root/zpool_scrub/zpool_scrub_txg_continue_from_last.ksh \ functional/cli_root/zpool_scrub/zpool_scrub_date_range_001.ksh \ + functional/cli_root/zpool_scrub/zpool_scrub_date_range_002.ksh \ functional/cli_root/zpool_scrub/zpool_error_scrub_001_pos.ksh \ functional/cli_root/zpool_scrub/zpool_error_scrub_002_pos.ksh \ functional/cli_root/zpool_scrub/zpool_error_scrub_003_pos.ksh \ @@ -1351,9 +1364,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_root/zpool/zpool_002_pos.ksh \ functional/cli_root/zpool/zpool_003_pos.ksh \ functional/cli_root/zpool/zpool_colors.ksh \ - functional/cli_user/misc/arcstat_001_pos.ksh \ - functional/cli_user/misc/arc_summary_001_pos.ksh \ - functional/cli_user/misc/arc_summary_002_neg.ksh \ + functional/cli_user/misc/zarcstat_001_pos.ksh \ + functional/cli_user/misc/zarcsummary_001_pos.ksh \ + functional/cli_user/misc/zarcsummary_002_neg.ksh \ functional/cli_user/misc/zilstat_001_pos.ksh \ functional/cli_user/misc/cleanup.ksh \ functional/cli_user/misc/setup.ksh \ @@ -1408,6 +1421,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/cli_user/zfs_list/zfs_list_005_neg.ksh \ functional/cli_user/zfs_list/zfs_list_007_pos.ksh \ functional/cli_user/zfs_list/zfs_list_008_neg.ksh \ + functional/cli_user/zfs_send_delegation_user/cleanup.ksh \ + functional/cli_user/zfs_send_delegation_user/setup.ksh \ + functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh \ functional/cli_user/zpool_iostat/cleanup.ksh \ functional/cli_user/zpool_iostat/setup.ksh \ functional/cli_user/zpool_iostat/zpool_iostat_001_neg.ksh \ @@ -1524,6 +1540,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/events/events_001_pos.ksh \ functional/events/events_002_pos.ksh \ functional/events/setup.ksh \ + functional/events/slow_vdev_degraded_sit_out.ksh \ + functional/events/slow_vdev_sit_out.ksh \ + functional/events/slow_vdev_sit_out_neg.ksh \ functional/events/zed_cksum_config.ksh \ functional/events/zed_cksum_reported.ksh \ functional/events/zed_diagnose_multiple.ksh \ @@ -1532,6 +1551,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/events/zed_rc_filter.ksh \ functional/events/zed_slow_io.ksh \ functional/events/zed_slow_io_many_vdevs.ksh \ + functional/events/zed_synchronous_zedlet.ksh \ functional/exec/cleanup.ksh \ functional/exec/exec_001_pos.ksh \ functional/exec/exec_002_neg.ksh \ @@ -1706,6 +1726,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/mmp/setup.ksh \ functional/mount/cleanup.ksh \ functional/mount/setup.ksh \ + functional/mount/mount_loopback.ksh \ functional/mount/umount_001.ksh \ functional/mount/umountall_001.ksh \ functional/mount/umount_unlinked_drain.ksh \ @@ -1935,6 +1956,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/replacement/attach_multiple.ksh \ functional/replacement/attach_rebuild.ksh \ functional/replacement/attach_resilver.ksh \ + functional/replacement/attach_resilver_sit_out.ksh \ functional/replacement/cleanup.ksh \ functional/replacement/detach.ksh \ functional/replacement/rebuild_disabled_feature.ksh \ @@ -1943,6 +1965,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/replacement/replace_import.ksh \ functional/replacement/replace_rebuild.ksh \ functional/replacement/replace_resilver.ksh \ + functional/replacement/replace_resilver_sit_out.ksh \ functional/replacement/resilver_restart_001.ksh \ functional/replacement/resilver_restart_002.ksh \ functional/replacement/scrub_cancel.ksh \ @@ -2211,6 +2234,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/xattr/xattr_011_pos.ksh \ functional/xattr/xattr_012_pos.ksh \ functional/xattr/xattr_013_pos.ksh \ + functional/xattr/xattr_014_pos.ksh \ functional/xattr/xattr_compat.ksh \ functional/zap_shrink/cleanup.ksh \ functional/zap_shrink/zap_shrink_001_pos.ksh \ diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted_raw.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted_raw.ksh new file mode 100755 index 000000000000..85d267d5402f --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_encrypted_raw.ksh @@ -0,0 +1,75 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# +# CDDL HEADER END +# + +# +# Copyright (c) 2023, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib + +# +# DESCRIPTION: +# 'zdb -K ...' should enable reading from a raw-encrypted dataset +# +# STRATEGY: +# 1. Create an encrypted dataset +# 2. Write some data to a file +# 3. Run zdb -dddd on the file, confirm it can't be read +# 4. Run zdb -K ... -ddddd on the file, confirm it can be read +# + +verify_runnable "both" + +dataset="$TESTPOOL/$TESTFS2" +file="$TESTDIR2/somefile" +keyfile="$TEST_BASE_DIR/keyfile" + +function cleanup +{ + datasetexists "$dataset" && destroy_dataset "$dataset" -f + rm -f "$keyfile" + default_cleanup_noexit +} + +log_onexit cleanup + +log_must default_setup_noexit $DISKS + +log_assert "'zdb -K' should enable reading from a raw-encrypted dataset" + +# The key must be 32 bytes long. +echo -n "$RAWKEY" > "$keyfile" + +log_must zfs create -o mountpoint="$TESTDIR2" \ + -o encryption=on -o keyformat=raw -o keylocation="file://$keyfile" \ + "$dataset" + +echo 'my great encrypted text' > "$file" + +typeset -i obj=$(ls -i "$file" | cut -d' ' -f1) +typeset -i size=$(wc -c < "$file") + +log_note "test file $file is objid $obj, size $size" + +sync_pool "$TESTPOOL" true + +log_must eval "zdb -dddd $dataset $obj | grep -q 'object encrypted'" + +log_must eval "zdb -K $keyfile -dddd $dataset $obj | grep -q 'size\s$size$'" + +log_pass "'zdb -K' enables reading from a raw-encrypted dataset" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh index 46965aa7cc37..b89790d5d525 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh @@ -63,7 +63,7 @@ log_mustnot_expect 'no such tunable: 0' zdb -o show=0 log_mustnot_expect 'no such tunable: 1' zdb -o info=1 # can set multiple in same command -log_must eval 'zdb -o zfs_recover=1 -o zfs_flags=512 | xargs | grep -qE "^zfs_recover: 0 -> 1 zfs_flags: 4294965758 -> 512$"' +log_must eval 'zdb -o zfs_recover=1 -o zfs_flags=512 | xargs | grep -qE "^zfs_recover: 0 -> 1 zfs_flags: 4294932990 -> 512$"' # can set and show in same command log_must eval 'zdb -o zfs_recover=1 -o zfs_recover -o zfs_recover=0 | xargs | grep -qE "^zfs_recover: 0 -> 1 zfs_recover: 1 zfs_recover: 1 -> 0$"' diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/cleanup.ksh new file mode 100755 index 000000000000..4a59e15cc693 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/cleanup.ksh @@ -0,0 +1,43 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib + + +poolexists $TESTPOOL1 && \ + destroy_pool $TESTPOOL1 + +del_user $STAFF1 +del_user $STAFF2 +del_group $STAFF_GROUP + +del_user $OTHER1 +del_user $OTHER2 +del_group $OTHER_GROUP + +default_cleanup diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/setup.ksh new file mode 100755 index 000000000000..0978193eddc4 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/setup.ksh @@ -0,0 +1,50 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib + +# Create staff group and add two user to it +log_must add_group $STAFF_GROUP +if ! id $STAFF1 > /dev/null 2>&1; then + log_must add_user $STAFF_GROUP $STAFF1 +fi +if ! id $STAFF2 > /dev/null 2>&1; then + log_must add_user $STAFF_GROUP $STAFF2 +fi + +# Create other group and add two user to it +log_must add_group $OTHER_GROUP +if ! id $OTHER1 > /dev/null 2>&1; then + log_must add_user $OTHER_GROUP $OTHER1 +fi +if ! id $OTHER2 > /dev/null 2>&1; then + log_must add_user $OTHER_GROUP $OTHER2 +fi +DISK=${DISKS%% *} + +default_raidz_setup $DISKS diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/zfs_send_test.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/zfs_send_test.ksh new file mode 100755 index 000000000000..d018f313fae1 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_send_delegation/zfs_send_test.ksh @@ -0,0 +1,111 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +# STRATEGY: +# 1. Create a pool (this is done by the test framework) +# 2. Create an encrypted dataset +# 3. Write random data to the encrypted dataset +# 4. Snapshot the dataset +# 5. As root: attempt a send and raw send (both should succeed) +# 6. Create a delegation (zfs allow -u user send testpool/encrypted_dataset) +# 7. As root: attempt a send and raw send (both should succeed) +# 8. Create a delegation (zfs allow -u user send:raw testpool/encrypted_dataset) +# 9. As root: attempt a send and raw send (both should succeed) +# 10. Disable delegation (zfs unallow) +# 11. As root: attempt a send and raw send (both should succeed) +# 12. Clean up (handled by framework) +# +# Tested as a user under ../cli_user/zfs_send_delegation_user/ + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib +. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib +. $STF_SUITE/tests/functional/delegate/delegate.cfg + +# create encrypted dataset + +log_must eval "echo $PASSPHRASE | zfs create -o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS1" + +# create target dataset for receives +if ! zfs list | grep testfs2 >/dev/null 2>&1; then + dataset_created="TRUE" + log_must zfs create $TESTPOOL/$TESTFS2 +fi + +# create user and group +typeset perms="snapshot,reservation,compression,checksum,userprop,receive" + +log_note "Added permissions to the $OTHER1 user." +log_must zfs allow $OTHER1 $perms $TESTPOOL/$TESTFS1 +log_must zfs allow $OTHER1 $perms $TESTPOOL/$TESTFS2 + +# create random data +log_must fill_fs $TESTPOOL/$TESTFS1/child 1 2047 1024 1 R + +# snapshot +log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1 + + +# check baseline send abilities (should pass) +log_must eval "zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv0_datastream.$$" +log_must eval "zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv0raw_datastream.$$" + + +# create delegation +log_must zfs allow $OTHER1 send $TESTPOOL/$TESTFS1 + +# attempt send with full allow + +log_must eval "zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv1_datastream.$$" +log_must eval "zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv1raw_datastream.$$" + +# create raw delegation +log_must zfs allow $OTHER1 send:raw $TESTPOOL/$TESTFS1 +log_must zfs unallow $OTHER1 send $TESTPOOL/$TESTFS1 + +# test new send abilities (should pass) +log_must eval "zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv2_datastream.$$" +log_must eval "zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv2raw_datastream.$$" + + +# disable raw delegation +zfs unallow $OTHER1 send:raw $TESTPOOL/$TESTFS1 +zfs allow $OTHER1 send $TESTPOOL/$TESTFS1 + +# verify original send abilities (should pass) +log_must eval "zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv3_datastream.$$" +log_must eval "zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive $TESTPOOL/$TESTFS2/zfsrecv3raw_datastream.$$" + + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + destroy_dataset $TESTPOOL/$TESTFS1 -r \ + destroy_dataset $TESTPOOL/$TESTFS2 -r + +} diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib index 0f5f6198daf2..0d07b1fd1952 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/library.kshlib @@ -33,13 +33,16 @@ # Test one: # # 1. Create pool on a loopback device with some test data -# 2. Export the pool. -# 3. Corrupt all label checksums in the pool -# 4. Check that pool cannot be imported -# 5. Verify that it cannot be imported after using zhack label repair -u +# 2. Checksum repair should work with a valid TXG. Repeatedly write and +# sync the pool so there are enough transactions for every uberblock +# to have a TXG +# 3. Export the pool. +# 4. Corrupt all label checksums in the pool +# 5. Check that pool cannot be imported +# 6. Verify that it cannot be imported after using zhack label repair -u # to ensure that the -u option will quit on corrupted checksums. -# 6. Use zhack label repair -c on device -# 7. Check that pool can be imported and that data is intact +# 7. Use zhack label repair -c on device +# 8. Check that pool can be imported and that data is intact # # Test two: # @@ -97,7 +100,7 @@ VIRTUAL_MIRROR_DEVICE= function cleanup_lo { - L_DEVICE="$1" + typeset L_DEVICE="$1" if [[ -e $L_DEVICE ]]; then if is_linux; then @@ -133,9 +136,9 @@ function get_devsize function pick_logop { - L_SHOULD_SUCCEED="$1" + typeset L_SHOULD_SUCCEED="$1" - l_logop="log_mustnot" + typeset l_logop="log_mustnot" if [ "$L_SHOULD_SUCCEED" == true ]; then l_logop="log_must" fi @@ -145,7 +148,9 @@ function pick_logop function check_dataset { - L_SHOULD_SUCCEED="$1" + typeset L_SHOULD_SUCCEED="$1" + + typeset L_LOGOP= L_LOGOP="$(pick_logop "$L_SHOULD_SUCCEED")" "$L_LOGOP" mounted "$TESTPOOL"/"$TESTFS" @@ -170,9 +175,21 @@ function setup_dataset check_dataset true } +function force_transactions +{ + typeset L_TIMES="$1" + typeset i= + for ((i=0; i < L_TIMES; i++)) + do + touch "$TESTDIR"/"test" || return $? + zpool sync -f "$TESTPOOL" || return $? + done + return 0 +} + function get_practical_size { - L_SIZE="$1" + typeset L_SIZE="$1" if [ "$((L_SIZE % LABEL_SIZE))" -ne 0 ]; then echo "$(((L_SIZE / LABEL_SIZE) * LABEL_SIZE))" @@ -183,10 +200,11 @@ function get_practical_size function corrupt_sized_label_checksum { - L_SIZE="$1" - L_LABEL="$2" - L_DEVICE="$3" + typeset L_SIZE="$1" + typeset L_LABEL="$2" + typeset L_DEVICE="$3" + typeset L_PRACTICAL_SIZE= L_PRACTICAL_SIZE="$(get_practical_size "$L_SIZE")" typeset -a L_OFFSETS=("$LABEL_CKSUM_START" \ @@ -201,8 +219,8 @@ function corrupt_sized_label_checksum function corrupt_labels { - L_SIZE="$1" - L_DISK="$2" + typeset L_SIZE="$1" + typeset L_DISK="$2" corrupt_sized_label_checksum "$L_SIZE" 0 "$L_DISK" corrupt_sized_label_checksum "$L_SIZE" 1 "$L_DISK" @@ -212,11 +230,14 @@ function corrupt_labels function try_import_and_repair { - L_REPAIR_SHOULD_SUCCEED="$1" - L_IMPORT_SHOULD_SUCCEED="$2" - L_OP="$3" - L_POOLDISK="$4" + typeset L_REPAIR_SHOULD_SUCCEED="$1" + typeset L_IMPORT_SHOULD_SUCCEED="$2" + typeset L_OP="$3" + typeset L_POOLDISK="$4" + + typeset L_REPAIR_LOGOP= L_REPAIR_LOGOP="$(pick_logop "$L_REPAIR_SHOULD_SUCCEED")" + typeset L_IMPORT_LOGOP= L_IMPORT_LOGOP="$(pick_logop "$L_IMPORT_SHOULD_SUCCEED")" log_mustnot zpool import "$TESTPOOL" -d "$L_POOLDISK" @@ -230,10 +251,10 @@ function try_import_and_repair function prepare_vdev { - L_SIZE="$1" - L_BACKFILE="$2" + typeset L_SIZE="$1" + typeset L_BACKFILE="$2" - l_devname= + typeset l_devname= if truncate -s "$L_SIZE" "$L_BACKFILE"; then if is_linux; then l_devname="$(losetup -f "$L_BACKFILE" --show)" @@ -248,7 +269,7 @@ function prepare_vdev function run_test_one { - L_SIZE="$1" + typeset L_SIZE="$1" VIRTUAL_DEVICE="$(prepare_vdev "$L_SIZE" "$VIRTUAL_DISK")" log_must test -e "$VIRTUAL_DEVICE" @@ -257,6 +278,9 @@ function run_test_one setup_dataset + # Force 256 extra transactions to ensure all uberblocks are assigned a TXG + log_must force_transactions 256 + log_must zpool export "$TESTPOOL" corrupt_labels "$L_SIZE" "$VIRTUAL_DISK" @@ -272,7 +296,7 @@ function run_test_one function make_mirrored_pool { - L_SIZE="$1" + typeset L_SIZE="$1" VIRTUAL_DEVICE="$(prepare_vdev "$L_SIZE" "$VIRTUAL_DISK")" log_must test -e "$VIRTUAL_DEVICE" @@ -296,7 +320,7 @@ function export_and_cleanup_vdisk function run_test_two { - L_SIZE="$1" + typeset L_SIZE="$1" make_mirrored_pool "$L_SIZE" @@ -317,7 +341,7 @@ function run_test_two function run_test_three { - L_SIZE="$1" + typeset L_SIZE="$1" make_mirrored_pool "$L_SIZE" @@ -342,7 +366,7 @@ function run_test_three function run_test_four { - L_SIZE="$1" + typeset L_SIZE="$1" make_mirrored_pool "$L_SIZE" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh index ce159b555d20..b5b24322f882 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_label_repair_001.ksh @@ -18,13 +18,16 @@ # Strategy: # # 1. Create pool on a loopback device with some test data -# 2. Export the pool. -# 3. Corrupt all label checksums in the pool -# 4. Check that pool cannot be imported -# 5. Verify that it cannot be imported after using zhack label repair -u +# 2. Checksum repair should work with a valid TXG. Repeatedly write and +# sync the pool so there are enough transactions for every uberblock +# to have a TXG +# 3. Export the pool. +# 4. Corrupt all label checksums in the pool +# 5. Check that pool cannot be imported +# 6. Verify that it cannot be imported after using zhack label repair -u # to ensure that the -u option will quit on corrupted checksums. -# 6. Use zhack label repair -c on device -# 7. Check that pool can be imported and that data is intact +# 7. Use zhack label repair -c on device +# 8. Check that pool can be imported and that data is intact . "$STF_SUITE"/tests/functional/cli_root/zhack/library.kshlib diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_metaslab_leak.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_metaslab_leak.ksh new file mode 100755 index 000000000000..0d2a39be6b5a --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zhack/zhack_metaslab_leak.ksh @@ -0,0 +1,70 @@ +#!/bin/ksh +# SPDX-License-Identifier: CDDL-1.0 + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# + +# +# Description: +# +# Test whether zhack metaslab leak functions correctly +# +# Strategy: +# +# 1. Create pool on a loopback device with some test data +# 2. Gather pool capacity stats +# 3. Generate fragmentation data with zdb +# 4. Destroy the pool +# 5. Create a new pool with the same configuration +# 6. Export the pool +# 7. Apply the fragmentation information with zhack metaslab leak +# 8. Import the pool +# 9. Verify that pool capacity stats match + +. "$STF_SUITE"/include/libtest.shlib + +verify_runnable "global" + +function cleanup +{ + zpool destroy $TESTPOOL + rm $tmp +} + +log_onexit cleanup +log_assert "zhack metaslab leak leaks the right amount of space" + +typeset tmp=$(mktemp) + +log_must zpool create $TESTPOOL $DISKS +for i in `seq 1 16`; do + log_must dd if=/dev/urandom of=/$TESTPOOL/f$i bs=1M count=16 + log_must zpool sync $TESTPOOL +done +for i in `seq 2 2 16`; do + log_must rm /$TESTPOOL/f$i +done +for i in `seq 1 16`; do + log_must touch /$TESTPOOL/g$i + log_must zpool sync $TESTPOOL +done + +alloc=$(zpool get -Hpo value alloc $TESTPOOL) +log_must eval "zdb -m --allocated-map $TESTPOOL > $tmp" +log_must zpool destroy $TESTPOOL + +log_must zpool create $TESTPOOL $DISKS +log_must zpool export $TESTPOOL +log_must eval "zhack metaslab leak $TESTPOOL < $tmp" +log_must zpool import $TESTPOOL + +alloc2=$(zpool get -Hpo value alloc $TESTPOOL) + +within_percent $alloc $alloc2 98 || + log_fail "space usage changed too much: $alloc to $alloc2" + +log_pass "zhack metaslab leak behaved correctly" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib index 091d65bb4f33..74780bb02141 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add.kshlib @@ -27,6 +27,7 @@ # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2025 by Lawrence Livermore National Security, LLC. # . $STF_SUITE/include/libtest.shlib @@ -89,3 +90,44 @@ function save_dump_dev fi echo $dumpdev } + +function zpool_create_add_setup +{ + typeset -i i=0 + + while ((i < 10)); do + log_must truncate -s $MINVDEVSIZE $TEST_BASE_DIR/vdev$i + + eval vdev$i=$TEST_BASE_DIR/vdev$i + ((i += 1)) + done + + if is_linux; then + vdev_lo="$(losetup -f "$vdev4" --show)" + elif is_freebsd; then + vdev_lo=/dev/"$(mdconfig -a -t vnode -f "$vdev4")" + else + vdev_lo="$(lofiadm -a "$vdev4")" + fi +} + +function zpool_create_add_cleanup +{ + datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1 + + if [[ -e $vdev_lo ]]; then + if is_linux; then + log_must losetup -d "$vdev_lo" + elif is_freebsd; then + log_must mdconfig -d -u "$vdev_lo" + else + log_must lofiadm -d "$vdev_lo" + fi + fi + + typeset -i i=0 + while ((i < 10)); do + rm -f $TEST_BASE_DIR/vdev$i + ((i += 1)) + done +} diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_create.ksh index df085a2ec746..661e55998d8d 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_010_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_create.ksh @@ -23,67 +23,51 @@ # # Copyright 2009 Sun Microsystems, Inc. All rights reserved. -# Use is subject to license terms. -# - -# -# Copyright (c) 2012, 2016 by Delphix. All rights reserved. +# Copyright 2012, 2016 by Delphix. All rights reserved. +# Copyright 2025 by Lawrence Livermore National Security, LLC. # . $STF_SUITE/include/libtest.shlib -. $STF_SUITE/tests/functional/cli_root/zpool_create/zpool_create.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib # # DESCRIPTION: -# Verify zpool add succeed when adding vdevs with matching redundancy. +# Verify zpool add succeeds when adding vdevs with matching redundancy +# and warns with differing redundancy for a healthy pool. # # STRATEGY: # 1. Create several files == $MINVDEVSIZE. # 2. Verify 'zpool add' succeeds with matching redundancy. # 3. Verify 'zpool add' warns with differing redundancy. -# 4. Verify 'zpool add' warns with differing redundancy after removal. # verify_runnable "global" -function cleanup -{ - datasetexists $TESTPOOL1 && destroy_pool $TESTPOOL1 - - typeset -i i=0 - while ((i < 10)); do - rm -f $TEST_BASE_DIR/vdev$i - ((i += 1)) - done -} - +log_assert "Verify 'zpool add' warns for differing redundancy." +log_onexit zpool_create_add_cleanup -log_assert "Verify 'zpool add' succeed with keywords combination." -log_onexit cleanup +zpool_create_add_setup -# 1. Create several files == $MINVDEVSIZE. typeset -i i=0 -while ((i < 10)); do - log_must truncate -s $MINVDEVSIZE $TEST_BASE_DIR/vdev$i - - eval vdev$i=$TEST_BASE_DIR/vdev$i - ((i += 1)) -done +typeset -i j=0 set -A redundancy0_create_args \ "$vdev0" set -A redundancy1_create_args \ "mirror $vdev0 $vdev1" \ - "raidz1 $vdev0 $vdev1" + "raidz1 $vdev0 $vdev1" \ + "draid1:1s $vdev0 $vdev1 $vdev9" set -A redundancy2_create_args \ "mirror $vdev0 $vdev1 $vdev2" \ - "raidz2 $vdev0 $vdev1 $vdev2" + "raidz2 $vdev0 $vdev1 $vdev2" \ + "draid2:1s $vdev0 $vdev1 $vdev2 $vdev9" set -A redundancy3_create_args \ "mirror $vdev0 $vdev1 $vdev2 $vdev3" \ - "raidz3 $vdev0 $vdev1 $vdev2 $vdev3" + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3" \ + "draid3:1s $vdev0 $vdev1 $vdev2 $vdev3 $vdev9" set -A redundancy0_add_args \ "$vdev5" \ @@ -93,21 +77,19 @@ set -A redundancy1_add_args \ "mirror $vdev5 $vdev6" \ "raidz1 $vdev5 $vdev6" \ "raidz1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ - "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8" + "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8" \ + "draid1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 draid1 $vdev7 $vdev8" set -A redundancy2_add_args \ "mirror $vdev5 $vdev6 $vdev7" \ - "raidz2 $vdev5 $vdev6 $vdev7" + "raidz2 $vdev5 $vdev6 $vdev7" \ + "draid2 $vdev5 $vdev6 $vdev7" set -A redundancy3_add_args \ "mirror $vdev5 $vdev6 $vdev7 $vdev8" \ - "raidz3 $vdev5 $vdev6 $vdev7 $vdev8" - -set -A log_args "log" "$vdev4" -set -A cache_args "cache" "$vdev4" -set -A spare_args "spare" "$vdev4" - -typeset -i j=0 + "raidz3 $vdev5 $vdev6 $vdev7 $vdev8" \ + "draid3 $vdev5 $vdev6 $vdev7 $vdev8" function zpool_create_add { @@ -148,30 +130,6 @@ function zpool_create_forced_add done } -function zpool_create_rm_add -{ - typeset -n create_args=$1 - typeset -n add_args=$2 - typeset -n rm_args=$3 - - i=0 - while ((i < ${#create_args[@]})); do - j=0 - while ((j < ${#add_args[@]})); do - log_must zpool create $TESTPOOL1 ${create_args[$i]} - log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} - log_must zpool add $TESTPOOL1 ${add_args[$j]} - log_must zpool remove $TESTPOOL1 ${rm_args[1]} - log_mustnot zpool add $TESTPOOL1 ${rm_args[1]} - log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} - log_must zpool destroy -f $TESTPOOL1 - - ((j += 1)) - done - ((i += 1)) - done -} - # 2. Verify 'zpool add' succeeds with matching redundancy. zpool_create_add redundancy0_create_args redundancy0_add_args zpool_create_add redundancy1_create_args redundancy1_add_args @@ -195,17 +153,4 @@ zpool_create_forced_add redundancy3_create_args redundancy0_add_args zpool_create_forced_add redundancy3_create_args redundancy1_add_args zpool_create_forced_add redundancy3_create_args redundancy2_add_args -# 4. Verify 'zpool add' warns with differing redundancy after removal. -zpool_create_rm_add redundancy1_create_args redundancy1_add_args log_args -zpool_create_rm_add redundancy2_create_args redundancy2_add_args log_args -zpool_create_rm_add redundancy3_create_args redundancy3_add_args log_args - -zpool_create_rm_add redundancy1_create_args redundancy1_add_args cache_args -zpool_create_rm_add redundancy2_create_args redundancy2_add_args cache_args -zpool_create_rm_add redundancy3_create_args redundancy3_add_args cache_args - -zpool_create_rm_add redundancy1_create_args redundancy1_add_args spare_args -zpool_create_rm_add redundancy2_create_args redundancy2_add_args spare_args -zpool_create_rm_add redundancy3_create_args redundancy3_add_args spare_args - -log_pass "'zpool add' succeed with keywords combination." +log_pass "Verify 'zpool add' warns for differing redundancy." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_degraded.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_degraded.ksh new file mode 100755 index 000000000000..313eb3666f27 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_degraded.ksh @@ -0,0 +1,204 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2012, 2016 by Delphix. All rights reserved. +# Copyright 2025 by Lawrence Livermore National Security, LLC. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib + +# +# DESCRIPTION: +# Verify zpool add succeeds when adding vdevs with matching redundancy +# and warns with differing redundancy for a degraded pool. +# +# STRATEGY: +# 1. Create several files == $MINVDEVSIZE. +# 2. Verify 'zpool add' succeeds with matching redundancy +# 3. Verify 'zpool add' warns with differing redundancy when +# a. Degraded pool with replaced mismatch vdev (file vs disk) +# b. Degraded pool dRAID distributed spare active +# c. Degraded pool hot spare active +# + +verify_runnable "global" + +log_assert "Verify 'zpool add' warns for differing redundancy." +log_onexit zpool_create_add_cleanup + +zpool_create_add_setup + +set -A redundancy1_create_args \ + "mirror $vdev0 $vdev1" \ + "raidz1 $vdev0 $vdev1" \ + "draid1:1s $vdev0 $vdev1 $vdev9" + +set -A redundancy2_create_args \ + "mirror $vdev0 $vdev1 $vdev2" \ + "raidz2 $vdev0 $vdev1 $vdev2" \ + "draid2:1s $vdev0 $vdev1 $vdev2 $vdev9" + +set -A redundancy3_create_args \ + "mirror $vdev0 $vdev1 $vdev2 $vdev3" \ + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3" \ + "draid3:1s $vdev0 $vdev1 $vdev2 $vdev3 $vdev9" + +set -A redundancy1_add_args \ + "mirror $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8" \ + "draid1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 draid1 $vdev7 $vdev8" + +set -A redundancy2_add_args \ + "mirror $vdev5 $vdev6 $vdev7" \ + "raidz2 $vdev5 $vdev6 $vdev7" \ + "draid2 $vdev5 $vdev6 $vdev7" + +set -A redundancy3_add_args \ + "mirror $vdev5 $vdev6 $vdev7 $vdev8" \ + "raidz3 $vdev5 $vdev6 $vdev7 $vdev8" \ + "draid3 $vdev5 $vdev6 $vdev7 $vdev8" + +set -A redundancy1_create_draid_args \ + "draid1:1s $vdev0 $vdev1 $vdev2" + +set -A redundancy2_create_draid_args \ + "draid2:1s $vdev0 $vdev1 $vdev2 $vdev3" + +set -A redundancy3_create_draid_args \ + "draid3:1s $vdev0 $vdev1 $vdev2 $vdev3 $vdev9" + +set -A redundancy1_create_spare_args \ + "mirror $vdev0 $vdev1 spare $vdev_lo" \ + "raidz1 $vdev0 $vdev1 spare $vdev_lo" \ + "draid1 $vdev0 $vdev1 spare $vdev_lo" + +set -A redundancy2_create_spare_args \ + "mirror $vdev0 $vdev1 $vdev2 spare $vdev_lo" \ + "raidz2 $vdev0 $vdev1 $vdev2 spare $vdev_lo" \ + "draid2 $vdev0 $vdev1 $vdev2 spare $vdev_lo" + +set -A redundancy3_create_spare_args \ + "mirror $vdev0 $vdev1 $vdev2 $vdev3 spare $vdev_lo" \ + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3 spare $vdev_lo" \ + "draid3 $vdev0 $vdev1 $vdev2 $vdev3 spare $vdev_lo" + +set -A replace_args "$vdev1" "$vdev_lo" +set -A draid1_args "$vdev1" "draid1-0-0" +set -A draid2_args "$vdev1" "draid2-0-0" +set -A draid3_args "$vdev1" "draid3-0-0" + +typeset -i i=0 +typeset -i j=0 + +function zpool_create_degraded_add +{ + typeset -n create_args=$1 + typeset -n add_args=$2 + typeset -n rm_args=$3 + + i=0 + while ((i < ${#create_args[@]})); do + j=0 + while ((j < ${#add_args[@]})); do + log_must zpool create $TESTPOOL1 ${create_args[$i]} + log_must zpool offline -f $TESTPOOL1 ${rm_args[0]} + log_must zpool replace -w $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} + log_must zpool add $TESTPOOL1 ${add_args[$j]} + log_must zpool destroy -f $TESTPOOL1 + log_must zpool labelclear -f ${rm_args[0]} + + ((j += 1)) + done + ((i += 1)) + done +} + +function zpool_create_forced_degraded_add +{ + typeset -n create_args=$1 + typeset -n add_args=$2 + typeset -n rm_args=$3 + + i=0 + while ((i < ${#create_args[@]})); do + j=0 + while ((j < ${#add_args[@]})); do + log_must zpool create $TESTPOOL1 ${create_args[$i]} + log_must zpool offline -f $TESTPOOL1 ${rm_args[0]} + log_must zpool replace -w $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} + log_mustnot zpool add $TESTPOOL1 ${add_args[$j]} + log_must zpool add --allow-replication-mismatch $TESTPOOL1 ${add_args[$j]} + log_must zpool destroy -f $TESTPOOL1 + log_must zpool labelclear -f ${rm_args[0]} + + ((j += 1)) + done + ((i += 1)) + done +} + +# 2. Verify 'zpool add' succeeds with matching redundancy and a degraded pool. +zpool_create_degraded_add redundancy1_create_args redundancy1_add_args replace_args +zpool_create_degraded_add redundancy2_create_args redundancy2_add_args replace_args +zpool_create_degraded_add redundancy3_create_args redundancy3_add_args replace_args + +# 3. Verify 'zpool add' warns with differing redundancy and a degraded pool. +# +# a. Degraded pool with replaced mismatch vdev (file vs disk) +zpool_create_forced_degraded_add redundancy1_create_args redundancy2_add_args replace_args +zpool_create_forced_degraded_add redundancy1_create_args redundancy3_add_args replace_args + +zpool_create_forced_degraded_add redundancy2_create_args redundancy1_add_args replace_args +zpool_create_forced_degraded_add redundancy2_create_args redundancy3_add_args replace_args + +zpool_create_forced_degraded_add redundancy3_create_args redundancy1_add_args replace_args +zpool_create_forced_degraded_add redundancy3_create_args redundancy2_add_args replace_args + +# b. Degraded pool dRAID distributed spare active + +zpool_create_forced_degraded_add redundancy1_create_draid_args redundancy2_add_args draid1_args +zpool_create_forced_degraded_add redundancy1_create_draid_args redundancy3_add_args draid1_args + +zpool_create_forced_degraded_add redundancy2_create_draid_args redundancy1_add_args draid2_args +zpool_create_forced_degraded_add redundancy2_create_draid_args redundancy3_add_args draid2_args + +zpool_create_forced_degraded_add redundancy3_create_draid_args redundancy1_add_args draid3_args +zpool_create_forced_degraded_add redundancy3_create_draid_args redundancy2_add_args draid3_args + +# c. Degraded pool hot spare active +zpool_create_forced_degraded_add redundancy1_create_spare_args redundancy2_add_args replace_args +zpool_create_forced_degraded_add redundancy1_create_spare_args redundancy3_add_args replace_args + +zpool_create_forced_degraded_add redundancy2_create_spare_args redundancy1_add_args replace_args +zpool_create_forced_degraded_add redundancy2_create_spare_args redundancy3_add_args replace_args + +zpool_create_forced_degraded_add redundancy3_create_spare_args redundancy1_add_args replace_args +zpool_create_forced_degraded_add redundancy3_create_spare_args redundancy2_add_args replace_args + +log_pass "Verify 'zpool add' warns for differing redundancy." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_removal.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_removal.ksh new file mode 100755 index 000000000000..782858e301ac --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_add/zpool_add_warn_removal.ksh @@ -0,0 +1,126 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2009 Sun Microsystems, Inc. All rights reserved. +# Copyright 2012, 2016 by Delphix. All rights reserved. +# Copyright 2025 by Lawrence Livermore National Security, LLC. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_add/zpool_add.kshlib + +# +# DESCRIPTION: +# Verify zpool add succeeds when adding vdevs with matching redundancy +# and warns with differing redundancy after removal. +# +# STRATEGY: +# 1. Create several files == $MINVDEVSIZE. +# 2. Verify 'zpool add' warns with differing redundancy after removal. +# + +verify_runnable "global" + +log_assert "Verify 'zpool add' warns for differing redundancy." +log_onexit zpool_create_add_cleanup + +zpool_create_add_setup + +typeset -i i=0 +typeset -i j=0 + +set -A redundancy1_create_args \ + "mirror $vdev0 $vdev1" \ + "raidz1 $vdev0 $vdev1" \ + "draid1:1s $vdev0 $vdev1 $vdev9" + +set -A redundancy2_create_args \ + "mirror $vdev0 $vdev1 $vdev2" \ + "raidz2 $vdev0 $vdev1 $vdev2" \ + "draid2:1s $vdev0 $vdev1 $vdev2 $vdev9" + +set -A redundancy3_create_args \ + "mirror $vdev0 $vdev1 $vdev2 $vdev3" \ + "raidz3 $vdev0 $vdev1 $vdev2 $vdev3" \ + "draid3:1s $vdev0 $vdev1 $vdev2 $vdev3 $vdev9" + +set -A redundancy1_add_args \ + "mirror $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6" \ + "raidz1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 raidz1 $vdev7 $vdev8" \ + "draid1 $vdev5 $vdev6 mirror $vdev7 $vdev8" \ + "mirror $vdev5 $vdev6 draid1 $vdev7 $vdev8" + +set -A redundancy2_add_args \ + "mirror $vdev5 $vdev6 $vdev7" \ + "raidz2 $vdev5 $vdev6 $vdev7" \ + "draid2 $vdev5 $vdev6 $vdev7" + +set -A redundancy3_add_args \ + "mirror $vdev5 $vdev6 $vdev7 $vdev8" \ + "raidz3 $vdev5 $vdev6 $vdev7 $vdev8" \ + "draid3 $vdev5 $vdev6 $vdev7 $vdev8" + +set -A log_args "log" "$vdev_lo" +set -A cache_args "cache" "$vdev_lo" +set -A spare_args "spare" "$vdev_lo" + + +function zpool_create_rm_add +{ + typeset -n create_args=$1 + typeset -n add_args=$2 + typeset -n rm_args=$3 + + i=0 + while ((i < ${#create_args[@]})); do + j=0 + while ((j < ${#add_args[@]})); do + log_must zpool create $TESTPOOL1 ${create_args[$i]} + log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} + log_must zpool add $TESTPOOL1 ${add_args[$j]} + log_must zpool remove $TESTPOOL1 ${rm_args[1]} + log_mustnot zpool add $TESTPOOL1 ${rm_args[1]} + log_must zpool add $TESTPOOL1 ${rm_args[0]} ${rm_args[1]} + log_must zpool destroy -f $TESTPOOL1 + + ((j += 1)) + done + ((i += 1)) + done +} + +# 2. Verify 'zpool add' warns with differing redundancy after removal. +zpool_create_rm_add redundancy1_create_args redundancy1_add_args log_args +zpool_create_rm_add redundancy2_create_args redundancy2_add_args log_args +zpool_create_rm_add redundancy3_create_args redundancy3_add_args log_args + +zpool_create_rm_add redundancy1_create_args redundancy1_add_args cache_args +zpool_create_rm_add redundancy2_create_args redundancy2_add_args cache_args +zpool_create_rm_add redundancy3_create_args redundancy3_add_args cache_args + +zpool_create_rm_add redundancy1_create_args redundancy1_add_args spare_args +zpool_create_rm_add redundancy2_create_args redundancy2_add_args spare_args +zpool_create_rm_add redundancy3_create_args redundancy3_add_args spare_args diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/cleanup.ksh new file mode 100755 index 000000000000..099b5426031d --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/cleanup.ksh @@ -0,0 +1,30 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara, Inc. +# +# +. $STF_SUITE/include/libtest.shlib + +log_pass diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/setup.ksh new file mode 100755 index 000000000000..3529a0ccc015 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/setup.ksh @@ -0,0 +1,32 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara, Inc. +# +# +. $STF_SUITE/include/libtest.shlib + +verify_runnable "global" + +log_pass diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat.kshlib new file mode 100644 index 000000000000..ea4b0bd2756d --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat.kshlib @@ -0,0 +1,235 @@ +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara, Inc. +# + +# Since we want to make sure that iostat responds correctly as pools appear and +# disappear, we run it in the background and capture its output to a file. +# Once we're done, we parse the output and ensure it matches what we'd expect +# from the operations we performed. +# +# Because iostat is producing output every interval, it may produce the "same" +# output for each step of the change; in fact, we want that to make sure we +# don't miss anything. So, we describe what we expect as a series of "chunks". +# Each chunk is a particular kind of output, which may repeat. Current known +# chunk types are: +# +# NOPOOL: the text "no pools available" +# HEADER: three lines, starting with "capacity", "pool" and "----" respectively. +# (the rough shape of the normal iostat header). +# POOL1: a line starting with "pool1" (stats line for a pool of that name) +# POOL2: a line starting with "pool2" +# POOLBOTH: three lines, starting with "pool1", "pool2" (either order) and +# "-----" respectively. (the pool stat output for multiple pools) +# +# (the parser may produce other chunks in a failed parse to assist with +# debugging, but they should never be part of the "wanted" output See the +# parser commentary below). +# +# To help recognise the start of a new interval output, we run iostat with the +# -T u option, which will output a numeric timestamp before each header or +# second-or-later pool stat after the header. +# +# To keep the test run shorter, we use a subsecond interval, but to make sure +# nothing is missed, we sleep for three intervals after each change. + +typeset _iostat_out=$(mktemp) +typeset _iostat_pid="" + +function cleanup_iostat { + if [[ -n $_iostat_pid ]] ; then + kill -KILL $_iostat_pid || true + fi + rm -f $_iostat_out +} + +function start_iostat { + zpool iostat -T u $@ 0.1 > $_iostat_out 2>&1 & + _iostat_pid=$! +} + +function stop_iostat { + kill -TERM $_iostat_pid + wait $_iostat_pid + _iostat_pid="" +} + +function delay_iostat { + sleep 0.3 +} + +typeset -a _iostat_expect +function expect_iostat { + typeset chunk=$1 + _iostat_expect+=($chunk) +} + +# Parse the output The `state` var is used to track state across +# multiple lines. The `last` var and the `_got_iostat` function are used +# to record the completed chunks, and to collapse repetitions. +typeset -a _iostat_got +typeset _iostat_last="" +typeset _iostat_state="" + +function _got_iostat { + typeset chunk=$1 + if [[ -n $chunk && $_iostat_last != $chunk ]] ; then + _iostat_last=$chunk + _iostat_got+=($chunk) + fi + _iostat_state="" +} + +function verify_iostat { + + cat $_iostat_out | while read line ; do + + # The "no pools available" text has no timestamp or other + # header, and should never appear in the middle of multiline + # chunk, so we can close any in-flight state. + if [[ $line = "no pools available" ]] ; then + _got_iostat $_iostat_state + _got_iostat "NOPOOL" + continue + fi + + # A run of digits alone on the line is a timestamp (the `-T u` + # switch to `iostat`). It closes any in-flight state as a + # complete chunk, and indicates the start of a new chunk. + if [[ -z ${line/#+([0-9])/} ]] ; then + _got_iostat $_iostat_state + _iostat_state="TIMESTAMP" + continue + fi + + # For this test, the first word of each line should be unique, + # so we extract it and use it for simplicity. + typeset first=${line%% *} + + # Header is emitted whenever the pool list changes. It has + # three lines: + # + # capacity operations bandwidth + # pool alloc free read write read write + # ---------- ----- ----- ----- ----- ----- ----- + # + # Each line moves the state; when we get to a run of dashes, we + # commit. Note that we check for one-or-more dashes, because + # the width can vary depending on the length of pool name. + # + if [[ $_iostat_state = "TIMESTAMP" && + $first = "capacity" ]] ; then + _iostat_state="INHEADER1" + continue + fi + if [[ $_iostat_state = "INHEADER1" && + $first = "pool" ]] ; then + _iostat_state="INHEADER2" + continue + fi + if [[ $_iostat_state = "INHEADER2" && + -z ${first/#+(-)/} ]] ; then + # Headers never repeat, so if the last committed chunk + # was a header, we commit this one as EXTRAHEADER so we + # can see it in the error output. + if [[ $_iostat_last = "HEADER" ]] ; then + _got_iostat "EXTRAHEADER" + elif [[ $_iostat_last != "EXTRAHEADER" ]] ; then + _got_iostat "HEADER" + fi + _iostat_state="HEADER" + continue + fi + + # A pool stat line looks like: + # + # pool1 147K 240M 0 0 0 0 + # + # If there are multiple pools, iostat follows them with a + # separator of dashed lines: + # + # pool1 147K 240M 0 0 0 0 + # pool2 147K 240M 0 0 0 0 + # ---------- ----- ----- ----- ----- ----- ----- + # + # Stats rows always start after a timestamp or a header. If the + # header was emitted, we won't see a timestamp here (it goes + # before the header). + # + # Because our test exercises both pools on their own and + # together, we allow pools in either order. In practice they + # are sorted, but that's a side-effect of the implementation + # (see zpool_compare()), so we're not going to rely on it here. + if [[ $first = "pool1" ]] || [[ $first = "pool2" ]] ; then + + # First line, track which one we saw. If it's a + # standalone line, it will be committed by the next + # NOPOOL or TIMESTAMP above (or the `_got_iostat` after + # the loop if this is the last line). + if [[ $_iostat_state == "TIMESTAMP" || + $_iostat_state == "HEADER" ]] ; then + if [[ $first = "pool1" ]] ; then + _iostat_state="POOL1" + elif [[ $first = "pool2" ]] ; then + _iostat_state="POOL2" + fi + continue + fi + + # If this is the second pool, we're in a multi-pool + # block, and need to look for the separator to close it + # out. + if [[ $_iostat_state = "POOL1" && $first = "pool2" ]] || + [[ $_iostat_state = "POOL2" && $first = "pool1" ]] ; + then + _iostat_state="INPOOLBOTH" + continue + fi + fi + + # Separator after the stats block. + if [[ $_iostat_state = "INPOOLBOTH" && + -z ${first/#+(-)/} ]] ; then + _got_iostat "POOLBOTH" + continue + fi + + # Anything else will fall through to here. We commit any + # in-flight state, then "UNKNOWN", all to help with debugging.. + if [[ $_iostat_state != "UNKNOWN" ]] ; then + _got_iostat $_iostat_state + _got_iostat "UNKNOWN" + fi + done + + # Close out any remaining state. + _got_iostat $_iostat_state + + # Compare what we wanted with what we got, and pass/fail the test! + if [[ "${_iostat_expect[*]}" != "${_iostat_got[*]}" ]] ; then + log_note "expected: ${_iostat_expect[*]}" + log_note " got: ${_iostat_got[*]}" + log_fail "zpool iostat did not produce expected output" + fi +} diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_all.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_all.ksh new file mode 100755 index 000000000000..8e040058ec3e --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_all.ksh @@ -0,0 +1,90 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara, Inc. +# + +# `zpool iostat <N>` should keep running and update the pools it displays as +# pools are created/destroyed/imported/export. + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_iostat/zpool_iostat.kshlib + +typeset vdev1=$(mktemp) +typeset vdev2=$(mktemp) + +function cleanup { + cleanup_iostat + + poolexists pool1 && destroy_pool pool1 + poolexists pool2 && destroy_pool pool2 + rm -f $vdev1 $vdev2 +} + +log_must mkfile $MINVDEVSIZE $vdev1 $vdev2 + +expect_iostat "NOPOOL" + +start_iostat + +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOL1" +log_must zpool create pool1 $vdev1 +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOLBOTH" +log_must zpool create pool2 $vdev2 +delay_iostat + +expect_iostat "NOPOOL" +log_must zpool export -a +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOL2" +log_must zpool import -d $vdev2 pool2 +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOLBOTH" +log_must zpool import -d $vdev1 pool1 +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOL2" +log_must zpool destroy pool1 +delay_iostat + +expect_iostat "NOPOOL" +log_must zpool destroy pool2 +delay_iostat + +stop_iostat + +verify_iostat + +log_pass "zpool iostat in interval mode follows pool updates" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_some.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_some.ksh new file mode 100755 index 000000000000..ab1f258aa1cd --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_iostat/zpool_iostat_interval_some.ksh @@ -0,0 +1,80 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara, Inc. +# + +# `zpool iostat <pools> <N>` should keep running and only show the listed pools. + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_iostat/zpool_iostat.kshlib + +typeset vdev1=$(mktemp) +typeset vdev2=$(mktemp) + +function cleanup { + cleanup_iostat + + poolexists pool1 && destroy_pool pool1 + poolexists pool2 && destroy_pool pool2 + rm -f $vdev1 $vdev2 +} + +log_must mkfile $MINVDEVSIZE $vdev1 $vdev2 + +log_must zpool create pool1 $vdev1 +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOL1" +start_iostat pool1 +delay_iostat + +log_must zpool create pool2 $vdev2 +delay_iostat + +expect_iostat "NOPOOL" +log_must zpool export -a +delay_iostat + +log_must zpool import -d $vdev2 pool2 +delay_iostat + +expect_iostat "HEADER" +expect_iostat "POOL1" +log_must zpool import -d $vdev1 pool1 +delay_iostat + +expect_iostat "NOPOOL" +log_must zpool destroy pool1 +delay_iostat + +log_must zpool destroy pool2 +delay_iostat + +stop_iostat + +verify_iostat + +log_pass "zpool iostat in interval mode with pools follows listed pool updates" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_002.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_002.ksh new file mode 100755 index 000000000000..9327df81a5c5 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_002.ksh @@ -0,0 +1,76 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# +# Copyright 2025 Klara, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg + +# +# DESCRIPTION: +# Verify that the timestamp database updates all the tables as expected. +# +# STRATEGY: +# 1. Decrease the note and flush frequency of the txg database. +# 2. Force the pool to sync several txgs +# 3. Verify that there are entries in each of the "month", "day", and +# "minute" tables. +# + +verify_runnable "global" + +function cleanup +{ + log_must restore_tunable SPA_NOTE_TXG_TIME + log_must restore_tunable SPA_FLUSH_TXG_TIME + rm /$TESTPOOL/f1 +} + +log_onexit cleanup + +log_assert "Verifiy timestamp databases all update as expected." + +log_must save_tunable SPA_NOTE_TXG_TIME +log_must set_tunable64 SPA_NOTE_TXG_TIME 1 +log_must save_tunable SPA_FLUSH_TXG_TIME +log_must set_tunable64 SPA_FLUSH_TXG_TIME 1 + +log_must touch /$TESTPOOL/f1 +log_must zpool sync $TESTPOOL +sleep 1 +log_must touch /$TESTPOOL/f1 +log_must zpool sync $TESTPOOL +sleep 1 +log_must touch /$TESTPOOL/f1 +log_must zpool sync $TESTPOOL + +mos_zap="$(zdb -dddd $TESTPOOL 1)" +minutes_entries=$(echo "$mos_zap" | grep "txg_log_time:minutes" | awk '{print $5}') +days_entries=$(echo "$mos_zap" | grep "txg_log_time:days" | awk '{print $5}') +months_entries=$(echo "$mos_zap" | grep "txg_log_time:months" | awk '{print $5}') + +[[ "$minutes_entries" -ne "0" ]] || log_fail "0 entries in the minutes table" +[[ "$days_entries" -ne "0" ]] || log_fail "0 entries in the days table" +[[ "$months_entries" -ne "0" ]] || log_fail "0 entries in the months table" + +log_pass "Verified all timestamp databases had entries as expected." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcstat_001_pos.ksh index 700bd9a6f529..d63b72f8039d 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arcstat_001_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcstat_001_pos.ksh @@ -37,7 +37,7 @@ log_assert "arcstat generates output and doesn't return an error code" typeset -i i=0 while [[ $i -lt ${#args[*]} ]]; do - log_must eval "arcstat ${args[i]} > /dev/null" + log_must eval "zarcstat ${args[i]} > /dev/null" ((i = i + 1)) done log_pass "arcstat generates output and doesn't return an error code" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcsummary_001_pos.ksh index 0840878fdb0d..b7faac5243c9 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_001_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcsummary_001_pos.ksh @@ -30,16 +30,16 @@ is_freebsd && ! python3 -c 'import sysctl' 2>/dev/null && log_unsupported "python3 sysctl module missing" -log_assert "arc_summary generates output and doesn't return an error code" +log_assert "zarcsummary generates output and doesn't return an error code" # Without this, the below checks aren't going to work the way we hope... set -o pipefail for arg in "" "-a" "-d" "-p 1" "-g" "-s arc" "-r"; do - log_must eval "arc_summary $arg > /dev/null" + log_must eval "zarcsummary $arg > /dev/null" done -log_must eval "arc_summary | head > /dev/null" -log_must eval "arc_summary | head -1 > /dev/null" +log_must eval "zarcsummary | head > /dev/null" +log_must eval "zarcsummary | head -1 > /dev/null" -log_pass "arc_summary generates output and doesn't return an error code" +log_pass "zarcsummary generates output and doesn't return an error code" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcsummary_002_neg.ksh index ec4abe35409d..227646777ba0 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/arc_summary_002_neg.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/misc/zarcsummary_002_neg.ksh @@ -30,10 +30,10 @@ is_freebsd && ! python3 -c 'import sysctl' 2>/dev/null && log_unsupported "python3 sysctl module missing" -log_assert "arc_summary generates an error code with invalid options" +log_assert "zarcsummary generates an error code with invalid options" for arg in "-x" "-5" "-p 7" "--err" "-@"; do - log_mustnot eval "arc_summary $arg > /dev/null" + log_mustnot eval "zarcsummary $arg > /dev/null" done -log_pass "arc_summary generates an error code with invalid options" +log_pass "zarcsummary generates an error code with invalid options" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/cleanup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/cleanup.ksh new file mode 100755 index 000000000000..4a59e15cc693 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/cleanup.ksh @@ -0,0 +1,43 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib + + +poolexists $TESTPOOL1 && \ + destroy_pool $TESTPOOL1 + +del_user $STAFF1 +del_user $STAFF2 +del_group $STAFF_GROUP + +del_user $OTHER1 +del_user $OTHER2 +del_group $OTHER_GROUP + +default_cleanup diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/setup.ksh new file mode 100755 index 000000000000..0978193eddc4 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/setup.ksh @@ -0,0 +1,50 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/delegate/delegate_common.kshlib + +# Create staff group and add two user to it +log_must add_group $STAFF_GROUP +if ! id $STAFF1 > /dev/null 2>&1; then + log_must add_user $STAFF_GROUP $STAFF1 +fi +if ! id $STAFF2 > /dev/null 2>&1; then + log_must add_user $STAFF_GROUP $STAFF2 +fi + +# Create other group and add two user to it +log_must add_group $OTHER_GROUP +if ! id $OTHER1 > /dev/null 2>&1; then + log_must add_user $OTHER_GROUP $OTHER1 +fi +if ! id $OTHER2 > /dev/null 2>&1; then + log_must add_user $OTHER_GROUP $OTHER2 +fi +DISK=${DISKS%% *} + +default_raidz_setup $DISKS diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh new file mode 100755 index 000000000000..f62f2b07929c --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_user/zfs_send_delegation_user/zfs_send_usertest.ksh @@ -0,0 +1,145 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025, Klara Inc. +# + +# STRATEGY: +# 1. Create a pool (this is done by the test framework) +# 2. Create a user +# 3. Create an encrypted dataset +# 4. Write random data to the encrypted dataset +# 5. Snapshot the dataset +# 6. As root: attempt a send and raw send (both should succeed) +# 7. As user: attempt a send and raw send (both should fail, no permission) +# 8. Create a delegation (zfs allow -u user send testpool/encrypted_dataset) +# 9. As root: attempt a send and raw send (both should succeed) +# 10. As user: attempt a send and raw send (both should succeed) +# 11. Create a delegation (zfs allow -u user sendraw testpool/encrypted_dataset) +# 12. As root: attempt a send and raw send (both should succeed) +# 13. As user: attempt a send and raw send (send should fail, raw send should succeed) +# 14. Disable delegation (zfs unallow) +# 15. As root: attempt a send and raw send (both should succeed) +# 16. As user: attempt a send and raw send (both should fail, no permission) +# 17. Clean up (handled by framework) +# root tests to verify this doesnt affect root user under ../cli_root/zfs_send_delegation/ +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib +. $STF_SUITE/tests/functional/cli_root/zfs_create/properties.kshlib +. $STF_SUITE/tests/functional/cli_root/zfs_load-key/zfs_load-key_common.kshlib +. $STF_SUITE/tests/functional/delegate/delegate.cfg + +# create encrypted dataset + +log_must eval "echo $PASSPHRASE | zfs create -o encryption=on -o keyformat=passphrase $TESTPOOL/$TESTFS1" + +# create target dataset for receives +log_must zfs create $TESTPOOL/$TESTFS2 + +# set user perms +# need to run chown for fs permissions for $OTHER1 +typeset perms="snapshot,reservation,compression,checksum,userprop,receive,mount,create" + +log_must zfs allow $OTHER1 $perms $TESTPOOL/$TESTFS1 +log_must zfs allow $OTHER1 $perms $TESTPOOL/$TESTFS2 +log_must chown ${OTHER1}:${OTHER_GROUP} /$TESTPOOL/$TESTFS2 + +# create random data +log_must fill_fs $TESTPOOL/$TESTFS1/child 1 2047 1024 1 R + +# snapshot +log_must zfs snapshot $TESTPOOL/$TESTFS1@snap1 + +# note +# we need to use `sh -c` here becuase the quoting on <<<"$*" in the user_run wrapper is broken once pipes and redirects get involved + +# check baseline send abilities (should fail) +log_mustnot user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv0_user_datastream.$$'" +# verify nothing went through +if [ -s $TESTPOOL/$TESTFS2/zfsrecv0_user_datastream.$$ ] +then + log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv0_user_datastream !" +fi +log_mustnot user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv0raw_user_datastream.$$'" +# verify nothing went through +if [ -s $TESTPOOL/$TESTFS2/zfsrecv0raw_user_datastream.$$ ] +then + log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv0raw_user_datastream !" +fi + +# create delegation +log_must zfs allow $OTHER1 send $TESTPOOL/$TESTFS1 + +# attempt send with full allow (should pass) +log_must user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv1_user_datastream.$$'" +log_must user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv1raw_user_datastream.$$'" + + +# create raw delegation +log_must zfs allow $OTHER1 send:raw $TESTPOOL/$TESTFS1 +# We have to remove 'send' to confirm 'send raw' only allows what we want +log_must zfs unallow -u $OTHER1 send $TESTPOOL/$TESTFS1 + +# test new sendraw abilities (send should fail, sendraw should pass) +log_mustnot user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream.$$'" + verify nothing went through +if [ -s $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream.$$ ] +then + log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv2_user_datastream !" +fi +log_must user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv2raw_user_datastream.$$'" + +# disable raw delegation +log_must zfs unallow -u $OTHER1 send:raw $TESTPOOL/$TESTFS1 +log_must zfs allow $OTHER1 send $TESTPOOL/$TESTFS1 + +# test with raw taken away (should pass) +log_must user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv3_user_datastream.$$'" +log_must user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv3raw_user_datastream.$$'" + +# disable send abilities +log_must zfs unallow -u $OTHER1 send $TESTPOOL/$TESTFS1 + +# verify original send abilities (should fail) +log_mustnot user_run $OTHER1 sh -c "'zfs send $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream.$$'" + verify nothing went through +if [ -s $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream.$$ ] +then + log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv4_user_datastream !" +fi +log_mustnot user_run $OTHER1 sh -c "'zfs send -w $TESTPOOL/$TESTFS1@snap1 | zfs receive -u $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream.$$'" + verify nothing went through +if [ -s $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream.$$ ] +then + log_fail "A zfs recieve was completed in $TESTPOOL/$TESTFS2/zfsrecv4raw_user_datastream !" +fi + + +function cleanup +{ + datasetexists $TESTPOOL/$TESTFS1 && \ + destroy_dataset $TESTPOOL/$TESTFS1 -r \ + destroy_dataset $TESTPOOL/$TESTFS2 -r + +} diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib index 0a402e71ee68..345239b88680 100644 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/delegate/delegate_common.kshlib @@ -1234,10 +1234,10 @@ function verify_fs_aedsx typeset oldval set -A modes "on" "off" oldval=$(get_prop $perm $fs) - if [[ $oldval == "on" ]]; then - n=1 - elif [[ $oldval == "off" ]]; then + if [[ $oldval == "off" ]]; then n=0 + else + n=1 fi log_note "$user zfs set $perm=${modes[$n]} $fs" user_run $user zfs set $perm=${modes[$n]} $fs diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_degraded_sit_out.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_degraded_sit_out.ksh new file mode 100755 index 000000000000..d5feb6936b4b --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_degraded_sit_out.ksh @@ -0,0 +1,106 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# Copyright (c) 2024 by Lawrence Livermore National Security, LLC. +# Copyright (c) 2025 by Klara, Inc. + +# DESCRIPTION: +# Verify that vdevs 'sit out' when they are slow +# +# STRATEGY: +# 1. Create various raidz/draid pools +# 2. Degrade/fault one of the disks. +# 3. Inject delays into one of the disks +# 4. Verify disk is set to 'sit out' for awhile. +# 5. Wait for READ_SIT_OUT_SECS and verify sit out state is lifted. +# + +. $STF_SUITE/include/libtest.shlib + +function cleanup +{ + restore_tunable READ_SIT_OUT_SECS + restore_tunable SIT_OUT_CHECK_INTERVAL + log_must zinject -c all + log_must zpool events -c + destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/vdev.$$.* +} + +log_assert "Verify sit_out works" + +log_onexit cleanup + +# shorten sit out period for testing +save_tunable READ_SIT_OUT_SECS +set_tunable32 READ_SIT_OUT_SECS 5 + +save_tunable SIT_OUT_CHECK_INTERVAL +set_tunable64 SIT_OUT_CHECK_INTERVAL 20 + +log_must truncate -s 150M $TEST_BASE_DIR/vdev.$$.{0..9} + +for raidtype in raidz2 raidz3 draid2 draid3 ; do + log_must zpool create $TESTPOOL2 $raidtype $TEST_BASE_DIR/vdev.$$.{0..9} + log_must zpool set autosit=on $TESTPOOL2 "${raidtype}-0" + log_must dd if=/dev/urandom of=/$TESTPOOL2/bigfile bs=1M count=400 + log_must zpool export $TESTPOOL2 + log_must zpool import -d $TEST_BASE_DIR $TESTPOOL2 + + BAD_VDEV=$TEST_BASE_DIR/vdev.$$.9 + SLOW_VDEV=$TEST_BASE_DIR/vdev.$$.8 + + # Initial state should not be sitting out + log_must eval [[ "$(get_vdev_prop sit_out $TESTPOOL2 $SLOW_VDEV)" == "off" ]] + + # Delay our reads 200ms to trigger sit out + log_must zinject -d $SLOW_VDEV -D200:1 -T read $TESTPOOL2 + type=$((RANDOM % 2)) + [[ "$type" -eq "0" ]] && action="degrade" || action="fault" + log_must zinject -d $BAD_VDEV -A $action -T read $TESTPOOL2 + + # Do some reads and wait for us to sit out + for i in {0..99} ; do + dd if=/$TESTPOOL2/bigfile skip=$i bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 100)) bs=2M count=1 of=/dev/null + + sit_out=$(get_vdev_prop sit_out $TESTPOOL2 $SLOW_VDEV) + if [[ "$sit_out" == "on" ]] ; then + break + fi + done + + log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $SLOW_VDEV)" == "on" + + # Clear fault injection + log_must zinject -c all + + # Wait for us to exit our sit out period + log_must wait_sit_out $TESTPOOL2 $SLOW_VDEV 10 + + log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $SLOW_VDEV)" == "off" + destroy_pool $TESTPOOL2 + log_must zpool labelclear -f $BAD_VDEV +done + +log_pass "sit_out works correctly" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out.ksh new file mode 100755 index 000000000000..37f616cf56ee --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out.ksh @@ -0,0 +1,102 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# Copyright (c) 2024 by Lawrence Livermore National Security, LLC. + +# DESCRIPTION: +# Verify that vdevs 'sit out' when they are slow +# +# STRATEGY: +# 1. Create various raidz/draid pools +# 2. Inject delays into one of the disks +# 3. Verify disk is set to 'sit out' for awhile. +# 4. Wait for READ_SIT_OUT_SECS and verify sit out state is lifted. +# + +. $STF_SUITE/include/libtest.shlib + +function cleanup +{ + restore_tunable READ_SIT_OUT_SECS + restore_tunable SIT_OUT_CHECK_INTERVAL + log_must zinject -c all + log_must zpool events -c + destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/vdev.$$.* +} + +log_assert "Verify sit_out works" + +log_onexit cleanup + +# shorten sit out period for testing +save_tunable READ_SIT_OUT_SECS +set_tunable32 READ_SIT_OUT_SECS 5 + +save_tunable SIT_OUT_CHECK_INTERVAL +set_tunable64 SIT_OUT_CHECK_INTERVAL 20 + +log_must truncate -s200M $TEST_BASE_DIR/vdev.$$.{0..9} + +for raidtype in raidz raidz2 raidz3 draid1 draid2 draid3 ; do + log_must zpool create $TESTPOOL2 $raidtype $TEST_BASE_DIR/vdev.$$.{0..9} + log_must zpool set autosit=on $TESTPOOL2 "${raidtype}-0" + log_must dd if=/dev/urandom of=/$TESTPOOL2/bigfile bs=1M count=600 + log_must zpool export $TESTPOOL2 + log_must zpool import -d $TEST_BASE_DIR $TESTPOOL2 + + BAD_VDEV=$TEST_BASE_DIR/vdev.$$.9 + + # Initial state should not be sitting out + log_must eval [[ "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV)" == "off" ]] + + # Delay our reads 200ms to trigger sit out + log_must zinject -d $BAD_VDEV -D200:1 -T read $TESTPOOL2 + + # Do some reads and wait for us to sit out + for i in {0..99} ; do + dd if=/$TESTPOOL2/bigfile skip=$i bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 100)) bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 200)) bs=2M count=1 of=/dev/null + + sit_out=$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV) + if [[ "$sit_out" == "on" ]] ; then + break + fi + done + + log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV)" == "on" + + # Clear fault injection + log_must zinject -c all + + # Wait for us to exit our sit out period + log_must wait_sit_out $TESTPOOL2 $BAD_VDEV 10 + + # Verify sit_out was cleared during wait_sit_out + log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV)" == "off" + + destroy_pool $TESTPOOL2 +done + +log_pass "sit_out works correctly" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out_neg.ksh new file mode 100755 index 000000000000..457105a66453 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/slow_vdev_sit_out_neg.ksh @@ -0,0 +1,116 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# Copyright (c) 2024 by Lawrence Livermore National Security, LLC. +# Copyright (c) 2025 by Klara, Inc. + +# DESCRIPTION: +# Verify that we don't sit out too many vdevs +# +# STRATEGY: +# 1. Create draid2 pool +# 2. Inject delays into three of the disks +# 3. Do reads to trigger sit-outs +# 4. Verify exactly 2 disks sit out +# + +. $STF_SUITE/include/libtest.shlib + +function cleanup +{ + restore_tunable READ_SIT_OUT_SECS + restore_tunable SIT_OUT_CHECK_INTERVAL + log_must zinject -c all + log_must zpool events -c + destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/vdev.$$.* +} + +log_assert "Verify sit_out works" + +log_onexit cleanup + +save_tunable SIT_OUT_CHECK_INTERVAL +set_tunable64 SIT_OUT_CHECK_INTERVAL 20 + +log_must truncate -s 150M $TEST_BASE_DIR/vdev.$$.{0..9} + +log_must zpool create $TESTPOOL2 draid2 $TEST_BASE_DIR/vdev.$$.{0..9} +log_must zpool set autosit=on $TESTPOOL2 draid2-0 +log_must dd if=/dev/urandom of=/$TESTPOOL2/bigfile bs=1M count=400 +log_must zpool export $TESTPOOL2 +log_must zpool import -d $TEST_BASE_DIR $TESTPOOL2 + +BAD_VDEV1=$TEST_BASE_DIR/vdev.$$.7 +BAD_VDEV2=$TEST_BASE_DIR/vdev.$$.8 +BAD_VDEV3=$TEST_BASE_DIR/vdev.$$.9 + +# Initial state should not be sitting out +log_must eval [[ "$(get_vdev_prop autosit $TESTPOOL2 draid2-0)" == "on" ]] +log_must eval [[ "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV1)" == "off" ]] +log_must eval [[ "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV2)" == "off" ]] +log_must eval [[ "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV3)" == "off" ]] + +# Delay our reads 200ms to trigger sit out +log_must zinject -d $BAD_VDEV1 -D200:1 -T read $TESTPOOL2 + +# Do some reads and wait for us to sit out +for i in {0..99} ; do + dd if=/$TESTPOOL2/bigfile skip=$i bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 100)) bs=2M count=1 of=/dev/null + + sit_out=$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV1) + if [[ "$sit_out" == "on" ]] ; then + break + fi +done +log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV1)" == "on" + +log_must zinject -d $BAD_VDEV2 -D200:1 -T read $TESTPOOL2 +# Do some reads and wait for us to sit out +for i in {0..99} ; do + dd if=/$TESTPOOL2/bigfile skip=$i bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 100)) bs=2M count=1 of=/dev/null + + sit_out=$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV2) + if [[ "$sit_out" == "on" ]] ; then + break + fi +done +log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV2)" == "on" + +log_must zinject -d $BAD_VDEV3 -D200:1 -T read $TESTPOOL2 +# Do some reads and wait for us to sit out +for i in {0..99} ; do + dd if=/$TESTPOOL2/bigfile skip=$i bs=2M count=1 of=/dev/null & + dd if=/$TESTPOOL2/bigfile skip=$((i + 100)) bs=2M count=1 of=/dev/null + + sit_out=$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV3) + if [[ "$sit_out" == "on" ]] ; then + break + fi +done +log_must test "$(get_vdev_prop sit_out $TESTPOOL2 $BAD_VDEV3)" == "off" + + +log_pass "sit_out works correctly" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/zed_synchronous_zedlet.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/zed_synchronous_zedlet.ksh new file mode 100755 index 000000000000..6b732ea96d0c --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/events/zed_synchronous_zedlet.ksh @@ -0,0 +1,149 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025 by Lawrence Livermore National Security, LLC. +# + +# DESCRIPTION: +# Verify ZED synchronous zedlets work as expected +# +# STRATEGY: +# 1. Create a scrub_start zedlet that runs quickly +# 2. Create a scrub_start zedlet that runs slowly (takes seconds) +# 3. Create a scrub_finish zedlet that is synchronous and runs slowly +# 4. Create a trim_start zedlet that runs quickly +# 4. Scrub the pool +# 5. Trim the pool +# 6. Verify the synchronous scrub_finish zedlet waited for the scrub_start +# zedlets to finish (including the slow one). If the scrub_finish zedlet +# was not synchronous, it would have completed before the slow scrub_start +# zedlet. +# 7. Verify the trim_start zedlet waited for the slow synchronous scrub_finish +# zedlet to complete. + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/events/events_common.kshlib + +verify_runnable "both" + +OUR_ZEDLETS="scrub_start-async.sh scrub_start-slow.sh scrub_finish-sync-slow.sh trim_start-async.sh" + +OUTFILE="$TEST_BASE_DIR/zed_synchronous_zedlet_lines" +TESTPOOL2=testpool2 + +function cleanup +{ + zed_stop + + for i in $OUR_ZEDLETS ; do + log_must rm -f $ZEDLET_DIR/$i + done + destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/vdev-file-sync-zedlet + log_must rm -f $OUTFILE +} + +log_assert "Verify ZED synchronous zedlets work as expected" + +log_onexit cleanup + +# Make a pool +log_must truncate -s 100M $TEST_BASE_DIR/vdev-file-sync-zedlet +log_must zpool create $TESTPOOL2 $TEST_BASE_DIR/vdev-file-sync-zedlet + +# Do an initial scrub +log_must zpool scrub -w $TESTPOOL2 + +log_must zpool events -c + +mkdir -p $ZEDLET_DIR + +# Create zedlets +cat << EOF > $ZEDLET_DIR/scrub_start-async.sh +#!/bin/ksh -p +echo "\$(date) \$(basename \$0)" >> $OUTFILE +EOF + +cat << EOF > $ZEDLET_DIR/scrub_start-slow.sh +#!/bin/ksh -p +sleep 3 +echo "\$(date) \$(basename \$0)" >> $OUTFILE +EOF + +cat << EOF > $ZEDLET_DIR/scrub_finish-sync-slow.sh +#!/bin/ksh -p +sleep 3 +echo "\$(date) \$(basename \$0)" >> $OUTFILE +EOF + +cat << EOF > $ZEDLET_DIR/trim_start-async.sh +#!/bin/ksh -p +echo "\$(date) \$(basename \$0)" >> $OUTFILE +EOF + +for i in $OUR_ZEDLETS ; do + log_must chmod +x $ZEDLET_DIR/$i +done + +log_must zed_start + +# Do a scrub - it should be instantaneous. +log_must zpool scrub -w $TESTPOOL2 + +# Start off a trim immediately after scrubiung. The trim should be +# instantaneous and generate a trimp_start event. This will happen in parallel +# with the slow 'scrub_finish-sync-slow.sh' zedlet still running. +log_must zpool trim -w $TESTPOOL2 + +# Wait for scrub_finish event to happen for sanity. This is the *event*, not +# the completion of zedlets for the event. +log_must file_wait_event $ZED_DEBUG_LOG 'sysevent\.fs\.zfs\.trim_finish' 10 + +# At a minimum, scrub_start-slow.sh + scrub_finish-sync-slow.sh will take a +# total of 6 seconds to run, so wait 7 sec to be sure. +sleep 7 + +# If our zedlets were run in the right order, with sync correctly honored, you +# will see this ordering in $OUTFILE: +# +# Fri May 16 12:04:23 PDT 2025 scrub_start-async.sh +# Fri May 16 12:04:26 PDT 2025 scrub_start-slow.sh +# Fri May 16 12:04:31 PDT 2025 scrub_finish-sync-slow.sh +# Fri May 16 12:04:31 PDT 2025 trim_start-async.sh +# +# Check for this ordering + +# Get a list of just the script names in the order they were executed +# from OUTFILE +lines="$(echo $(grep -Eo '(scrub|trim)_.+\.sh$' $OUTFILE))" + +# Compare it to the ordering we expect +expected="\ +scrub_start-async.sh \ +scrub_start-slow.sh \ +scrub_finish-sync-slow.sh \ +trim_start-async.sh" +log_must test "$lines" == "$expected" + +log_pass "Verified synchronous zedlets" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh index ef49a5d50f6c..45848bec1f5a 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_001_pos.ksh @@ -86,7 +86,7 @@ log_must zpool set autoreplace=on $TESTPOOL # Add some data to the pool log_must zfs create $TESTPOOL/fs -log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 Z +log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 R log_must zpool export $TESTPOOL # Record the partition UUID for later comparison diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh index a77957f32255..878b4e450340 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/auto_replace_002_pos.ksh @@ -119,7 +119,7 @@ log_must zpool set autoreplace=on $TESTPOOL # Add some data to the pool log_must zfs create $TESTPOOL/fs -log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 Z +log_must fill_fs /$TESTPOOL/fs 4 100 4096 512 R log_must zpool export $TESTPOOL # Record the partition UUID for later comparison diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/fault_limits.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/fault_limits.ksh index 1b3310edb98b..45b041503e22 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/fault_limits.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/fault_limits.ksh @@ -67,7 +67,7 @@ log_must zpool create -f ${TESTPOOL} raidz${PARITY} ${disks[1..$((VDEV_CNT - 1)) # Add some data to the pool log_must zfs create $TESTPOOL/fs MNTPOINT="$(get_prop mountpoint $TESTPOOL/fs)" -log_must fill_fs $MNTPOINT $PARITY 200 32768 1000 Z +log_must fill_fs $MNTPOINT $PARITY 200 32768 100 R sync_pool $TESTPOOL # Replace the last child vdev to form a replacing vdev diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/suspend_on_probe_errors.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/suspend_on_probe_errors.ksh index 340994bb60c5..b5df1c7e37f8 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/suspend_on_probe_errors.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/fault/suspend_on_probe_errors.ksh @@ -101,7 +101,7 @@ sync_pool $TESTPOOL log_must zfs create $TESTPOOL/fs MNTPOINT="$(get_prop mountpoint $TESTPOOL/fs)" SECONDS=0 -log_must fill_fs $MNTPOINT 1 200 4096 10 Z +log_must fill_fs $MNTPOINT 1 200 4096 10 R log_note "fill_fs took $SECONDS seconds" sync_pool $TESTPOOL diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mount/mount_loopback.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mount/mount_loopback.ksh new file mode 100755 index 000000000000..86adef7ea032 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mount/mount_loopback.ksh @@ -0,0 +1,111 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# Copyright (c) 2025 by Lawrence Livermore National Security, LLC. + +. $STF_SUITE/include/libtest.shlib + +# +# DESCRIPTION: +# Verify that we can make an xfs filesystem on a ZFS-backed loopback device. +# +# See: +# https://github.com/openzfs/zfs/pull/17298 +# https://github.com/openzfs/zfs/issues/17277 +# +# STRATEGY: +# 1. Make a pool +# 2. Make a file on the pool or create zvol +# 3. Mount the file/zvol behind a loopback device +# 4. Create & mount an xfs filesystem on the loopback device + +function cleanup +{ + if [ -d $TEST_BASE_DIR/mnt ] ; then + umount $TEST_BASE_DIR/mnt + log_must rmdir $TEST_BASE_DIR/mnt + fi + if [ -n "$DEV" ] ; then + log_must losetup -d $DEV + fi + destroy_pool $TESTPOOL2 + log_must rm -f $TEST_BASE_DIR/file1 +} + +if [ ! -x "$(which mkfs.xfs)" ] ; then + log_unsupported "No mkfs.xfs binary" +fi + +if [ ! -d /lib/modules/$(uname -r)/kernel/fs/xfs ] && \ + ! grep -qE '\sxfs$' /proc/filesystems ; then + log_unsupported "No XFS kernel support" +fi + +log_assert "Make an xfs filesystem on a ZFS-backed loopback device" +log_onexit cleanup + +# fio options +export NUMJOBS=2 +export RUNTIME=3 +export PERF_RANDSEED=1234 +export PERF_COMPPERCENT=66 +export PERF_COMPCHUNK=0 +export BLOCKSIZE=128K +export SYNC_TYPE=0 +export FILE_SIZE=$(( 1024 * 1024 )) + +function do_test +{ + imgfile=$1 + log_note "Running test on $imgfile" + log_must losetup -f $imgfile + DEV=$(losetup --associated $imgfile | grep -Eo '^/dev/loop[0-9]+') + log_must mkfs.xfs $DEV + mkdir $TEST_BASE_DIR/mnt + log_must mount $DEV $TEST_BASE_DIR/mnt + export DIRECTORY=$TEST_BASE_DIR/mnt + + for d in 0 1 ; do + # fio options + export DIRECT=$d + log_must fio $FIO_SCRIPTS/mkfiles.fio + log_must fio $FIO_SCRIPTS/random_reads.fio + done + log_must umount $TEST_BASE_DIR/mnt + log_must rmdir $TEST_BASE_DIR/mnt + log_must losetup -d $DEV + DEV="" +} + +log_must truncate -s 1G $TEST_BASE_DIR/file1 +log_must zpool create $TESTPOOL2 $TEST_BASE_DIR/file1 +log_must truncate -s 512M /$TESTPOOL2/img +do_test /$TESTPOOL2/img +log_must rm /$TESTPOOL2/img +log_must zfs create -V 512M $TESTPOOL2/vol + +blkdev="$ZVOL_DEVDIR/$TESTPOOL2/vol" +block_device_wait $blkdev +do_test $blkdev + +log_pass "Verified xfs filesystem on a ZFS-backed loopback device" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh index 3249bd93d5ce..a1da4a8631e1 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/refreserv/refreserv_raidz.ksh @@ -17,6 +17,7 @@ . $STF_SUITE/include/libtest.shlib . $STF_SUITE/tests/functional/refreserv/refreserv.cfg +. $STF_SUITE/tests/functional/zvol/zvol_misc/zvol_misc_common.kshlib # # DESCRIPTION: @@ -24,7 +25,7 @@ # # STRATEGY: # 1. Create a pool with a single raidz vdev -# 2. For each block size [512b, 1k, 128k] or [4k, 8k, 128k] +# 2. For each block size [4k, 8k, 128k] # - create a volume # - fully overwrite it # - verify that referenced is less than or equal to reservation @@ -38,6 +39,7 @@ # 1. This test will use up to 14 disks but can cover the key concepts with # 5 disks. # 2. If the disks are a mixture of 4Kn and 512n/512e, failures are likely. +# Therefore, when creating the pool we specify 4Kn sectors. # verify_runnable "global" @@ -60,29 +62,10 @@ log_onexit cleanup poolexists "$TESTPOOL" && log_must_busy zpool destroy "$TESTPOOL" -# Testing tiny block sizes on ashift=12 pools causes so much size inflation -# that small test disks may fill before creating small volumes. However, -# testing 512b and 1K blocks on ashift=9 pools is an ok approximation for -# testing the problems that arise from 4K and 8K blocks on ashift=12 pools. -if is_freebsd; then - bps=$(diskinfo -v ${alldisks[0]} | awk '/sectorsize/ { print $1 }') -elif is_linux; then - bps=$(lsblk -nrdo min-io /dev/${alldisks[0]}) -fi -log_must test "$bps" -eq 512 -o "$bps" -eq 4096 -case "$bps" in -512) - allshifts=(9 10 17) - maxpct=151 - ;; -4096) - allshifts=(12 13 17) - maxpct=110 - ;; -*) - log_fail "bytes/sector: $bps != (512|4096)" - ;; -esac +ashift=12 +allshifts=(12 13 17) +maxpct=110 + log_note "Testing in ashift=${allshifts[0]} mode" # This loop handles all iterations of steps 1 through 4 described in strategy @@ -99,18 +82,21 @@ for parity in 1 2 3; do continue fi - log_must zpool create -O compression=off "$TESTPOOL" "$raid" "${disks[@]}" + log_must zpool create -o ashift=$ashift "$TESTPOOL" "$raid" "${disks[@]}" for bits in "${allshifts[@]}"; do vbs=$((1 << bits)) log_note "Testing $raid-$ndisks volblocksize=$vbs" - vol=$TESTPOOL/$TESTVOL + vol=$TESTPOOL/$TESTVOL-$vbs + zdev=$ZVOL_DEVDIR/$vol log_must zfs create -V ${volsize}m \ -o volblocksize=$vbs "$vol" - block_device_wait "/dev/zvol/$vol" - log_must dd if=/dev/zero of=/dev/zvol/$vol \ - bs=1024k count=$volsize + block_device_wait $zdev + blockdev_exists $zdev + + log_must timeout 120 dd if=/dev/urandom of=$zdev \ + bs=1024k count=$volsize status=progress sync_pool $TESTPOOL ref=$(zfs get -Hpo value referenced "$vol") @@ -126,7 +112,7 @@ for parity in 1 2 3; do log_must test "$deltapct" -le $maxpct log_must_busy zfs destroy "$vol" - block_device_wait + blockdev_missing $zdev done log_must_busy zpool destroy "$TESTPOOL" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/attach_resilver_sit_out.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/attach_resilver_sit_out.ksh new file mode 100755 index 000000000000..6820aba184b7 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/attach_resilver_sit_out.ksh @@ -0,0 +1,189 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# Copyright (c) 2025, Klara, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/replacement/replacement.cfg + +# +# DESCRIPTION: +# Attaching disks while a disk is sitting out reads should pass +# +# STRATEGY: +# 1. Create raidz pools +# 2. Make one disk slower and trigger a read sit out for that disk +# 3. Start some random I/O +# 4. Attach a disk to the pool. +# 5. Verify the integrity of the file system and the resilvering. + +verify_runnable "global" + +save_tunable READ_SIT_OUT_SECS +set_tunable32 READ_SIT_OUT_SECS 120 +save_tunable SIT_OUT_CHECK_INTERVAL +set_tunable64 SIT_OUT_CHECK_INTERVAL 20 + +function cleanup +{ + restore_tunable READ_SIT_OUT_SECS + restore_tunable SIT_OUT_CHECK_INTERVAL + log_must zinject -c all + log_must zpool events -c + + if [[ -n "$child_pids" ]]; then + for wait_pid in $child_pids; do + kill $wait_pid + done + fi + + if poolexists $TESTPOOL1; then + destroy_pool $TESTPOOL1 + fi + + [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/* +} + +log_assert "Replacing a disk during I/O with a sit out completes." + +options="" +options_display="default options" + +log_onexit cleanup + +[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE " + +[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE " + +[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT " + +[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED " + +[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET " + +options="$options -r " + +[[ -n "$options" ]] && options_display=$options + +child_pids="" + +function attach_test +{ + typeset vdev=$1 + typeset disk=$2 + + typeset i=0 + while [[ $i -lt $iters ]]; do + log_note "Invoking file_trunc with: $options_display on $TESTFILE.$i" + file_trunc $options $TESTDIR/$TESTFILE.$i & + typeset pid=$! + + sleep 1 + + child_pids="$child_pids $pid" + ((i = i + 1)) + done + + # attach disk with a slow drive still present + SECONDS=0 + log_must zpool attach -w $TESTPOOL1 $vdev $disk + log_note took $SECONDS seconds to attach disk + + for wait_pid in $child_pids + do + kill $wait_pid + done + child_pids="" + + log_must zinject -c all + log_must zpool export $TESTPOOL1 + log_must zpool import -d $TESTDIR $TESTPOOL1 + log_must zfs umount $TESTPOOL1/$TESTFS1 + log_must zdb -cdui $TESTPOOL1/$TESTFS1 + log_must zfs mount $TESTPOOL1/$TESTFS1 + verify_pool $TESTPOOL1 +} + +DEVSIZE="150M" +specials_list="" +i=0 +while [[ $i != 10 ]]; do + truncate -s $DEVSIZE $TESTDIR/$TESTFILE1.$i + specials_list="$specials_list $TESTDIR/$TESTFILE1.$i" + + ((i = i + 1)) +done + +slow_disk=$TESTDIR/$TESTFILE1.3 +log_must truncate -s $DEVSIZE $TESTDIR/$REPLACEFILE + +# Test file size in MB +count=200 + +for type in "raidz1" "raidz2" "raidz3" ; do + create_pool $TESTPOOL1 $type $specials_list + log_must zpool set autosit=on $TESTPOOL1 "${type}-0" + log_must zfs create -o primarycache=none -o recordsize=512K \ + $TESTPOOL1/$TESTFS1 + log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1 + + log_must dd if=/dev/urandom of=/$TESTDIR1/bigfile bs=1M count=$count + + # Make one disk 100ms slower to trigger a sit out + log_must zinject -d $slow_disk -D100:1 -T read $TESTPOOL1 + + # Do some reads and wait for sit out on slow disk + SECONDS=0 + typeset -i size=0 + for i in $(seq 1 $count) ; do + dd if=/$TESTDIR1/bigfile skip=$i bs=1M count=1 of=/dev/null + size=$i + + sit_out=$(get_vdev_prop sit_out $TESTPOOL1 $slow_disk) + if [[ "$sit_out" == "on" ]] ; then + break + fi + done + + log_must test "$(get_vdev_prop sit_out $TESTPOOL1 $slow_disk)" == "on" + log_note took $SECONDS seconds to reach sit out reading ${size}M + log_must zpool status -s $TESTPOOL1 + + typeset top=$(zpool status -j | jq -r ".pools.$TESTPOOL1.vdevs[].vdevs[].name") + attach_test $top $TESTDIR/$REPLACEFILE + + log_must eval "zpool iostat -v $TESTPOOL1 | grep \"$REPLACEFILE\"" + + destroy_pool $TESTPOOL1 + log_must rm -rf /$TESTPOOL1 +done + +log_pass diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/replace_resilver_sit_out.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/replace_resilver_sit_out.ksh new file mode 100755 index 000000000000..4109dbaf45ac --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/replacement/replace_resilver_sit_out.ksh @@ -0,0 +1,199 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright 2008 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2013, 2016 by Delphix. All rights reserved. +# Copyright (c) 2025, Klara, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/replacement/replacement.cfg + +# +# DESCRIPTION: +# Replacing disks while a disk is sitting out reads should pass +# +# STRATEGY: +# 1. Create raidz and draid pools +# 2. Make one disk slower and trigger a read sit out for that disk +# 3. Start some random I/O +# 4. Replace a disk in the pool with another disk. +# 5. Verify the integrity of the file system and the resilvering. +# + +verify_runnable "global" + +save_tunable READ_SIT_OUT_SECS +set_tunable32 READ_SIT_OUT_SECS 120 +save_tunable SIT_OUT_CHECK_INTERVAL +set_tunable64 SIT_OUT_CHECK_INTERVAL 20 + +function cleanup +{ + restore_tunable READ_SIT_OUT_SECS + restore_tunable SIT_OUT_CHECK_INTERVAL + log_must zinject -c all + log_must zpool events -c + + if [[ -n "$child_pids" ]]; then + for wait_pid in $child_pids + do + kill $wait_pid + done + fi + + if poolexists $TESTPOOL1; then + destroy_pool $TESTPOOL1 + fi + + [[ -e $TESTDIR ]] && log_must rm -rf $TESTDIR/* +} + +log_assert "Replacing a disk during I/O with a sit out completes." + +options="" +options_display="default options" + +log_onexit cleanup + +[[ -n "$HOLES_FILESIZE" ]] && options=" $options -f $HOLES_FILESIZE " + +[[ -n "$HOLES_BLKSIZE" ]] && options="$options -b $HOLES_BLKSIZE " + +[[ -n "$HOLES_COUNT" ]] && options="$options -c $HOLES_COUNT " + +[[ -n "$HOLES_SEED" ]] && options="$options -s $HOLES_SEED " + +[[ -n "$HOLES_FILEOFFSET" ]] && options="$options -o $HOLES_FILEOFFSET " + +options="$options -r " + +[[ -n "$options" ]] && options_display=$options + +child_pids="" + +function replace_test +{ + typeset -i iters=2 + typeset disk1=$1 + typeset disk2=$2 + typeset repl_type=$3 + + typeset i=0 + while [[ $i -lt $iters ]]; do + log_note "Invoking file_trunc with: $options_display on $TESTFILE.$i" + file_trunc $options $TESTDIR/$TESTFILE.$i & + typeset pid=$! + + sleep 1 + + child_pids="$child_pids $pid" + ((i = i + 1)) + done + + typeset repl_flag="-w" + if [[ "$repl_type" == "seq" ]]; then + repl_flag="-ws" + fi + # replace disk with a slow drive still present + SECONDS=0 + log_must zpool replace $repl_flag $TESTPOOL1 $disk1 $disk2 + log_note took $SECONDS seconds to replace disk + + for wait_pid in $child_pids + do + kill $wait_pid + done + child_pids="" + + log_must zinject -c all + log_must zpool export $TESTPOOL1 + log_must zpool import -d $TESTDIR $TESTPOOL1 + log_must zfs umount $TESTPOOL1/$TESTFS1 + log_must zdb -cdui $TESTPOOL1/$TESTFS1 + log_must zfs mount $TESTPOOL1/$TESTFS1 + verify_pool $TESTPOOL1 +} + +DEVSIZE="150M" +specials_list="" +i=0 +while [[ $i != 10 ]]; do + log_must truncate -s $DEVSIZE $TESTDIR/$TESTFILE1.$i + specials_list="$specials_list $TESTDIR/$TESTFILE1.$i" + + ((i = i + 1)) +done + +slow_disk=$TESTDIR/$TESTFILE1.3 +log_must truncate -s $DEVSIZE $TESTDIR/$REPLACEFILE + +# Test file size in MB +count=400 + +for type in "raidz2" "raidz3" "draid2"; do + create_pool $TESTPOOL1 $type $specials_list + log_must zpool set autosit=on $TESTPOOL1 "${type}-0" + log_must zfs create -o primarycache=none -o recordsize=512K \ + $TESTPOOL1/$TESTFS1 + log_must zfs set mountpoint=$TESTDIR1 $TESTPOOL1/$TESTFS1 + + log_must dd if=/dev/urandom of=/$TESTDIR1/bigfile bs=1M count=$count + + # Make one disk 100ms slower to trigger a sit out + log_must zinject -d $slow_disk -D100:1 -T read $TESTPOOL1 + + # Do some reads and wait for sit out on slow disk + SECONDS=0 + typeset -i size=0 + for i in $(seq 1 $count) ; do + dd if=/$TESTDIR1/bigfile skip=$i bs=1M count=1 of=/dev/null + size=$i + + sit_out=$(get_vdev_prop sit_out $TESTPOOL1 $slow_disk) + if [[ "$sit_out" == "on" ]] ; then + break + fi + done + log_must test "$(get_vdev_prop sit_out $TESTPOOL1 $slow_disk)" == "on" + log_note took $SECONDS seconds to reach sit out reading ${size}M + log_must zpool status -s $TESTPOOL1 + + typeset repl_type="replace" + if [[ "$type" == "draid2" && $((RANDOM % 2)) -eq 0 ]]; then + repl_type="seq" + fi + replace_test $TESTDIR/$TESTFILE1.1 $TESTDIR/$REPLACEFILE $repl_type + + log_must eval "zpool iostat -v $TESTPOOL1 | grep \"$REPLACEFILE\"" + + destroy_pool $TESTPOOL1 + log_must rm -rf /$TESTPOOL1 +done + +log_pass diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/setup.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/setup.ksh index 26153aafbc02..0e79e9b8b70c 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/setup.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/setup.ksh @@ -39,6 +39,6 @@ verify_runnable "global" # create a pool without any features -log_must mkfile 128m $TMPDEV +log_must truncate -s $MINVDEVSIZE $TMPDEV log_pass diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh index d6bd69b7e134..e81d07794689 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/upgrade/upgrade_readonly_pool.ksh @@ -35,17 +35,19 @@ verify_runnable "global" -TESTFILE="$TESTDIR/file.bin" - log_assert "User accounting upgrade should not be executed on readonly pool" log_onexit cleanup_upgrade # 1. Create a pool with the feature@userobj_accounting disabled to simulate # a legacy pool from a previous ZFS version. -log_must zpool create -d -m $TESTDIR $TESTPOOL $TMPDEV +log_must zpool create -d $TESTPOOL $TMPDEV +log_must zfs create $TESTPOOL/$TESTFS + +MNTPNT=$(get_prop mountpoint $TESTPOOL/$TESTFS) +TESTFILE="$MNTPNT/file.bin" # 2. Create a file on the "legecy" dataset -log_must touch $TESTDIR/file.bin +log_must touch $TESTFILE # 3. Enable feature@userobj_accounting on the pool and verify it is only # "enabled" and not "active": upgrading starts when the filesystem is mounted @@ -54,12 +56,12 @@ log_must test "enabled" == "$(get_pool_prop 'feature@userobj_accounting' $TESTPO # 4. Export the pool and re-import is readonly, without mounting any filesystem log_must zpool export $TESTPOOL -log_must zpool import -o readonly=on -N -d "$(dirname $TMPDEV)" $TESTPOOL +log_must zpool import -o readonly=on -N -d $TEST_BASE_DIR $TESTPOOL # 5. Try to mount the root dataset manually without the "ro" option, then verify # filesystem status and the pool feature status (not "active") to ensure the # pool "readonly" status is enforced. -log_must mount -t zfs -o zfsutil $TESTPOOL $TESTDIR +log_must zfs mount -R $TESTPOOL log_must stat "$TESTFILE" log_mustnot touch "$TESTFILE" log_must test "enabled" == "$(get_pool_prop 'feature@userobj_accounting' $TESTPOOL)" diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_014_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_014_pos.ksh new file mode 100755 index 000000000000..d4c9a0a41816 --- /dev/null +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/xattr/xattr_014_pos.ksh @@ -0,0 +1,53 @@ +#!/bin/ksh -p +# SPDX-License-Identifier: CDDL-1.0 +# +# CDDL HEADER START +# +# The contents of this file are subject to the terms of the +# Common Development and Distribution License (the "License"). +# You may not use this file except in compliance with the License. +# +# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE +# or https://opensource.org/licenses/CDDL-1.0. +# See the License for the specific language governing permissions +# and limitations under the License. +# +# When distributing Covered Code, include this CDDL HEADER in each +# file and include the License file at usr/src/OPENSOLARIS.LICENSE. +# If applicable, add the following below this CDDL HEADER, with the +# fields enclosed by brackets "[]" replaced with your own identifying +# information: Portions Copyright [yyyy] [name of copyright owner] +# +# CDDL HEADER END +# + +# +# Copyright (c) 2025 by Klara, Inc. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/xattr/xattr_common.kshlib + +# +# DESCRIPTION: +# The default xattr should be shown as 'sa', not 'on', for clarity. +# +# STRATEGY: +# 1. Create a filesystem. +# 2. Verify that the xattra is shown as 'sa'. +# 3. Manually set the value to 'dir', 'sa', 'on', and 'off'. +# 4. Verify that it is shown as 'dir', 'sa', 'sa', and 'off. +# + +log_assert "The default and specific xattr values are displayed correctly." + +set -A args "dir" "sa" "on" "off" +set -A display "dir" "sa" "sa" "off" + +log_must eval "[[ 'sa' == '$(zfs get -Hpo value xattr $TESTPOOL)' ]]" + +for i in `seq 0 3`; do + log_must zfs set xattr="${args[$i]}" $TESTPOOL + log_must eval "[[ '${display[$i]}' == '$(zfs get -Hpo value xattr $TESTPOOL)' ]]" +done +log_pass "The default and specific xattr values are displayed correctly." diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh index 571a698eb63a..502ebada22dc 100755 --- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh +++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/zvol/zvol_misc/zvol_misc_fua.ksh @@ -50,17 +50,53 @@ fi typeset datafile1="$(mktemp -t zvol_misc_fua1.XXXXXX)" typeset datafile2="$(mktemp -t zvol_misc_fua2.XXXXXX)" +typeset datafile3="$(mktemp -t zvol_misc_fua3_log.XXXXXX)" typeset zvolpath=${ZVOL_DEVDIR}/$TESTPOOL/$TESTVOL +typeset DISK1=${DISKS%% *} function cleanup { - rm "$datafile1" "$datafile2" + log_must zpool remove $TESTPOOL $datafile3 + rm "$datafile1" "$datafile2" "$datafile2" +} + +# Prints the total number of sync writes for a vdev +# $1: vdev +function get_sync +{ + zpool iostat -p -H -v -r $TESTPOOL $1 | \ + awk '/[0-9]+$/{s+=$4+$5} END{print s}' } function do_test { # Wait for udev to create symlinks to our zvol block_device_wait $zvolpath + # Write using sync (creates FLUSH calls after writes, but not FUA) + old_vdev_writes=$(get_sync $DISK1) + old_log_writes=$(get_sync $datafile3) + + log_must fio --name=write_iops --size=5M \ + --ioengine=libaio --verify=0 --bs=4K \ + --iodepth=1 --rw=randwrite --group_reporting=1 \ + --filename=$zvolpath --sync=1 + + vdev_writes=$(( $(get_sync $DISK1) - $old_vdev_writes)) + log_writes=$(( $(get_sync $datafile3) - $old_log_writes)) + + # When we're doing sync writes, we should see many more writes go to + # the log vs the first vdev. Experiments show anywhere from a 160-320x + # ratio of writes to the log vs the first vdev (due to some straggler + # writes to the first vdev). + # + # Check that we have a large ratio (100x) of sync writes going to the + # log device + ratio=$(($log_writes / $vdev_writes)) + log_note "Got $log_writes log writes, $vdev_writes vdev writes." + if [ $ratio -lt 100 ] ; then + log_fail "Expected > 100x more log writes than vdev writes. " + fi + # Create a data file log_must dd if=/dev/urandom of="$datafile1" bs=1M count=5 @@ -81,6 +117,8 @@ log_assert "Verify that a ZFS volume can do Force Unit Access (FUA)" log_onexit cleanup log_must zfs set compression=off $TESTPOOL/$TESTVOL +log_must truncate -s 100M $datafile3 +log_must zpool add $TESTPOOL log $datafile3 log_note "Testing without blk-mq" |