aboutsummaryrefslogtreecommitdiff
path: root/sys/contrib/openzfs/tests
diff options
context:
space:
mode:
Diffstat (limited to 'sys/contrib/openzfs/tests')
-rw-r--r--sys/contrib/openzfs/tests/runfiles/common.run6
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am2
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/btree_test.c4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_write_sync.c84
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg1
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am9
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode.kshlib149
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_continue.ksh36
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_wait.ksh36
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_continue.ksh36
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_wait.ksh36
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_continue.ksh36
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_wait.ksh37
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_continue.ksh37
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_wait.ksh37
16 files changed, 543 insertions, 4 deletions
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run
index 9fad8946f4f3..131845f5ed40 100644
--- a/sys/contrib/openzfs/tests/runfiles/common.run
+++ b/sys/contrib/openzfs/tests/runfiles/common.run
@@ -725,7 +725,11 @@ tests = ['fadvise_willneed']
tags = ['functional', 'fadvise']
[tests/functional/failmode]
-tests = ['failmode_dmu_tx_wait', 'failmode_dmu_tx_continue']
+tests = ['failmode_dmu_tx_wait', 'failmode_dmu_tx_continue',
+ 'failmode_fsync_wait', 'failmode_fsync_continue',
+ 'failmode_msync_wait', 'failmode_msync_continue',
+ 'failmode_osync_wait', 'failmode_osync_continue',
+ 'failmode_syncalways_wait', 'failmode_syncalways_continue']
tags = ['functional', 'failmode']
[tests/functional/fallocate]
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
index 1cd90024e94d..62f1684acfb4 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/.gitignore
@@ -28,6 +28,7 @@
/mmap_seek
/mmap_sync
/mmapwrite
+/mmap_write_sync
/nvlist_to_lua
/randfree_file
/randwritecomp
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
index d5448055a1e1..85c3cf3c35a8 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/Makefile.am
@@ -74,7 +74,7 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/mkbusy %D%/mkfile %D%/mkfiles %D%/mktree
scripts_zfs_tests_bin_PROGRAMS += \
%D%/mmap_exec %D%/mmap_ftruncate %D%/mmap_seek \
- %D%/mmap_sync %D%/mmapwrite %D%/readmmap
+ %D%/mmap_sync %D%/mmapwrite %D%/readmmap %D%/mmap_write_sync
%C%_mmapwrite_LDADD = -lpthread
if WANT_MMAP_LIBAIO
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/btree_test.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/btree_test.c
index e7b80d01efaa..f8948a61833d 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/cmd/btree_test.c
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/btree_test.c
@@ -207,7 +207,7 @@ insert_find_remove(zfs_btree_t *bt, char *why)
"Found removed value (%llu)\n", *p);
return (1);
}
- ASSERT3S(zfs_btree_numnodes(bt), ==, 0);
+ ASSERT0(zfs_btree_numnodes(bt));
zfs_btree_verify(bt);
return (0);
@@ -279,7 +279,7 @@ drain_tree(zfs_btree_t *bt, char *why)
node = avl_last(&avl);
ASSERT3U(node->data, ==, *(uint64_t *)zfs_btree_last(bt, NULL));
}
- ASSERT3S(zfs_btree_numnodes(bt), ==, 0);
+ ASSERT0(zfs_btree_numnodes(bt));
void *avl_cookie = NULL;
while ((node = avl_destroy_nodes(&avl, &avl_cookie)) != NULL)
diff --git a/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_write_sync.c b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_write_sync.c
new file mode 100644
index 000000000000..ad5e37f24960
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/cmd/mmap_write_sync.c
@@ -0,0 +1,84 @@
+// 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.
+ */
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+
+#define PAGES (8)
+
+int
+main(int argc, char **argv)
+{
+ if (argc != 2) {
+ fprintf(stderr, "usage: %s <filename>\n", argv[0]);
+ exit(1);
+ }
+
+ long page_size = sysconf(_SC_PAGESIZE);
+ if (page_size < 0) {
+ perror("sysconf");
+ exit(2);
+ }
+ size_t map_size = page_size * PAGES;
+
+ int fd = open(argv[1], O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
+ if (fd < 0) {
+ perror("open");
+ exit(2);
+ }
+
+ if (ftruncate(fd, map_size) < 0) {
+ perror("ftruncate");
+ close(fd);
+ exit(2);
+ }
+
+ uint64_t *p =
+ mmap(NULL, map_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (p == MAP_FAILED) {
+ perror("mmap");
+ close(fd);
+ exit(2);
+ }
+
+ for (int i = 0; i < (map_size / sizeof (uint64_t)); i++)
+ p[i] = 0x0123456789abcdef;
+
+ if (msync(p, map_size, MS_SYNC) < 0) {
+ perror("msync");
+ munmap(p, map_size);
+ close(fd);
+ exit(3);
+ }
+
+ munmap(p, map_size);
+ close(fd);
+ exit(0);
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
index bbaa8665ecc8..884a99d785bc 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
+++ b/sys/contrib/openzfs/tests/zfs-tests/include/commands.cfg
@@ -210,6 +210,7 @@ export ZFSTEST_FILES='badsend
mmap_seek
mmap_sync
mmapwrite
+ mmap_write_sync
nvlist_to_lua
randfree_file
randwritecomp
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
index c2542287c1d7..b8b8bbe45a42 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
@@ -276,6 +276,7 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \
functional/direct/dio.kshlib \
functional/events/events.cfg \
functional/events/events_common.kshlib \
+ functional/failmode/failmode.kshlib \
functional/fault/fault.cfg \
functional/gang_blocks/gang_blocks.kshlib \
functional/grow/grow.cfg \
@@ -1541,6 +1542,14 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/failmode/cleanup.ksh \
functional/failmode/failmode_dmu_tx_wait.ksh \
functional/failmode/failmode_dmu_tx_continue.ksh \
+ functional/failmode/failmode_fsync_wait.ksh \
+ functional/failmode/failmode_fsync_continue.ksh \
+ functional/failmode/failmode_msync_wait.ksh \
+ functional/failmode/failmode_msync_continue.ksh \
+ functional/failmode/failmode_osync_wait.ksh \
+ functional/failmode/failmode_osync_continue.ksh \
+ functional/failmode/failmode_syncalways_wait.ksh \
+ functional/failmode/failmode_syncalways_continue.ksh \
functional/failmode/setup.ksh \
functional/fallocate/cleanup.ksh \
functional/fallocate/fallocate_prealloc.ksh \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode.kshlib
new file mode 100644
index 000000000000..d0b7404557ab
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode.kshlib
@@ -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, Klara, Inc.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+typeset -A failmode_sync_helper_cmd=(
+ ["fsync"]='dd if=/dev/urandom of=DATAFILE bs=128k count=1 conv=fsync'
+ ["msync"]='mmap_write_sync DATAFILE'
+ ["osync"]='dd if=/dev/urandom of=DATAFILE bs=128k count=1 oflag=sync'
+ ["syncalways"]='dd if=/dev/urandom of=DATAFILE bs=128k count=1'
+)
+
+typeset -A failmode_sync_helper_dsopts=(
+ ["syncalways"]="-o sync=always"
+)
+
+function failmode_sync_cleanup
+{
+ zinject -c all || true
+ zpool clear $TESTPOOL || true
+ destroy_pool $TESTPOOL
+}
+
+#
+# failmode_sync_test <failmode> <helper>
+#
+# run a failmode sync test:
+# - failmode: wait|continue
+# - helper: fsync|msync|osync|syncalways
+#
+function failmode_sync_test
+{
+ typeset failmode=$1
+ typeset helper=$2
+
+ # we'll need two disks, one for the main pool, one for the log
+ read -r DISK1 DISK2 _ <<<"$DISKS"
+
+ # file to write to the pool
+ typeset datafile="/$TESTPOOL/$TESTFS/datafile"
+
+ # create a single-disk pool with a separate log and the wanted failmode
+ log_must zpool create \
+ -f -o failmode=$failmode $TESTPOOL $DISK1 log $DISK2
+
+ # create the test dataset. we bias the ZIL towards the log device to
+ # try to ensure that the sync write never involves the main device
+ log_must zfs create \
+ -o recordsize=128k -o logbias=latency \
+ ${failmode_sync_helper_dsopts[$helper]} \
+ $TESTPOOL/$TESTFS
+
+ # create the target file. the ZIL head structure is created on first
+ # use, and does a full txg wait to finish, which we want to avoid
+ log_must dd if=/dev/zero of=$datafile bs=128k count=1 conv=fsync
+ log_must zpool sync
+
+ # inject errors. writes will fail, as will the followup probes
+ zinject -d $DISK1 -e io -T write $TESTPOOL
+ zinject -d $DISK1 -e nxio -T probe $TESTPOOL
+ zinject -d $DISK2 -e io -T write $TESTPOOL
+ zinject -d $DISK2 -e nxio -T probe $TESTPOOL
+
+ # run the helper program in the background. the pool should immediately
+ # suspend, and the sync op block or fail based on the failmode
+ typeset helper_cmd=${failmode_sync_helper_cmd[$helper]/DATAFILE/$datafile}
+ log_note "running failmode sync helper: $helper_cmd"
+ $helper_cmd &
+ typeset -i pid=$!
+
+ # should only take a moment, but give it a chance
+ log_note "waiting for pool to suspend"
+ typeset -i tries=10
+ until [[ $(kstat_pool $TESTPOOL state) == "SUSPENDED" ]] ; do
+ if ((tries-- == 0)); then
+ log_fail "pool didn't suspend"
+ fi
+ sleep 1
+ done
+
+ # zil_commit() should have noticed the suspend by now
+ typeset -i zilerr=$(kstat zil.zil_commit_error_count)
+
+ # see if the helper program blocked
+ typeset -i blocked
+ if kill -0 $pid ; then
+ blocked=1
+ log_note "$helper: blocked in the kernel"
+ else
+ blocked=0
+ log_note "$helper: exited while pool suspended"
+ fi
+
+ # bring the pool back online
+ zinject -c all
+ zpool clear $TESTPOOL
+
+ # program definitely exited now, get its return code
+ wait $pid
+ typeset -i rc=$?
+
+ failmode_sync_cleanup
+
+ log_note "$helper: zilerr=$zilerr blocked=$blocked rc=$rc"
+
+ # confirm expected results for the failmode
+ if [[ $failmode = "wait" ]] ; then
+ # - the ZIL saw an error, and fell back to a txg sync
+ # - sync op blocked when the pool suspended
+ # - after resume, sync op succeeded, helper returned success
+ log_must test $zilerr -ne 0
+ log_must test $blocked -eq 1
+ log_must test $rc -eq 0
+ elif [[ $failmode = "continue" ]] ; then
+ # confirm expected results:
+ # - the ZIL saw an error, and fell back to a txg sync
+ # - helper exited when the pool suspended
+ # - sync op returned an error, so helper returned failure
+ log_must test $zilerr -ne 0
+ log_must test $blocked -eq 0
+ log_must test $rc -ne 0
+ else
+ log_fail "impossible failmode: $failmode"
+ fi
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_continue.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_continue.ksh
new file mode 100755
index 000000000000..7b145d3a2b4c
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_continue.ksh
@@ -0,0 +1,36 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="fsync() returns when pool suspends with failmode=continue"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test continue fsync
+log_pass $desc
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_wait.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_wait.ksh
new file mode 100755
index 000000000000..677d226b5481
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_fsync_wait.ksh
@@ -0,0 +1,36 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="fsync() blocks when pool suspends with failmode=wait"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test wait fsync
+log_pass $desc
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_continue.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_continue.ksh
new file mode 100755
index 000000000000..0c79ee15a1ba
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_continue.ksh
@@ -0,0 +1,36 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="msync() returns when pool suspends with failmode=continue"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test continue msync
+log_pass $desc
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_wait.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_wait.ksh
new file mode 100755
index 000000000000..a59d8cc50d61
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_msync_wait.ksh
@@ -0,0 +1,36 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="msync() blocks when pool suspends with failmode=wait"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test wait msync
+log_pass $desc
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_continue.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_continue.ksh
new file mode 100755
index 000000000000..c4fa0c8f042c
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_continue.ksh
@@ -0,0 +1,36 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="O_SYNC returns when pool suspends with failmode=continue"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test continue osync
+log_pass $desc
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_wait.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_wait.ksh
new file mode 100755
index 000000000000..5f65cf92ad33
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_osync_wait.ksh
@@ -0,0 +1,37 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="O_SYNC blocks when pool suspends with failmode=wait"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test wait osync
+log_pass $desc
+
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_continue.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_continue.ksh
new file mode 100755
index 000000000000..b80d776224a0
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_continue.ksh
@@ -0,0 +1,37 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="write()+sync=always returns when pool suspends with failmode=continue"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test continue syncalways
+log_pass $desc
+
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_wait.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_wait.ksh
new file mode 100755
index 000000000000..4fcb167b5c77
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/failmode/failmode_syncalways_wait.ksh
@@ -0,0 +1,37 @@
+#!/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/failmode/failmode.kshlib
+
+typeset desc="write()+sync=always blocks when pool suspends with failmode=wait"
+
+log_assert $desc
+log_onexit failmode_sync_cleanup
+log_must failmode_sync_test wait syncalways
+log_pass $desc
+