aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/tests/zfs-tests
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/tests/zfs-tests')
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/callbacks/zfs_dmesg.ksh7
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/draid.c2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/idmap_util.c2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/mktree.c2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_ftruncate.c85
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am15
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh5
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh8
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh5
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh5
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh2
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh4
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh39
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh46
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh21
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh71
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh100
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh2
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh3
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg3
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_multiple_pools.ksh131
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh3
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_001.ksh94
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_pools.ksh128
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple_pools.ksh123
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks.kshlib17
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_neg.ksh53
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_pos.ksh81
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_multi.ksh54
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/mmap/mmap_ftruncate.ksh80
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh2
38 files changed, 1103 insertions, 109 deletions
diff --git a/sys/contrib/openzfs/tests/zfs-tests/callbacks/zfs_dmesg.ksh b/sys/contrib/openzfs/tests/zfs-tests/callbacks/zfs_dmesg.ksh
index 73c654125319..de31765a52e4 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/callbacks/zfs_dmesg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/callbacks/zfs_dmesg.ksh
@@ -15,6 +15,7 @@
#
# Copyright (c) 2016 by Delphix. All rights reserved.
# Copyright (c) 2017 Lawrence Livermore National Security, LLC.
+# Copyright (c) 2025, Klara, Inc.
#
# $1: number of lines to output (default: 200)
@@ -25,7 +26,11 @@ echo " Tailing last $lines lines of dmesg log"
echo "================================================================="
# report and reset afterwards
-sudo dmesg -c | tail -n $lines
+dmesg_args="-c"
+if [[ $(uname) = "Linux" ]] ; then
+ dmesg_args="$dmesg_args --time-format=iso"
+fi
+sudo dmesg $dmesg_args | tail -n $lines
echo "================================================================="
echo " End of dmesg log"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
index e9a6f8f0ac17..1cd90024e94d 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
@@ -23,6 +23,7 @@
/mkfiles
/mktree
/mmap_exec
+/mmap_ftruncate
/mmap_libaio
/mmap_seek
/mmap_sync
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
index 909a72c43d80..d5448055a1e1 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
@@ -72,7 +72,9 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/mkbusy %D%/mkfile %D%/mkfiles %D%/mktree
%C%_mkfile_LDADD = $(LTLIBINTL)
-scripts_zfs_tests_bin_PROGRAMS += %D%/mmap_exec %D%/mmap_seek %D%/mmap_sync %D%/mmapwrite %D%/readmmap
+scripts_zfs_tests_bin_PROGRAMS += \
+ %D%/mmap_exec %D%/mmap_ftruncate %D%/mmap_seek \
+ %D%/mmap_sync %D%/mmapwrite %D%/readmmap
%C%_mmapwrite_LDADD = -lpthread
if WANT_MMAP_LIBAIO
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/draid.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/draid.c
index 8d0bdc450f80..2c1ab1b9bec3 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/draid.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/draid.c
@@ -204,7 +204,7 @@ write_map(const char *filename, nvlist_t *allcfgs)
error = errno;
free(buf);
free(tmpname);
- return (errno);
+ return (error);
}
ssize_t rc, bytes = 0;
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/idmap_util.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/idmap_util.c
index 416e80714f9b..f332677f520c 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/idmap_util.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/idmap_util.c
@@ -301,7 +301,7 @@ static int
write_idmap(pid_t pid, char *buf, size_t buf_size, idmap_type_t type)
{
char path[PATH_MAX];
- int fd = -EBADF;
+ int fd;
int ret;
(void) snprintf(path, sizeof (path), "/proc/%d/%cid_map",
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/mktree.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/mktree.c
index 297cf6dea415..9a5253468bd2 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/mktree.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/mktree.c
@@ -152,7 +152,7 @@ getfdname(char *pdir, char type, int level, int dir, int file)
static void
crtfile(char *pname)
{
- int fd = -1;
+ int fd;
int i, size;
const char *context = "0123456789ABCDF";
char *pbuf;
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_ftruncate.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_ftruncate.c
new file mode 100644
index 000000000000..91cdfe3715e6
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_ftruncate.c
@@ -0,0 +1,85 @@
+// 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 http://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.
+ */
+
+/*
+ * Tests async writeback behaviour. Creates a file, maps it into memory, and
+ * dirties every page within it. Then, calls ftruncate() to collapse the file
+ * back down to 0. This causes the kernel to begin writeback on the dirty
+ * pages so they can be freed, before it can complete the ftruncate() call.
+ * None of these are sync operations, so they should avoid the various "force
+ * flush" codepaths.
+ */
+
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#define _pdfail(f, l, s) \
+ do { perror("[" f "#" #l "] " s); exit(2); } while (0)
+#define pdfail(str) _pdfail(__FILE__, __LINE__, str)
+
+int
+main(int argc, char **argv) {
+ if (argc != 3) {
+ printf("usage: mmap_ftruncate <file> <size>\n");
+ exit(2);
+ }
+
+ const char *file = argv[1];
+
+ char *end;
+ off_t sz = strtoull(argv[2], &end, 0);
+ if (end == argv[2] || *end != '\0' || sz == 0) {
+ fprintf(stderr, "E: invalid size");
+ exit(2);
+ }
+
+ int fd = open(file, O_CREAT|O_TRUNC|O_RDWR, S_IRUSR|S_IWUSR);
+ if (fd < 0)
+ pdfail("open");
+
+ if (ftruncate(fd, sz) < 0)
+ pdfail("ftruncate");
+
+ char *p = mmap(NULL, sz, PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED)
+ pdfail("mmap");
+
+ for (off_t off = 0; off < sz; off += 4096)
+ p[off] = 1;
+
+ if (ftruncate(fd, 0) < 0)
+ pdfail("ftruncate");
+
+ if (munmap(p, sz) < 0)
+ pdfail("munmap");
+
+ close(fd);
+ return (0);
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c
index 61fcdc35af13..31d61ffb07d0 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmapwrite.c
@@ -59,7 +59,7 @@ static void *
normal_writer(void *filename)
{
char *file_path = filename;
- int fd = -1;
+ int fd;
ssize_t write_num = 0;
int page_size = getpagesize();
@@ -93,7 +93,7 @@ normal_writer(void *filename)
static void *
map_writer(void *filename)
{
- int fd = -1;
+ int fd;
int ret = 0;
char *buf = NULL;
int page_size = getpagesize();
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
index 1c7e42a06e05..bbaa8665ecc8 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
@@ -205,6 +205,7 @@ export ZFSTEST_FILES='badsend
mkfiles
mktree
mmap_exec
+ mmap_ftruncate
mmap_libaio
mmap_seek
mmap_sync
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
index 4b8db189310f..23e89599cae0 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/libtest.shlib
@@ -2884,7 +2884,9 @@ function user_run
typeset out=$TEST_BASE_DIR/out
typeset err=$TEST_BASE_DIR/err
- sudo -Eu $user env PATH="$PATH" ksh <<<"$*" >$out 2>$err
+ sudo -Eu $user \
+ env PATH="$PATH" ZTS_LOG_SUPPRESS_TIMESTAMP=1 \
+ ksh <<<"$*" >$out 2>$err
typeset res=$?
log_note "out: $(<$out)"
log_note "err: $(<$err)"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
index 98e14ad97718..e273c9f85c28 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/tunables.cfg
@@ -87,6 +87,7 @@ SPA_ASIZE_INFLATION spa.asize_inflation spa_asize_inflation
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
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 d27660a42c5a..c2542287c1d7 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
@@ -429,8 +429,6 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/alloc_class/alloc_class_011_neg.ksh \
functional/alloc_class/alloc_class_012_pos.ksh \
functional/alloc_class/alloc_class_013_pos.ksh \
- functional/alloc_class/alloc_class_014_neg.ksh \
- functional/alloc_class/alloc_class_015_pos.ksh \
functional/alloc_class/alloc_class_016_pos.ksh \
functional/alloc_class/cleanup.ksh \
functional/alloc_class/setup.ksh \
@@ -647,6 +645,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zdb/zdb_objset_id.ksh \
functional/cli_root/zdb/zdb_recover_2.ksh \
functional/cli_root/zdb/zdb_recover.ksh \
+ functional/cli_root/zdb/zdb_tunables.ksh \
functional/cli_root/zfs_bookmark/cleanup.ksh \
functional/cli_root/zfs_bookmark/setup.ksh \
functional/cli_root/zfs_bookmark/zfs_bookmark_cliargs.ksh \
@@ -870,6 +869,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zfs_rewrite/cleanup.ksh \
functional/cli_root/zfs_rewrite/setup.ksh \
functional/cli_root/zfs_rewrite/zfs_rewrite.ksh \
+ functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh \
functional/cli_root/zfs_rollback/cleanup.ksh \
functional/cli_root/zfs_rollback/setup.ksh \
functional/cli_root/zfs_rollback/zfs_rollback_001_pos.ksh \
@@ -1177,6 +1177,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_import_export.ksh \
+ functional/cli_root/zpool_initialize/zpool_initialize_multiple_pools.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_offline_export_import_online.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_online_offline.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_split.ksh \
@@ -1240,9 +1241,11 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_scrub/zpool_scrub_005_pos.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_encrypted_unloaded.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_multiple_copies.ksh \
+ functional/cli_root/zpool_scrub/zpool_scrub_multiple_pools.ksh \
functional/cli_root/zpool_scrub/zpool_scrub_offline_device.ksh \
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_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 \
@@ -1292,6 +1295,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_trim/zpool_trim_fault_export_import_online.ksh \
functional/cli_root/zpool_trim/zpool_trim_import_export.ksh \
functional/cli_root/zpool_trim/zpool_trim_multiple.ksh \
+ functional/cli_root/zpool_trim/zpool_trim_multiple_pools.ksh \
functional/cli_root/zpool_trim/zpool_trim_neg.ksh \
functional/cli_root/zpool_trim/zpool_trim_offline_export_import_online.ksh \
functional/cli_root/zpool_trim/zpool_trim_online_offline.ksh \
@@ -1444,6 +1448,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/crtime/setup.ksh \
functional/crypto/icp_aes_ccm.ksh \
functional/crypto/icp_aes_gcm.ksh \
+ functional/ctime/cleanup.ksh \
+ functional/ctime/ctime_001_pos.ksh \
+ functional/ctime/setup.ksh \
functional/deadman/deadman_ratelimit.ksh \
functional/deadman/deadman_sync.ksh \
functional/deadman/deadman_zio.ksh \
@@ -1578,6 +1585,9 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/gang_blocks/gang_blocks_001_pos.ksh \
functional/gang_blocks/gang_blocks_ddt_copies.ksh \
functional/gang_blocks/gang_blocks_redundant.ksh \
+ functional/gang_blocks/gang_blocks_dyn_header_neg.ksh \
+ functional/gang_blocks/gang_blocks_dyn_header_pos.ksh \
+ functional/gang_blocks/gang_blocks_dyn_multi.ksh \
functional/gang_blocks/setup.ksh \
functional/grow/grow_pool_001_pos.ksh \
functional/grow/grow_replicas_001_pos.ksh \
@@ -1667,6 +1677,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/mmap/mmap_seek_001_pos.ksh \
functional/mmap/mmap_sync_001_pos.ksh \
functional/mmap/mmap_write_001_pos.ksh \
+ functional/mmap/mmap_ftruncate.ksh \
functional/mmap/setup.ksh \
functional/mmp/cleanup.ksh \
functional/mmp/mmp_active_import.ksh \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh
index 7d6924b2c9bf..79a431a13238 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_002_neg.ksh
@@ -41,9 +41,4 @@ log_mustnot zpool create $TESTPOOL $ZPOOL_DISKS special mirror \
log_mustnot display_status $TESTPOOL
log_mustnot zpool destroy -f $TESTPOOL
-log_mustnot zpool create $TESTPOOL raidz $ZPOOL_DISKS special raidz \
- $CLASS_DISK0 $CLASS_DISK1 $CLASS_DISK2
-log_mustnot display_status $TESTPOOL
-log_mustnot zpool destroy -f $TESTPOOL
-
log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh
index 42d5deda3842..961dcd46429a 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_003_pos.ksh
@@ -32,7 +32,7 @@ log_onexit cleanup
log_must disk_setup
-for type in "" "mirror" "raidz"
+for type in "" "mirror" "raidz" "draid"
do
log_must zpool create $TESTPOOL $type $ZPOOL_DISKS
@@ -47,6 +47,12 @@ do
$CLASS_DISK0 $CLASS_DISK1
log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
log_must zpool iostat -H $TESTPOOL $CLASS_DISK1
+ elif [ "$type" = "draid" ]; then
+ log_must zpool add $TESTPOOL special raidz \
+ $CLASS_DISK0 $CLASS_DISK1 $CLASS_DISK2
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK1
+ log_must zpool iostat -H $TESTPOOL $CLASS_DISK2
else
log_must zpool add $TESTPOOL special $CLASS_DISK0
log_must zpool iostat -H $TESTPOOL $CLASS_DISK0
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh
index 684b6557e3f1..39ddaad1be5b 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_004_pos.ksh
@@ -37,7 +37,7 @@ typeset ac_value
typeset stype=""
typeset sdisks=""
-for type in "" "mirror" "raidz"
+for type in "" "mirror" "raidz" "draid"
do
if [ "$type" = "mirror" ]; then
stype="mirror"
@@ -45,6 +45,9 @@ do
elif [ "$type" = "raidz" ]; then
stype="mirror"
sdisks="${CLASS_DISK0} ${CLASS_DISK1}"
+ elif [ "$type" = "draid" ]; then
+ stype="raidz"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1} ${CLASS_DISK2}"
else
stype=""
sdisks="${CLASS_DISK0}"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh
index 2223bb1c491d..b7e93fc7350e 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_009_pos.ksh
@@ -36,7 +36,7 @@ typeset stype=""
typeset sdisks=""
typeset props=""
-for type in "" "mirror" "raidz"
+for type in "" "mirror" "raidz" "draid"
do
if [ "$type" = "mirror" ]; then
stype="mirror"
@@ -45,6 +45,9 @@ do
elif [ "$type" = "raidz" ]; then
stype="mirror"
sdisks="${CLASS_DISK0} ${CLASS_DISK1}"
+ elif [ "$type" = "draid" ]; then
+ stype="raidz"
+ sdisks="${CLASS_DISK0} ${CLASS_DISK1} ${CLASS_DISK2}"
else
stype=""
sdisks="${CLASS_DISK0}"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh
index 7f9d108ed184..f7dfd42b0f05 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_010_pos.ksh
@@ -36,7 +36,7 @@ log_must disk_setup
log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
$CLASS_DISK0 $CLASS_DISK1
-for value in 0 512 1024 2048 4096 8192 16384 32768 65536 131072
+for value in 0 200 512 1300 4096 12345 131072 1572864 16777216
do
log_must zfs set special_small_blocks=$value $TESTPOOL
ACTUAL=$(zfs get -p special_small_blocks $TESTPOOL | \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh
index a04e9ca43273..0f90117544a6 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_011_neg.ksh
@@ -22,7 +22,7 @@
#
# DESCRIPTION:
# Setting the special_small_blocks property to invalid values fails.
-# Powers of two from 512 to 1M are allowed.
+# Only values between 0 and 16M including are allowed.
#
verify_runnable "global"
@@ -36,7 +36,7 @@ log_must disk_setup
log_must zpool create $TESTPOOL raidz $ZPOOL_DISKS special mirror \
$CLASS_DISK0 $CLASS_DISK1
-for value in 256 1025 33554432
+for value in 16777217 33554432 4294967296
do
log_mustnot zfs set special_small_blocks=$value $TESTPOOL
done
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh
deleted file mode 100755
index e16b64a964e4..000000000000
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_014_neg.ksh
+++ /dev/null
@@ -1,39 +0,0 @@
-#!/bin/ksh -p
-# 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.
-#
-# 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.
-#
-
-. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
-
-#
-# DESCRIPTION:
-# Setting the special_small_blocks property greater than recordsize fails.
-#
-
-verify_runnable "global"
-
-claim="Setting the special_small_blocks property greater than recordsize fails"
-
-log_assert $claim
-log_onexit cleanup
-log_must disk_setup
-
-for size in 512 4096 32768 131072 524288 1048576
-do
- let bigger=$size*2
- log_mustnot zpool create -O recordsize=$size \
- -O special_small_blocks=$bigger \
- $TESTPOOL raidz $ZPOOL_DISKS special mirror \
- $CLASS_DISK0 $CLASS_DISK1
-done
-
-log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh
deleted file mode 100755
index 9d34375b74ca..000000000000
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/alloc_class/alloc_class_015_pos.ksh
+++ /dev/null
@@ -1,46 +0,0 @@
-#!/bin/ksh -p
-# 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.
-#
-# 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.
-#
-
-. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib
-
-#
-# DESCRIPTION:
-# Can set special_small_blocks property less than or equal to recordsize.
-#
-
-verify_runnable "global"
-
-claim="Can set special_small_blocks property less than or equal to recordsize"
-
-log_assert $claim
-log_onexit cleanup
-log_must disk_setup
-
-for size in 8192 32768 131072 524288 1048576
-do
- let smaller=$size/2
- log_must zpool create -O recordsize=$size \
- -O special_small_blocks=$smaller \
- $TESTPOOL raidz $ZPOOL_DISKS special mirror \
- $CLASS_DISK0 $CLASS_DISK1
- log_must zpool destroy -f "$TESTPOOL"
-
- log_must zpool create -O recordsize=$size \
- -O special_small_blocks=$size \
- $TESTPOOL raidz $ZPOOL_DISKS special mirror \
- $CLASS_DISK0 $CLASS_DISK1
- log_must zpool destroy -f "$TESTPOOL"
-done
-
-log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh
index 54ffdc75669a..4cede26b913a 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_copyfilerange_fallback_same_txg.ksh
@@ -41,16 +41,22 @@ function cleanup
{
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
set_tunable64 TXG_TIMEOUT $timeout
+ log_must restore_tunable BCLONE_WAIT_DIRTY
}
log_onexit cleanup
+log_must save_tunable BCLONE_WAIT_DIRTY
+
log_must set_tunable64 TXG_TIMEOUT 5000
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
log_must sync_pool $TESTPOOL true
+# Verify fallback to copy when there are dirty blocks
+log_must set_tunable32 BCLONE_WAIT_DIRTY 0
+
log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=128K count=4
log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 0 0 524288
@@ -61,5 +67,20 @@ log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
log_must [ "$blocks" = "" ]
+log_must rm /$TESTPOOL/file /$TESTPOOL/clone
+
+# Verify blocks are cloned even when there are dirty blocks
+log_must set_tunable32 BCLONE_WAIT_DIRTY 1
+
+log_must dd if=/dev/urandom of=/$TESTPOOL/file bs=128K count=4
+log_must clonefile -f /$TESTPOOL/file /$TESTPOOL/clone 0 0 524288
+
+log_must sync_pool $TESTPOOL
+
+log_must have_same_content /$TESTPOOL/file /$TESTPOOL/clone
+
+typeset blocks=$(get_same_blocks $TESTPOOL file $TESTPOOL clone)
+log_must [ "$blocks" = "0 1 2 3" ]
+
log_pass $claim
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
new file mode 100755
index 000000000000..46965aa7cc37
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zdb/zdb_tunables.ksh
@@ -0,0 +1,71 @@
+#!/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, Rob Norris <robn@despairlabs.com>
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+verify_runnable "both"
+
+log_assert "zdb can work with libzpool tunables"
+
+# a tunable name by itself, or with the "show" command, produces name and value
+log_must eval 'zdb -o zfs_recover | grep -qE "^zfs_recover: 0$"'
+log_must eval 'zdb -o show=zfs_recover | grep -qE "^zfs_recover: 0$"'
+
+# info about a tunable shows a different format
+log_must eval 'zdb -o info=zfs_recover | grep -qE "^zfs_recover \[[[:alnum:]_]+ r[dw]]: .+"'
+
+# "show" by itself shows all the tunables and their values
+# this tests limits to 50 tunables, and then counts the number that match
+# the format, which should be all of them
+log_must test $(zdb -o show | head -50 | grep -cE "^[[:alnum:]_]+: .+") -eq 50
+
+# "info" by itself shows info about all tunables
+# like previous test, we limit and then count
+log_must test $(zdb -o info | head -50 | grep -cE "^[[:alnum:]_]+ \[[[:alnum:]_]+ r[dw]]: .+") -eq 50
+
+# can't lookup nonexistent tunables
+log_mustnot_expect 'no such tunable: hello' zdb -o hello
+log_mustnot_expect 'no such tunable: hello' zdb -o show=hello
+log_mustnot_expect 'no such tunable: hello' zdb -o info=hello
+
+# setting a tunable shows the old and the new value
+log_must eval 'zdb -o zfs_recover=1 | grep -qE "^zfs_recover: 0 -> 1$"'
+
+# replacing a value still sets it
+log_must eval 'zdb -o zfs_recover=0 | grep -qE "^zfs_recover: 0 -> 0$"'
+
+# can't set the "magic" commands
+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$"'
+
+# 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$"'
+
+log_pass "zdb can work with libzpool tunables"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh
new file mode 100755
index 000000000000..142e44f53515
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zfs_rewrite/zfs_rewrite_physical.ksh
@@ -0,0 +1,100 @@
+#!/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, iXsystems, Inc.
+#
+
+# DESCRIPTION:
+# Verify zfs rewrite -P flag correctly preserves logical birth times.
+#
+# STRATEGY:
+# 1. Create a test file and sync it.
+# 2. Create a snapshot to capture the original birth time.
+# 3. Test default rewrite behavior (updates logical birth time).
+# 4. Test -P flag behavior (preserves logical birth time).
+# 5. Verify incremental send behavior difference.
+
+. $STF_SUITE/include/libtest.shlib
+
+typeset tmp=$(mktemp)
+typeset send_default=$(mktemp)
+typeset send_physical=$(mktemp)
+
+function cleanup
+{
+ rm -rf $tmp $send_default $send_physical $TESTDIR/*
+ zfs destroy -R $TESTPOOL/$TESTFS@snap1 2>/dev/null || true
+ zfs destroy -R $TESTPOOL/$TESTFS@snap2 2>/dev/null || true
+ zfs destroy -R $TESTPOOL/$TESTFS@snap3 2>/dev/null || true
+}
+
+log_assert "zfs rewrite -P flag correctly preserves logical birth times"
+
+log_onexit cleanup
+
+log_must zfs set recordsize=128k $TESTPOOL/$TESTFS
+
+# Create test file and initial snapshot
+log_must dd if=/dev/urandom of=$TESTDIR/testfile bs=128k count=4
+log_must sync_pool $TESTPOOL
+typeset orig_hash=$(xxh128digest $TESTDIR/testfile)
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap1
+
+# Test default rewrite behavior (updates logical birth time)
+log_must zfs rewrite $TESTDIR/testfile
+log_must sync_pool $TESTPOOL
+typeset default_hash=$(xxh128digest $TESTDIR/testfile)
+log_must [ "$orig_hash" = "$default_hash" ]
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap2
+
+# Test incremental send size - should be large with updated birth time
+log_must eval "zfs send -i @snap1 $TESTPOOL/$TESTFS@snap2 > $send_default"
+typeset default_size=$(wc -c < $send_default)
+log_note "Default rewrite incremental send size: $default_size bytes"
+
+# Reset the file to original state
+log_must zfs rollback -r $TESTPOOL/$TESTFS@snap1
+
+# Test -P flag behavior (preserves logical birth time)
+log_must zfs rewrite -P $TESTDIR/testfile
+log_must sync_pool $TESTPOOL
+typeset physical_hash=$(xxh128digest $TESTDIR/testfile)
+log_must [ "$orig_hash" = "$physical_hash" ]
+log_must zfs snapshot $TESTPOOL/$TESTFS@snap3
+
+# Test incremental send size - should be minimal with preserved birth time
+log_must eval "zfs send -i @snap1 $TESTPOOL/$TESTFS@snap3 > $send_physical"
+typeset physical_size=$(wc -c < $send_physical)
+log_note "Physical rewrite incremental send size: $physical_size bytes"
+
+# Verify that -P flag produces smaller incremental send
+if [[ $physical_size -lt $default_size ]]; then
+ log_note "SUCCESS: -P flag produces smaller incremental send" \
+ "($physical_size < $default_size)"
+else
+ log_fail "FAIL: -P flag should produce smaller incremental send" \
+ "($physical_size >= $default_size)"
+fi
+
+log_pass
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
index f96d291ccb1c..94ccabeb80a8 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_001_pos.ksh
@@ -50,7 +50,7 @@ function cleanup
function check_features
{
- for state in $(zpool get all $TESTPOOL | \
+ for state in $(zpool get all $TESTPOOL | grep -v "dynamic_gang_header" | \
awk '$2 ~ /feature@/ { print $3 }'); do
if [[ "$state" != "enabled" && "$state" != "active" ]]; then
log_fail "some features are not enabled on new pool"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
index 7366a46f9c81..676aca1a20a5 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_create/zpool_create_features_005_pos.ksh
@@ -58,6 +58,9 @@ function check_features
return 1;
fi
else
+ if [[ "feature@dynamic_gang_header" == "${2}" ]]; then
+ continue
+ fi
# Failure other features must be enabled or active.
if [[ "${3}" != "enabled" && "${3}" != "active" ]]; then
return 2;
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
index cf5e0961f9fd..bdf5fdf85cff 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_get/zpool_get.cfg
@@ -91,6 +91,8 @@ typeset -a properties=(
"feature@device_rebuild"
"feature@draid"
"feature@redaction_list_spill"
+ "feature@dynamic_gang_header"
+ "feature@physical_rewrite"
)
if is_linux || is_freebsd; then
@@ -114,5 +116,6 @@ if is_linux || is_freebsd; then
"feature@fast_dedup"
"feature@longname"
"feature@large_microzap"
+ "feature@block_cloning_endian"
)
fi
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_multiple_pools.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_multiple_pools.ksh
new file mode 100755
index 000000000000..cc7bca5445d2
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_initialize/zpool_initialize_multiple_pools.ksh
@@ -0,0 +1,131 @@
+#!/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) 2025 Hewlett Packard Enterprise Development LP.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_initialize/zpool_initialize.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool initialize -a' works correctly with multiple pools
+#
+# STRATEGY:
+# 1. Create multiple pools.
+# 2. Start a initialize operation on all pools using 'zpool initialize -a'.
+# 3. Verify that the initializing is active on all pools.
+# 4. Wait for the initialize operation to complete.
+# 5. Verify that the initialize operation is complete on all pools.
+# 6. Start a initializing on all pools using 'zpool initialize -w -a'.
+# 7. Verify that the initialize operation is complete on all pools.
+# 8. Now test the -u, -c and -s options on multiple pools with -a.
+# 9. Verify that the initialize status is correctly updated on all pools.
+#
+
+verify_runnable "global"
+
+cleanup() {
+ for pool in {1..4}; do
+ zpool destroy $TESTPOOL${pool}
+ rm -rf $TESTDIR${pool}
+ done
+ rm -f $DISK1 $DISK2 $DISK3 $DISK4
+}
+
+log_onexit cleanup
+
+log_assert "Verify if 'zpool initialize -a' works correctly with multiple pools."
+
+DEVSIZE='5G'
+TESTDIR="$TEST_BASE_DIR/zpool_initialize_multiple_pools"
+DISK1="$TEST_BASE_DIR/zpool_disk1.dat"
+DISK2="$TEST_BASE_DIR/zpool_disk2.dat"
+DISK3="$TEST_BASE_DIR/zpool_disk3.dat"
+DISK4="$TEST_BASE_DIR/zpool_disk4.dat"
+
+truncate -s $DEVSIZE $DISK1
+truncate -s $DEVSIZE $DISK2
+truncate -s $DEVSIZE $DISK3
+truncate -s $DEVSIZE $DISK4
+
+for pool in {1..4}; do
+ DISK[$pool]="$TEST_BASE_DIR/zpool_disk${pool}.dat"
+ truncate -s $DEVSIZE ${DISK[$pool]}
+ log_must zpool create $TESTPOOL${pool} ${DISK[$pool]}
+done
+sync_all_pools
+
+# Start an initialize operation on all pools using 'zpool initialize -a'.
+log_must zpool initialize -a
+
+# Verify that the initializing is active on all pools.
+for pool in {1..4}; do
+ if [[ -z "$(initialize_progress $TESTPOOL${pool} ${DISK[$pool]})" ]]; then
+ log_fail "Initializing did not start on pool $TESTPOOL${pool}"
+ fi
+done
+
+# Wait for the initialize operation to complete on all pools.
+for pool in {1..4}; do
+ log_must zpool wait -t initialize $TESTPOOL${pool}
+done
+
+# Verify that the initialize operation is complete on all pools.
+complete_count=$(zpool status -i | grep -c "completed")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have initialize status 'completed', but found ${complete_count}."
+fi
+
+# Start an initialize operation on all pools using 'zpool initialize -w -a'.
+log_must zpool initialize -w -a
+
+# Verify that the initialize operation is complete on all pools.
+complete_count=$(zpool status -i | grep -c "completed")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have initialize status 'completed', but found ${complete_count}."
+fi
+
+# Now test the -u, -c and -s options on multiple pools with -a.
+log_must zpool initialize -u -a
+complete_count=$(zpool status -i | grep -c "uninitialized")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have initialize status 'uninitialized', but found ${complete_count}."
+fi
+
+log_must zpool initialize -a
+
+for pool in {1..4}; do
+ if [[ -z "$(initialize_progress $TESTPOOL${pool} ${DISK[$pool]})" ]]; then
+ log_fail "Initializing did not start on pool $TESTPOOL${pool}"
+ fi
+done
+
+log_must zpool initialize -a -s
+complete_count=$(zpool status -i | grep -c "suspended")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have initialize status 'suspended', but found ${complete_count}."
+fi
+
+log_must zpool initialize -a -c
+for pool in {1..4}; do
+ [[ -z "$(initialize_progress $TESTPOOL${pool} ${DISK[$pool]})" ]] || \
+ log_fail "Initialize did not stop on pool $TESTPOOL${pool}"
+done
+
+log_pass "Initialize '-a' works on multiple pools correctly."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
index 431568053472..5ffba803342f 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_001_neg.ksh
@@ -28,6 +28,7 @@
#
# Copyright (c) 2016 by Delphix. All rights reserved.
+# Copyright (c) 2025 Hewlett Packard Enterprise Development LP.
#
. $STF_SUITE/include/libtest.shlib
@@ -46,7 +47,7 @@
verify_runnable "global"
set -A args "" "-?" "blah blah" "-%" "--?" "-*" "-=" \
- "-a" "-b" "-c" "-d" "-e" "-f" "-g" "-h" "-i" "-j" "-k" "-l" \
+ "-b" "-c" "-d" "-e" "-f" "-g" "-h" "-i" "-j" "-k" "-l" \
"-m" "-n" "-o" "-p" "-q" "-r" "-s" "-t" "-u" "-v" "-w" "-x" "-y" "-z" \
"-A" "-B" "-C" "-D" "-E" "-F" "-G" "-H" "-I" "-J" "-K" "-L" \
"-M" "-N" "-O" "-P" "-Q" "-R" "-S" "-T" "-U" "-V" "-W" "-X" "-W" "-Z"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_001.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_001.ksh
new file mode 100755
index 000000000000..7f5f8052c8ec
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_date_range_001.ksh
@@ -0,0 +1,94 @@
+#!/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.
+# Copyright 2025 Mariusz Zaborski <oshogbo@FreeBSD.org>
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify that the date range scrub only scrubs the files that were
+# created/modified within a given time slot.
+#
+# STRATEGY:
+# 1. Write a file.
+# 2. Force a sync of everything via export/import.
+# 3. Wait for one minute.
+# 4. Repeat steps 1, 2, and 3 four two times.
+# 5. Inject checksum errors into all 3 files.
+# 6. Scrub the date range for the first file.
+# 7. Verify that the first file is scrubbed.
+# 8. Verify that newer files are not scrubbed.
+# 9. Repeat steps 6–8 for each of the remaining 2 files.
+#
+
+verify_runnable "global"
+
+function cleanup
+{
+ log_must zinject -c all
+ rm -f $TESTDIR/*_file
+ log_must restore_tunable SPA_NOTE_TXG_TIME
+}
+
+log_onexit cleanup
+
+log_assert "Verifiy scrub, -E, and -S show expected status."
+
+log_must save_tunable SPA_NOTE_TXG_TIME
+log_must set_tunable64 SPA_NOTE_TXG_TIME 30
+
+typeset -a date_list
+for i in `seq 0 2`; do
+ log_must sleep 60
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ date_list+=("$(date '+%Y-%m-%d %H:%M')")
+
+ log_must file_write -o create -f"$TESTDIR/${i}_file" \
+ -b 512 -c 2048 -dR
+
+ log_must sleep 60
+ log_must zpool export $TESTPOOL
+ log_must zpool import $TESTPOOL
+ date_list+=("$(date '+%Y-%m-%d %H:%M')")
+done
+
+for i in `seq 0 2`; do
+ log_must zinject -t data -e checksum -f 100 $TESTDIR/${i}_file
+done
+
+for i in `seq 0 2`; do
+ log_must zpool scrub -w -S "${date_list[$((i * 2))]}" -E "${date_list[$((i * 2 + 1))]}" $TESTPOOL
+ log_must eval "zpool status -v $TESTPOOL | grep '${i}_file'"
+ for j in `seq 0 2`; do
+ if [ $i == $j ]; then
+ continue
+ fi
+ log_mustnot eval "zpool status -v $TESTPOOL | grep '${j}_file'"
+ done
+done
+
+log_pass "Verified scrub, -E, and -S show expected status."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_pools.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_pools.ksh
new file mode 100755
index 000000000000..b8647e208644
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_scrub/zpool_scrub_multiple_pools.ksh
@@ -0,0 +1,128 @@
+#!/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) 2025 Hewlett Packard Enterprise Development LP.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_scrub/zpool_scrub.cfg
+
+#
+# DESCRIPTION:
+# Verify 'zpool scrub -a' works correctly with multiple pools
+#
+# STRATEGY:
+# 1. Create multiple pools.
+# 2. Start a scrub on all pools using 'zpool scrub -a'.
+# 3. Verify that the scrub is running on all pools.
+# 4. Wait for the scrub to complete.
+# 5. Verify that the scrub status is complete on all pools.
+# 6. Start a scrub on all pools using 'zpool scrub -w -a'.
+# 7. Verify that the scrub status is complete on all pools.
+# 8. Now test the -p and -s options on multiple pools with -a.
+# 9. Verify that the scrub status is correct for each option.
+#
+
+verify_runnable "global"
+
+cleanup() {
+ log_must set_tunable32 SCAN_SUSPEND_PROGRESS 0
+ for pool in {1..4}; do
+ zpool destroy $TESTPOOL${pool}
+ rm -rf $TESTDIR${pool}
+ done
+ rm -f $DISK1 $DISK2 $DISK3 $DISK4
+ # Import the testpool
+ zpool import -a
+}
+
+log_onexit cleanup
+
+log_assert "Verify if scrubbing multiple pools works correctly."
+
+# Export the testpool created by setup and Import them later.
+log_must zpool export -a
+
+DEVSIZE='128m'
+FILESIZE='50m'
+TESTDIR="$TEST_BASE_DIR/zpool_scrub_multiple_pools"
+DISK1="$TEST_BASE_DIR/zpool_disk1.dat"
+DISK2="$TEST_BASE_DIR/zpool_disk2.dat"
+DISK3="$TEST_BASE_DIR/zpool_disk3.dat"
+DISK4="$TEST_BASE_DIR/zpool_disk4.dat"
+
+truncate -s $DEVSIZE $DISK1
+truncate -s $DEVSIZE $DISK2
+truncate -s $DEVSIZE $DISK3
+truncate -s $DEVSIZE $DISK4
+
+for pool in {1..4}; do
+ DISK[$pool]="$TEST_BASE_DIR/zpool_disk${pool}.dat"
+ truncate -s $DEVSIZE ${DISK[$pool]}
+ log_must zpool create -O mountpoint=$TESTDIR${pool} $TESTPOOL${pool} ${DISK[$pool]}
+ log_must zfs create -o compression=off $TESTPOOL${pool}/testfs${pool}
+ typeset mntpnt=$(get_prop mountpoint $TESTPOOL${pool}/testfs${pool})
+ # Fill some data into the filesystem.
+ log_must mkfile $FILESIZE $mntpnt/file${pool}.dat
+done
+sync_all_pools
+
+# Start a scrub on all pools using 'zpool scrub -a'.
+log_must zpool scrub -a
+# Wait for the scrub to complete on all pools.
+for pool in {1..4}; do
+ log_must zpool wait -t scrub $TESTPOOL${pool}
+done
+
+# Verify that the scrub status is complete on all pools.
+complete_count=$(zpool status -v | grep -c "scrub repaired")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have scrub status 'scrub repaired', but found $complete_count."
+fi
+
+# Start a error scrub on all pools using 'zpool scrub -w -a'
+log_must zpool scrub -w -a
+
+# Verify that the scrub status is complete on all pools.
+complete_count=$(zpool status -v | grep -c "scrub repaired")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have scrub status 'scrub repaired', but found $complete_count."
+fi
+
+# Now test the -p and -s options on multiple pools with -a.
+log_must set_tunable32 SCAN_SUSPEND_PROGRESS 1
+
+log_must zpool scrub -a
+complete_count=$(zpool status -v | grep -c "scrub in progress since")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have scrub status 'scrub in progress since', but found $complete_count."
+fi
+
+log_must zpool scrub -a -p
+complete_count=$(zpool status -v | grep -c "scrub paused since")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have scrub status 'scrub paused since', but found $complete_count."
+fi
+
+log_must zpool scrub -a -s
+complete_count=$(zpool status -v | grep -c "scrub canceled")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have scrub status 'scrub canceled', but found $complete_count."
+fi
+
+log_pass "Scrubbing multiple pools works correctly."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple_pools.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple_pools.ksh
new file mode 100755
index 000000000000..4348eecc698c
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cli_root/zpool_trim/zpool_trim_multiple_pools.ksh
@@ -0,0 +1,123 @@
+#!/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) 2025 Hewlett Packard Enterprise Development LP.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/cli_root/zpool_trim/zpool_trim.kshlib
+
+#
+# DESCRIPTION:
+# Verify 'zpool trim -a' works correctly with multiple pools
+#
+# STRATEGY:
+# 1. Create multiple pools.
+# 2. Start a trim on all pools using 'zpool trim -a'.
+# 3. Verify that the trim is started on all pools.
+# 4. Wait for the trim to complete.
+# 5. Verify that the trim is complete on all pools.
+# 6. Start a trim on all pools using 'zpool trim -w -a'.
+# 7. Verify that the trim is complete on all pools.
+# 8. Now test the -c and -s options on multiple pools with -a.
+# 9. Verify that the trim status is correct for each option.
+#
+
+verify_runnable "global"
+
+cleanup() {
+ for pool in {1..4}; do
+ zpool destroy $TESTPOOL${pool}
+ rm -rf $TESTDIR${pool}
+ done
+ rm -f $DISK1 $DISK2 $DISK3 $DISK4
+}
+
+log_onexit cleanup
+
+log_assert "Verify if trim '-a' works on multiple pools correctly."
+
+DEVSIZE='5G'
+TESTDIR="$TEST_BASE_DIR/zpool_trim_multiple_pools"
+DISK1="$TEST_BASE_DIR/zpool_disk1.dat"
+DISK2="$TEST_BASE_DIR/zpool_disk2.dat"
+DISK3="$TEST_BASE_DIR/zpool_disk3.dat"
+DISK4="$TEST_BASE_DIR/zpool_disk4.dat"
+
+truncate -s $DEVSIZE $DISK1
+truncate -s $DEVSIZE $DISK2
+truncate -s $DEVSIZE $DISK3
+truncate -s $DEVSIZE $DISK4
+
+for pool in {1..4}; do
+ DISK[$pool]="$TEST_BASE_DIR/zpool_disk${pool}.dat"
+ truncate -s $DEVSIZE ${DISK[$pool]}
+ log_must zpool create $TESTPOOL${pool} ${DISK[$pool]}
+done
+sync_all_pools
+
+# Start a trim on all pools using 'zpool trim -a'.
+log_must zpool trim -a
+
+# Verify that the trim is started on all pools.
+for pool in {1..4}; do
+ [[ -z "$(trim_progress $TESTPOOL${pool} ${DISK[$pool]})" ]] && \
+ log_fail "Trim did not start on pool $TESTPOOL${pool}"
+done
+
+# Wait for the trim to complete on all pools.
+for pool in {1..4}; do
+ log_must zpool wait -t trim $TESTPOOL${pool}
+done
+
+# Verify that the trim status is complete on all pools.
+complete_count=$(zpool status -t | grep -c "completed")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have trim status 'completed', but found ${complete_count}."
+fi
+
+# Start a trim on all pools using 'zpool trim -w -a'
+log_must zpool trim -w -a
+
+# Verify that the trim status is complete on all pools.
+complete_count=$(zpool status -t | grep -c "completed")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have trim status 'completed', but found ${complete_count}."
+fi
+
+# Now test the -s and -c options on multiple pools with -a.
+log_must zpool trim -r 1 -a
+
+for pool in {1..4}; do
+ [[ -z "$(trim_progress $TESTPOOL${pool} ${DISK[$pool]})" ]] && \
+ log_fail "Trim did not start"
+done
+
+log_must zpool trim -a -s
+complete_count=$(zpool status -t | grep -c "suspended")
+if [[ $complete_count -ne 4 ]]; then
+ log_fail "Expected 4 pools to have trim status 'suspended', but found $complete_count."
+fi
+
+log_must zpool trim -a -c
+for pool in {1..4}; do
+ [[ -z "$(trim_progress $TESTPOOL${pool} ${DISK[$pool]})" ]] || \
+ log_fail "TRIM did not stop on pool $TESTPOOL${pool}"
+done
+
+log_pass "Trim '-a' works on multiple pools correctly."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh
index 8f3e6d12e53d..449dedacb307 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_files_002_pos.ksh
@@ -56,7 +56,7 @@ function cleanup
{
datasetexists $TESTPOOL/cp-reflink && \
destroy_dataset $$TESTPOOL/cp-reflink -f
- log_must set_tunable32 BCLONE_WAIT_DIRTY 0
+ log_must restore_tunable BCLONE_WAIT_DIRTY
}
function verify_copy
@@ -81,6 +81,8 @@ SRC_SIZE=$((1024 + $RANDOM % 1024))
# A smaller recordsize is used merely to speed up the test.
RECORDSIZE=4096
+log_must save_tunable BCLONE_WAIT_DIRTY
+
log_must zfs create -o recordsize=$RECORDSIZE $TESTPOOL/cp-reflink
CP_TESTDIR=$(get_prop mountpoint $TESTPOOL/cp-reflink)
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks.kshlib
index 553533377aa4..1fd9b321cd9e 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks.kshlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks.kshlib
@@ -72,6 +72,23 @@ function get_num_dvas
sed 's/.*L[0-9] \(.*\) [a-f0-9]*L.*/\1/' | awk '{print NF}'
}
+function check_gang_bp
+{
+ typeset gang="$(echo -n $1 | grep -c 'gang')"
+ [[ "$gang" == "1" ]] || return 1
+ return 0
+}
+
+function check_is_gang_bp
+{
+ check_gang_bp $1 || log_fail "Not a gang DVA: \"$1\""
+}
+
+function check_not_gang_bp
+{
+ check_gang_bp $1 && log_fail "Gang DVA: \"$1\""
+}
+
function check_gang_dva
{
typeset last_byte="$(echo -n $1 | tail -c 1)"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_neg.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_neg.ksh
new file mode 100755
index 000000000000..e9cb1d2a034a
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_neg.ksh
@@ -0,0 +1,53 @@
+#!/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.
+#
+# 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.
+#
+
+#
+# Copyright (c) 2025 by Klara Inc.
+#
+
+#
+# Description:
+# Verify that we don't use larger gang headers on ashift=9 pools
+#
+# Strategy:
+# 1. Create a pool with dynamic gang headers.
+# 2. Set metaslab_force_ganging to force multi-level ganging.
+# 3. Verify that a large file has multi-level ganging
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/gang_blocks/gang_blocks.kshlib
+
+log_assert "Verify that we don't use large gang headers on small-ashift pools".
+
+log_onexit cleanup
+preamble
+
+log_must zpool create -f -o ashift=9 -o feature@dynamic_gang_header=enabled $TESTPOOL $DISKS
+log_must zfs create -o recordsize=1M $TESTPOOL/$TESTFS
+mountpoint=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+set_tunable64 METASLAB_FORCE_GANGING 200000
+set_tunable32 METASLAB_FORCE_GANGING_PCT 100
+
+path="${mountpoint}/file"
+log_must dd if=/dev/urandom of=$path bs=1M count=1
+log_must zpool sync $TESTPOOL
+first_block=$(get_first_block_dva $TESTPOOL/$TESTFS file)
+leaves=$(read_gang_header $TESTPOOL $first_block 200)
+gangs=$(echo "$leaves" | grep -c gang)
+[[ "$gangs" -gt 0 ]] || log_fail "We didn't use a deep gang tree when needed"
+
+log_must verify_pool $TESTPOOL
+status=$(get_pool_prop feature@dynamic_gang_header $TESTPOOL)
+[[ "$status" == "enabled" ]] || log_fail "Dynamic gang headers active on an ashift-9 pool"
+log_pass "We don't use large gang headers on small-ashift pools".
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_pos.ksh
new file mode 100755
index 000000000000..2941325fdc33
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_header_pos.ksh
@@ -0,0 +1,81 @@
+#!/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.
+#
+# 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.
+#
+
+#
+# Copyright (c) 2025 by Klara Inc.
+#
+
+#
+# Description:
+# Verify that we use larger gang headers on ashift=12 pools
+#
+# Strategy:
+# 1. Create a pool with dynamic gang headers.
+# 2. Set metaslab_force_ganging to force ganging.
+# 3. Verify that a large file has more than 3 gang headers.
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/gang_blocks/gang_blocks.kshlib
+
+log_assert "Verify that we don't use large gang headers on small-ashift pools".
+
+log_onexit cleanup
+preamble
+
+for vdevtype in "" "mirror" "raidz" "raidz2" "draid"; do
+ log_must zpool create -f -o ashift=12 $TESTPOOL $vdevtype $DISKS
+ log_must zfs create -o recordsize=1M $TESTPOOL/$TESTFS
+ mountpoint=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+ set_tunable64 METASLAB_FORCE_GANGING 200000
+ set_tunable32 METASLAB_FORCE_GANGING_PCT 100
+
+ status=$(get_pool_prop feature@dynamic_gang_header $TESTPOOL)
+ [[ "$status" == "enabled" ]] || \
+ log_fail "Dynamic gang headers not enabled"
+ path="${mountpoint}/file"
+ log_must dd if=/dev/urandom of=$path bs=1M count=1
+ log_must zpool sync $TESTPOOL
+ first_block=$(get_first_block_dva $TESTPOOL/$TESTFS file)
+ leaves=$(read_gang_header $TESTPOOL $first_block 1000 | \
+ grep -v HOLE | grep -v "^Found")
+ first_child=$(echo "$leaves" | head -n 1)
+ check_gang_bp $first_child
+
+ num_leaves=$(echo "$leaves" | wc -l)
+ [[ "$num_leaves" -gt 3 ]] && \
+ log_fail "used a larger gang header too soon: \"$leaves\""
+ log_must verify_pool $TESTPOOL
+ status=$(get_pool_prop feature@dynamic_gang_header $TESTPOOL)
+ [[ "$status" == "active" ]] || log_fail "Dynamic gang headers not active"
+
+ path="${mountpoint}/file2"
+ log_must dd if=/dev/urandom of=$path bs=1M count=1
+ log_must zpool sync $TESTPOOL
+ first_block=$(get_first_block_dva $TESTPOOL/$TESTFS file2)
+ leaves=$(read_gang_header $TESTPOOL $first_block 1000 | \
+ grep -v HOLE | grep -v "^Found")
+ first_child=$(echo "$leaves" | head -n 1)
+ check_not_gang_bp $first_child
+
+ num_leaves=$(echo "$leaves" | wc -l)
+ [[ "$num_leaves" -gt 3 ]] || \
+ log_fail "didn't use a larger gang header: \"$leaves\""
+
+
+ log_must verify_pool $TESTPOOL
+ status=$(get_pool_prop feature@dynamic_gang_header $TESTPOOL)
+ [[ "$status" == "active" ]] || log_fail "Dynamic gang headers not active"
+ log_must zpool destroy $TESTPOOL
+done
+log_pass "We don't use large gang headers on small-ashift pools".
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_multi.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_multi.ksh
new file mode 100755
index 000000000000..2ffe24968f10
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/gang_blocks/gang_blocks_dyn_multi.ksh
@@ -0,0 +1,54 @@
+#!/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.
+#
+# 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.
+#
+
+#
+# Copyright (c) 2025 by Klara Inc.
+#
+
+#
+# Description:
+# Verify that multi-level ganging still works with dynamic headers
+#
+# Strategy:
+# 1. Create a pool with dynamic gang headers and ashift=12.
+# 2. Set metaslab_force_ganging to force multi-level ganging.
+# 3. Verify that a large file has multi-level ganging
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/gang_blocks/gang_blocks.kshlib
+
+log_assert "Verify that we can still multi-level gang with large headers."
+
+log_onexit cleanup
+preamble
+
+log_must zpool create -f -o ashift=12 -o feature@dynamic_gang_header=enabled $TESTPOOL $DISKS
+log_must zfs create -o recordsize=16M $TESTPOOL/$TESTFS
+mountpoint=$(get_prop mountpoint $TESTPOOL/$TESTFS)
+set_tunable64 METASLAB_FORCE_GANGING 50000
+set_tunable32 METASLAB_FORCE_GANGING_PCT 100
+
+path="${mountpoint}/file"
+log_must dd if=/dev/urandom of=$path bs=16M count=1
+log_must zpool sync $TESTPOOL
+first_block=$(get_first_block_dva $TESTPOOL/$TESTFS file)
+leaves=$(read_gang_header $TESTPOOL $first_block 200)
+gangs=$(echo "$leaves" | grep -c gang)
+[[ "$gangs" -gt 0 ]] || log_fail "We didn't use a deep gang tree when needed"
+
+log_must verify_pool $TESTPOOL
+status=$(get_pool_prop feature@dynamic_gang_header $TESTPOOL)
+[[ "$status" == "active" ]] || log_fail "Dynamic gang headers not active"
+
+log_pass "We can still multi-level gang with large headers."
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmap/mmap_ftruncate.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmap/mmap_ftruncate.ksh
new file mode 100755
index 000000000000..63ebf95de7f0
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/mmap/mmap_ftruncate.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.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# This verifies that async writeback of dirty mmap()'d pages completes quickly.
+# ftruncate() is an operation that will trigger async writeback, but is not
+# itself a syncing operation, making it a useful proxy for any way the kernel
+# might trigger async writeback.
+#
+# The guts of this test is in the mmap_ftruncate program. This driver sets a
+# larger zfs_txg_timeout. Test failure occurs ftruncate() blocks waiting for
+# the writeback until the txg timeout is reached and the changes are forcibly
+# written out. Success means the DMU has accepted the changes and cleared the
+# page dirty flags.
+#
+
+TIMEOUT=180
+TESTFILE=/$TESTPOOL/truncfile
+TESTSIZE=$((2*1024*1024*1024)) # 2G
+
+verify_runnable "global"
+
+typeset claim="async writeback of dirty mmap()'d pages completes quickly"
+
+log_assert $claim
+
+log_must save_tunable TXG_TIMEOUT
+
+function cleanup
+{
+ log_must restore_tunable TXG_TIMEOUT
+ rm -f $TESTFILE
+}
+log_onexit cleanup
+
+log_must set_tunable32 TXG_TIMEOUT $TIMEOUT
+log_must zpool sync -f
+
+# run mmap_ftruncate and record the run time
+typeset -i start=$(date +%s)
+log_must mmap_ftruncate $TESTFILE $TESTSIZE
+typeset -i end=$(date +%s)
+typeset -i delta=$((end - start))
+
+# in practice, mmap_ftruncate needs a few seconds to dirty all the pages, and
+# when this test passes, the ftruncate() call itself should be near-instant.
+# when it fails, then its only the txg sync that allows ftruncate() to
+# complete, in that case, the run time will be extremely close to the timeout,
+# so to avoid any confusion at the edges, we require that it complets within
+# half the transaction time. for any timeout higher than ~30s that should be a
+# very bright line down the middle.
+log_must test $delta -lt $((TIMEOUT / 2))
+
+log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh
index cd4573b2e4d1..b364a5cb4bdc 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/pool_checkpoint/checkpoint_zdb.ksh
@@ -63,6 +63,7 @@ log_must eval "zdb $TESTPOOL | grep -q \"Checkpointed uberblock found\""
log_mustnot eval "zdb -k $TESTPOOL | grep -q \"Checkpointed uberblock found\""
log_mustnot eval "zdb $TESTPOOL | grep \"Dataset $FS1\""
log_must eval "zdb -k $TESTPOOL | grep \"Dataset $CHECKPOINTED_FS1\""
+log_must eval "zdb -k $TESTPOOL/ | grep \"$TESTPOOL$BOGUS_SUFFIX\""
log_must zpool export $TESTPOOL
@@ -70,6 +71,7 @@ log_must eval "zdb -e $TESTPOOL | grep \"Checkpointed uberblock found\""
log_mustnot eval "zdb -k -e $TESTPOOL | grep \"Checkpointed uberblock found\""
log_mustnot eval "zdb -e $TESTPOOL | grep \"Dataset $FS1\""
log_must eval "zdb -k -e $TESTPOOL | grep \"Dataset $CHECKPOINTED_FS1\""
+log_must eval "zdb -k -e $TESTPOOL/ | grep \"$TESTPOOL$BOGUS_SUFFIX\""
log_must zpool import $TESTPOOL