aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMartin Matuska <mm@FreeBSD.org>2023-12-15 13:17:23 +0000
committerMartin Matuska <mm@FreeBSD.org>2023-12-15 13:18:07 +0000
commit5fb307d29b364982acbde82cbf77db3cae486f8c (patch)
treec88ea4fda58b14ab37ae6140ccb7135bf152ac55 /sys
parentc2e340452c147b551180f2a1600ae76491342b0e (diff)
parent86e115e21e5bdeee73c88c5a1a73a29d9637380a (diff)
zfs: merge openzfs/zfs@86e115e21
Notable upstream pull request merges: #15643 a9b937e06 For db_marker inherit the db pointer for AVL comparision #15644 e53e60c0b DMU: Fix lock leak on dbuf_hold() error #15653 86063d903 dbuf: Handle arcbuf assignment after block cloning #15656 86e115e21 dbuf: Set dr_data when unoverriding after clone Obtained from: OpenZFS OpenZFS commit: 86e115e21e5bdeee73c88c5a1a73a29d9637380a
Diffstat (limited to 'sys')
-rwxr-xr-xsys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh6
-rw-r--r--sys/contrib/openzfs/cmd/zed/zed.d/zed.rc2
-rw-r--r--sys/contrib/openzfs/include/sys/dbuf.h1
-rw-r--r--sys/contrib/openzfs/module/zfs/dbuf.c20
-rw-r--r--sys/contrib/openzfs/module/zfs/dmu.c2
-rw-r--r--sys/contrib/openzfs/module/zfs/dnode.c8
-rw-r--r--sys/contrib/openzfs/module/zfs/dnode_sync.c9
-rw-r--r--sys/contrib/openzfs/tests/runfiles/common.run2
-rw-r--r--sys/contrib/openzfs/tests/runfiles/linux.run3
-rwxr-xr-xsys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in5
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/Makefile.am3
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am4
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib2
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh131
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh133
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore1
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh73
-rw-r--r--sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c180
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh7
-rwxr-xr-xsys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh2
-rw-r--r--sys/modules/zfs/zfs_config.h4
-rw-r--r--sys/modules/zfs/zfs_gitrev.h2
22 files changed, 582 insertions, 18 deletions
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh
index 150012abe71a..06acce93b8aa 100755
--- a/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/statechange-slot_off.sh
@@ -5,7 +5,7 @@
#
# Bad SCSI disks can often "disappear and reappear" causing all sorts of chaos
# as they flip between FAULTED and ONLINE. If
-# ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
+# ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT is set in zed.rc, and the disk gets
# FAULTED, then power down the slot via sysfs:
#
# /sys/class/enclosure/<enclosure>/<slot>/power_status
@@ -19,7 +19,7 @@
# Exit codes:
# 0: slot successfully powered off
# 1: enclosure not available
-# 2: ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT disabled
+# 2: ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT disabled
# 3: vdev was not FAULTED
# 4: The enclosure sysfs path passed from ZFS does not exist
# 5: Enclosure slot didn't actually turn off after we told it to
@@ -32,7 +32,7 @@ if [ ! -d /sys/class/enclosure ] ; then
exit 1
fi
-if [ "${ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT}" != "1" ] ; then
+if [ "${ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT}" != "1" ] ; then
exit 2
fi
diff --git a/sys/contrib/openzfs/cmd/zed/zed.d/zed.rc b/sys/contrib/openzfs/cmd/zed/zed.d/zed.rc
index acdfabc8ded2..bc269b155d76 100644
--- a/sys/contrib/openzfs/cmd/zed/zed.d/zed.rc
+++ b/sys/contrib/openzfs/cmd/zed/zed.d/zed.rc
@@ -146,7 +146,7 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event"
# Power off the drive's slot in the enclosure if it becomes FAULTED. This can
# help silence misbehaving drives. This assumes your drive enclosure fully
# supports slot power control via sysfs.
-#ZED_POWER_OFF_ENCLOUSRE_SLOT_ON_FAULT=1
+#ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT=1
##
# Ntfy topic
diff --git a/sys/contrib/openzfs/include/sys/dbuf.h b/sys/contrib/openzfs/include/sys/dbuf.h
index 1800a7e31da0..2ff0bc72b270 100644
--- a/sys/contrib/openzfs/include/sys/dbuf.h
+++ b/sys/contrib/openzfs/include/sys/dbuf.h
@@ -79,6 +79,7 @@ extern "C" {
* dbuf_states_t (see comment on dn_dbufs in dnode.h).
*/
typedef enum dbuf_states {
+ DB_MARKER = -2,
DB_SEARCH = -1,
DB_UNCACHED,
DB_FILL,
diff --git a/sys/contrib/openzfs/module/zfs/dbuf.c b/sys/contrib/openzfs/module/zfs/dbuf.c
index c5ccd4cd1e0c..03c97941d6d3 100644
--- a/sys/contrib/openzfs/module/zfs/dbuf.c
+++ b/sys/contrib/openzfs/module/zfs/dbuf.c
@@ -1919,7 +1919,6 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
dmu_buf_impl_t *db = dr->dr_dbuf;
blkptr_t *bp = &dr->dt.dl.dr_overridden_by;
uint64_t txg = dr->dr_txg;
- boolean_t release;
ASSERT(MUTEX_HELD(&db->db_mtx));
/*
@@ -1940,7 +1939,10 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
if (!BP_IS_HOLE(bp) && !dr->dt.dl.dr_nopwrite)
zio_free(db->db_objset->os_spa, txg, bp);
- release = !dr->dt.dl.dr_brtwrite;
+ if (dr->dt.dl.dr_brtwrite) {
+ ASSERT0P(dr->dt.dl.dr_data);
+ dr->dt.dl.dr_data = db->db_buf;
+ }
dr->dt.dl.dr_override_state = DR_NOT_OVERRIDDEN;
dr->dt.dl.dr_nopwrite = B_FALSE;
dr->dt.dl.dr_brtwrite = B_FALSE;
@@ -1954,7 +1956,7 @@ dbuf_unoverride(dbuf_dirty_record_t *dr)
* the buf thawed to save the effort of freezing &
* immediately re-thawing it.
*/
- if (release)
+ if (dr->dt.dl.dr_data)
arc_release(dr->dt.dl.dr_data, db);
}
@@ -2945,7 +2947,8 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
while (db->db_state == DB_READ || db->db_state == DB_FILL)
cv_wait(&db->db_changed, &db->db_mtx);
- ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED);
+ ASSERT(db->db_state == DB_CACHED || db->db_state == DB_UNCACHED ||
+ db->db_state == DB_NOFILL);
if (db->db_state == DB_CACHED &&
zfs_refcount_count(&db->db_holds) - 1 > db->db_dirtycnt) {
@@ -2982,6 +2985,15 @@ dbuf_assign_arcbuf(dmu_buf_impl_t *db, arc_buf_t *buf, dmu_tx_t *tx)
arc_buf_destroy(db->db_buf, db);
}
db->db_buf = NULL;
+ } else if (db->db_state == DB_NOFILL) {
+ /*
+ * We will be completely replacing the cloned block. In case
+ * it was cloned in this transaction group, let's undirty the
+ * pending clone and mark the block as uncached. This will be
+ * as if the clone was never done.
+ */
+ VERIFY(!dbuf_undirty(db, tx));
+ db->db_state = DB_UNCACHED;
}
ASSERT(db->db_buf == NULL);
dbuf_set_data(db, buf);
diff --git a/sys/contrib/openzfs/module/zfs/dmu.c b/sys/contrib/openzfs/module/zfs/dmu.c
index 6cf7f3c3b12e..f5a5d0fc437f 100644
--- a/sys/contrib/openzfs/module/zfs/dmu.c
+++ b/sys/contrib/openzfs/module/zfs/dmu.c
@@ -1501,9 +1501,9 @@ dmu_assign_arcbuf_by_dnode(dnode_t *dn, uint64_t offset, arc_buf_t *buf,
rw_enter(&dn->dn_struct_rwlock, RW_READER);
blkid = dbuf_whichblock(dn, 0, offset);
db = dbuf_hold(dn, blkid, FTAG);
+ rw_exit(&dn->dn_struct_rwlock);
if (db == NULL)
return (SET_ERROR(EIO));
- rw_exit(&dn->dn_struct_rwlock);
/*
* We can only assign if the offset is aligned and the arc buf is the
diff --git a/sys/contrib/openzfs/module/zfs/dnode.c b/sys/contrib/openzfs/module/zfs/dnode.c
index 7ae74ad1318d..ba28aa06a91f 100644
--- a/sys/contrib/openzfs/module/zfs/dnode.c
+++ b/sys/contrib/openzfs/module/zfs/dnode.c
@@ -99,6 +99,14 @@ dbuf_compare(const void *x1, const void *x2)
if (likely(cmp))
return (cmp);
+ if (d1->db_state == DB_MARKER) {
+ ASSERT3S(d2->db_state, !=, DB_MARKER);
+ return (TREE_PCMP(d1->db_parent, d2));
+ } else if (d2->db_state == DB_MARKER) {
+ ASSERT3S(d1->db_state, !=, DB_MARKER);
+ return (TREE_PCMP(d1, d2->db_parent));
+ }
+
if (d1->db_state == DB_SEARCH) {
ASSERT3S(d2->db_state, !=, DB_SEARCH);
return (-1);
diff --git a/sys/contrib/openzfs/module/zfs/dnode_sync.c b/sys/contrib/openzfs/module/zfs/dnode_sync.c
index 8cffbdb9d20b..f67dad002319 100644
--- a/sys/contrib/openzfs/module/zfs/dnode_sync.c
+++ b/sys/contrib/openzfs/module/zfs/dnode_sync.c
@@ -482,7 +482,14 @@ dnode_evict_dbufs(dnode_t *dn)
zfs_refcount_is_zero(&db->db_holds)) {
db_marker->db_level = db->db_level;
db_marker->db_blkid = db->db_blkid;
- db_marker->db_state = DB_SEARCH;
+ /*
+ * Insert a MARKER node with the same level and blkid.
+ * And to resolve any ties in dbuf_compare() use the
+ * pointer of the dbuf that we are evicting. Pass the
+ * address in db_parent.
+ */
+ db_marker->db_state = DB_MARKER;
+ db_marker->db_parent = (void *)((uintptr_t)db - 1);
avl_insert_here(&dn->dn_dbufs, db_marker, db,
AVL_BEFORE);
diff --git a/sys/contrib/openzfs/tests/runfiles/common.run b/sys/contrib/openzfs/tests/runfiles/common.run
index dd44b63aaf3d..8c1f0ad0b14e 100644
--- a/sys/contrib/openzfs/tests/runfiles/common.run
+++ b/sys/contrib/openzfs/tests/runfiles/common.run
@@ -598,7 +598,7 @@ tests = ['compress_001_pos', 'compress_002_pos', 'compress_003_pos',
tags = ['functional', 'compression']
[tests/functional/cp_files]
-tests = ['cp_files_001_pos']
+tests = ['cp_files_001_pos', 'cp_stress']
tags = ['functional', 'cp_files']
[tests/functional/crtime]
diff --git a/sys/contrib/openzfs/tests/runfiles/linux.run b/sys/contrib/openzfs/tests/runfiles/linux.run
index fb78d96fb52d..17ba23352422 100644
--- a/sys/contrib/openzfs/tests/runfiles/linux.run
+++ b/sys/contrib/openzfs/tests/runfiles/linux.run
@@ -43,7 +43,8 @@ tests = ['block_cloning_copyfilerange', 'block_cloning_copyfilerange_partial',
'block_cloning_disabled_ficlonerange',
'block_cloning_copyfilerange_cross_dataset',
'block_cloning_cross_enc_dataset',
- 'block_cloning_copyfilerange_fallback_same_txg']
+ 'block_cloning_copyfilerange_fallback_same_txg',
+ 'block_cloning_replay', 'block_cloning_replay_encrypted']
tags = ['functional', 'block_cloning']
[tests/functional/chattr:Linux]
diff --git a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
index b188a101c257..3b5eeacb6bad 100755
--- a/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
+++ b/sys/contrib/openzfs/tests/test-runner/bin/zts-report.py.in
@@ -301,6 +301,10 @@ elif sys.platform.startswith('linux'):
['SKIP', cfr_reason],
'block_cloning/block_cloning_copyfilerange_fallback':
['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_replay':
+ ['SKIP', cfr_reason],
+ 'block_cloning/block_cloning_replay_encrypted':
+ ['SKIP', cfr_reason],
'block_cloning/block_cloning_copyfilerange_cross_dataset':
['SKIP', cfr_cross_reason],
'block_cloning/block_cloning_copyfilerange_fallback_same_txg':
@@ -309,7 +313,6 @@ elif sys.platform.startswith('linux'):
['SKIP', cfr_cross_reason],
})
-
# Not all Github actions runners have scsi_debug module, so we may skip
# some tests which use it.
if os.environ.get('CI') == 'true':
diff --git a/sys/contrib/openzfs/tests/zfs-tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
index f8166352489e..3dd1a6452728 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/Makefile.am
@@ -13,6 +13,9 @@ scripts_zfs_tests_functional_hkdf_PROGRAMS = %D%/tests/functional/hkdf/hkdf_test
%C%_tests_functional_hkdf_hkdf_test_LDADD = \
libzpool.la
+scripts_zfs_tests_functional_cp_filesdir = $(datadir)/$(PACKAGE)/zfs-tests/tests/functional/cp_files
+scripts_zfs_tests_functional_cp_files_PROGRAMS = %D%/tests/functional/cp_files/seekflood
+
if BUILD_LINUX
scripts_zfs_tests_functional_tmpfiledir = $(datadir)/$(PACKAGE)/zfs-tests/tests/functional/tmpfile
scripts_zfs_tests_functional_tmpfile_PROGRAMS = \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
index 2d899e58bdbb..3c9f09382424 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/Makefile.am
@@ -452,6 +452,8 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/block_cloning/block_cloning_ficlonerange.ksh \
functional/block_cloning/block_cloning_ficlonerange_partial.ksh \
functional/block_cloning/block_cloning_cross_enc_dataset.ksh \
+ functional/block_cloning/block_cloning_replay.ksh \
+ functional/block_cloning/block_cloning_replay_encrypted.ksh \
functional/bootfs/bootfs_001_pos.ksh \
functional/bootfs/bootfs_002_neg.ksh \
functional/bootfs/bootfs_003_pos.ksh \
@@ -1113,6 +1115,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/cli_root/zpool_import/zpool_import_missing_002_pos.ksh \
functional/cli_root/zpool_import/zpool_import_missing_003_pos.ksh \
functional/cli_root/zpool_import/zpool_import_rename_001_pos.ksh \
+ functional/cli_root/zpool_import/zpool_import_status.ksh \
functional/cli_root/zpool_initialize/cleanup.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_attach_detach_add_remove.ksh \
functional/cli_root/zpool_initialize/zpool_initialize_fault_export_import_online.ksh \
@@ -1366,6 +1369,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/compression/setup.ksh \
functional/cp_files/cleanup.ksh \
functional/cp_files/cp_files_001_pos.ksh \
+ functional/cp_files/cp_stress.ksh \
functional/cp_files/setup.ksh \
functional/crtime/cleanup.ksh \
functional/crtime/crtime_001_pos.ksh \
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib
index 526bd54a2bf3..50f3a3d262c0 100644
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib
@@ -53,6 +53,6 @@ function get_same_blocks
awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.a
zdb $KEY -vvvvv $3 -O $4 | \
awk '/ L0 / { print l++ " " $3 " " $7 }' > $zdbout.b
- echo $(sort $zdbout.a $zdbout.b | uniq -d | cut -f1 -d' ')
+ echo $(sort -n $zdbout.a $zdbout.b | uniq -d | cut -f1 -d' ')
}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh
new file mode 100755
index 000000000000..1fdf379ed2d2
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh
@@ -0,0 +1,131 @@
+#!/bin/ksh -p
+#
+# 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
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly for cloned files. This
+# test is ported from slog_replay tests for block cloning.
+#
+# STRATEGY:
+# 1. Create an empty file system (TESTFS)
+# 2. Create regular files and sync
+# 3. Freeze TESTFS
+# 4. Clone the file
+# 5. Unmount filesystem
+# <At this stage TESTFS is frozen, the intent log contains a
+# complete set of deltas to replay it>
+# 6. Remount TESTFS <which replays the intent log>
+# 7. Compare clone file with the original file
+#
+
+verify_runnable "global"
+
+if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+export VDIR=$TEST_BASE_DIR/disk-bclone
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export LDEV="$VDIR/e $VDIR/f"
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s $MINVDEVSIZE $VDEV $LDEV
+
+claim="The slogs are replayed correctly for cloned files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR $VDIR $VDIR2
+}
+
+log_onexit cleanup
+
+#
+# 1. Create an empty file system (TESTFS)
+#
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV \
+ log mirror $LDEV
+log_must zfs create $TESTPOOL/$TESTFS
+
+#
+# 2. TX_WRITE: Create two files and sync txg
+#
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 \
+ oflag=sync bs=128k count=4
+log_must zfs set recordsize=16K $TESTPOOL/$TESTFS
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file2 \
+ oflag=sync bs=16K count=2048
+sync_pool $TESTPOOL
+
+#
+# 3. Checkpoint for ZIL Replay
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 4. TX_CLONE_RANGE: Clone the file
+#
+log_must clonefile -c /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must clonefile -c /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is frozen, the intent log contains a complete set
+# of deltas to replay for clone files.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must zpool import -f -d $VDIR $TESTPOOL
+
+#
+# 7. Compare clone file with the original file
+#
+log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must have_same_content /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 \
+ $TESTPOOL/$TESTFS clone1)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
+ $TESTPOOL/$TESTFS clone2)
+log_must [ "$blocks" = "$(seq -s " " 0 2047)" ]
+
+log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh
new file mode 100755
index 000000000000..f9f687c83e5b
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh
@@ -0,0 +1,133 @@
+#!/bin/ksh -p
+#
+# 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
+#
+
+. $STF_SUITE/include/libtest.shlib
+. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
+
+#
+# DESCRIPTION:
+# Verify slogs are replayed correctly for encrypted cloned files.
+# This test is ported from slog_replay tests for block cloning.
+#
+# STRATEGY:
+# 1. Create an encrypted file system (TESTFS)
+# 2. Create regular files and sync
+# 3. Freeze TESTFS
+# 4. Clone the file
+# 5. Unmount filesystem
+# <At this stage TESTFS is frozen, the intent log contains a
+# complete set of deltas to replay it>
+# 6. Remount encrypted TESTFS <which replays the intent log>
+# 7. Compare clone file with the original file
+#
+
+verify_runnable "global"
+
+if [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
+ log_unsupported "copy_file_range not available before Linux 4.5"
+fi
+
+export VDIR=$TEST_BASE_DIR/disk-bclone
+export VDEV="$VDIR/a $VDIR/b $VDIR/c"
+export LDEV="$VDIR/e $VDIR/f"
+log_must rm -rf $VDIR
+log_must mkdir -p $VDIR
+log_must truncate -s $MINVDEVSIZE $VDEV $LDEV
+export PASSPHRASE="password"
+
+claim="The slogs are replayed correctly for encrypted cloned files."
+
+log_assert $claim
+
+function cleanup
+{
+ datasetexists $TESTPOOL && destroy_pool $TESTPOOL
+ rm -rf $TESTDIR $VDIR $VDIR2
+}
+
+log_onexit cleanup
+
+#
+# 1. Create an encrypted file system (TESTFS)
+#
+log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $VDEV \
+ log mirror $LDEV
+log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \
+ "-o keyformat=passphrase -o keylocation=prompt $TESTPOOL/$TESTFS"
+
+#
+# 2. TX_WRITE: Create two files and sync txg
+#
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file1 \
+ oflag=sync bs=128k count=4
+log_must zfs set recordsize=16K $TESTPOOL/$TESTFS
+log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/file2 \
+ oflag=sync bs=16K count=2048
+sync_pool $TESTPOOL
+
+#
+# 3. Checkpoint for ZIL Replay
+#
+log_must zpool freeze $TESTPOOL
+
+#
+# 4. TX_CLONE_RANGE: Clone the file
+#
+log_must clonefile -c /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must clonefile -c /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+#
+# 5. Unmount filesystem and export the pool
+#
+# At this stage TESTFS is frozen, the intent log contains a complete set
+# of deltas to replay for clone files.
+#
+log_must zfs unmount /$TESTPOOL/$TESTFS
+
+log_note "Verify transactions to replay:"
+log_must zdb -iv $TESTPOOL/$TESTFS
+
+log_must zpool export $TESTPOOL
+
+#
+# 6. Remount TESTFS <which replays the intent log>
+#
+# Import the pool to unfreeze it and claim log blocks. It has to be
+# `zpool import -f` because we can't write a frozen pool's labels!
+#
+log_must eval "echo $PASSPHRASE | zpool import -l -f -d $VDIR $TESTPOOL"
+
+#
+# 7. Compare clone file with the original file
+#
+log_must have_same_content /$TESTPOOL/$TESTFS/file1 /$TESTPOOL/$TESTFS/clone1
+log_must have_same_content /$TESTPOOL/$TESTFS/file2 /$TESTPOOL/$TESTFS/clone2
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file1 \
+ $TESTPOOL/$TESTFS clone1 $PASSPHRASE)
+log_must [ "$blocks" = "0 1 2 3" ]
+
+typeset blocks=$(get_same_blocks $TESTPOOL/$TESTFS file2 \
+ $TESTPOOL/$TESTFS clone2 $PASSPHRASE)
+log_must [ "$blocks" = "$(seq -s " " 0 2047)" ]
+
+log_pass $claim
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore
new file mode 100644
index 000000000000..d15225ac8429
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore
@@ -0,0 +1 @@
+seekflood
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh
new file mode 100755
index 000000000000..43bb8ab572d2
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh
@@ -0,0 +1,73 @@
+#! /bin/ksh -p
+#
+# 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) 2023 by Lawrence Livermore National Security, LLC.
+#
+
+. $STF_SUITE/include/libtest.shlib
+
+#
+# DESCRIPTION:
+#
+# https://github.com/openzfs/zfs/issues/15526 identified a dirty dnode
+# SEEK_HOLE/SEEK_DATA bug. https://github.com/openzfs/zfs/pull/15571
+# fixed the bug, and was backported to 2.1.14 and 2.2.2.
+#
+# This test is to ensure that the bug, as understood, will not recur.
+#
+# STRATEGY:
+#
+# 1. Run the 'seekflood' binary, for creation of files with timing
+# characteristics that can trigger #15526.
+# 2. A single run is not always a trigger, so run repeatedly.
+
+verify_runnable "global"
+
+function cleanup
+{
+ rm -rf /$TESTDIR/cp_stress
+}
+
+log_assert "Run the 'seekflood' binary repeatedly to try to trigger #15526"
+
+log_onexit cleanup
+
+log_must mkdir /$TESTPOOL/cp_stress
+
+MYPWD="$PWD"
+cd /$TESTPOOL/cp_stress
+CPUS=$(get_num_cpus)
+
+if is_freebsd ; then
+ # 'seekflood' takes longer on FreeBSD and can timeout the test
+ RUNS=3
+else
+ RUNS=10
+fi
+
+for i in $(seq 1 $RUNS) ; do
+ # Each run takes around 12 seconds.
+ log_must $STF_SUITE/tests/functional/cp_files/seekflood 2000 $CPUS
+done
+cd "$MYPWD"
+
+log_pass "No corruption detected"
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c
new file mode 100644
index 000000000000..02c2c8e6eca5
--- /dev/null
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c
@@ -0,0 +1,180 @@
+/*
+ * SPDX-License-Identifier: MIT
+ *
+ * Copyright (c) 2023, Rob Norris <robn@despairlabs.com>
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#define DATASIZE (4096)
+char data[DATASIZE];
+
+static int
+_open_file(int n, int wr)
+{
+ char buf[256];
+ int fd;
+
+ snprintf(buf, sizeof (buf), "testdata_%d_%d", getpid(), n);
+
+ if ((fd = open(buf, wr ? (O_WRONLY | O_CREAT) : O_RDONLY,
+ wr ? (S_IRUSR | S_IWUSR) : 0)) < 0) {
+ fprintf(stderr, "Error: open '%s' (%s): %s\n",
+ buf, wr ? "write" : "read", strerror(errno));
+ exit(1);
+ }
+
+ return (fd);
+}
+
+static void
+_write_file(int n, int fd)
+{
+ /* write a big ball of stuff */
+ ssize_t nwr = write(fd, data, DATASIZE);
+ if (nwr < 0) {
+ fprintf(stderr, "Error: write '%d_%d': %s\n",
+ getpid(), n, strerror(errno));
+ exit(1);
+ } else if (nwr < DATASIZE) {
+ fprintf(stderr, "Error: write '%d_%d': short write\n", getpid(),
+ n);
+ exit(1);
+ }
+}
+
+static int
+_seek_file(int n, int fd)
+{
+ struct stat st;
+ if (fstat(fd, &st) < 0) {
+ fprintf(stderr, "Error: fstat '%d_%d': %s\n", getpid(), n,
+ strerror(errno));
+ exit(1);
+ }
+
+ /*
+ * A zero-sized file correctly has no data, so seeking the file is
+ * pointless.
+ */
+ if (st.st_size == 0)
+ return (0);
+
+ /* size is real, and we only write, so SEEK_DATA must find something */
+ if (lseek(fd, 0, SEEK_DATA) < 0) {
+ if (errno == ENXIO)
+ return (1);
+ fprintf(stderr, "Error: lseek '%d_%d': %s\n",
+ getpid(), n, strerror(errno));
+ exit(2);
+ }
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ int nfiles = 0;
+ int nthreads = 0;
+
+ if (argc < 3 || (nfiles = atoi(argv[1])) == 0 ||
+ (nthreads = atoi(argv[2])) == 0) {
+ printf("usage: seekflood <nfiles> <threads>\n");
+ exit(1);
+ }
+
+ memset(data, 0x5a, DATASIZE);
+
+ /* fork off some flood threads */
+ for (int i = 0; i < nthreads; i++) {
+ if (!fork()) {
+ /* thread main */
+
+ /* create zero file */
+ int fd = _open_file(0, 1);
+ _write_file(0, fd);
+ close(fd);
+
+ int count = 0;
+
+ int h = 0, i, j, rfd, wfd;
+ for (i = 0; i < nfiles; i += 2, h++) {
+ j = i+1;
+
+ /* seek h, write i */
+ rfd = _open_file(h, 0);
+ wfd = _open_file(i, 1);
+ count += _seek_file(h, rfd);
+ _write_file(i, wfd);
+ close(rfd);
+ close(wfd);
+
+ /* seek i, write j */
+ rfd = _open_file(i, 0);
+ wfd = _open_file(j, 1);
+ count += _seek_file(i, rfd);
+ _write_file(j, wfd);
+ close(rfd);
+ close(wfd);
+ }
+
+ /* return count of failed seeks to parent */
+ exit(count < 256 ? count : 255);
+ }
+ }
+
+ /* wait for threads, take their seek fail counts from exit code */
+ int count = 0, crashed = 0;
+ for (int i = 0; i < nthreads; i++) {
+ int wstatus;
+ wait(&wstatus);
+ if (WIFEXITED(wstatus))
+ count += WEXITSTATUS(wstatus);
+ else
+ crashed++;
+ }
+
+ if (crashed) {
+ fprintf(stderr, "Error: child crashed; test failed\n");
+ exit(1);
+ }
+
+ if (count) {
+ fprintf(stderr, "Error: %d seek failures; test failed\n",
+ count);
+ exit(1);
+ }
+
+ exit(0);
+}
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh
index 47e439d0f4d5..2fa146556358 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh
@@ -44,6 +44,13 @@ if ! $(grep -q "CONFIG_IO_URING=y" /boot/config-$(uname -r)); then
log_unsupported "Requires io_uring support"
fi
+if [ -e /etc/os-release ] ; then
+ source /etc/os-release
+ if [ -n "$REDHAT_SUPPORT_PRODUCT_VERSION" ] && ((floor($REDHAT_SUPPORT_PRODUCT_VERSION) == 9)) ; then
+ log_unsupported "Disabled on CentOS 9, fails with 'Operation not permitted'"
+ fi
+fi
+
fio --ioengine=io_uring --parse-only || log_unsupported "fio io_uring support required"
function cleanup
diff --git a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh
index a31a7d254bfe..56ee3e9be67c 100755
--- a/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh
+++ b/sys/contrib/openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh
@@ -113,7 +113,7 @@ function test_replace # <pool> <devices> <parity>
log_must zpool scrub -w $pool
log_must zpool status -v
- log_must check_pool_status $pool "scan" "repaired 0B"
+ log_must check_pool_status $pool "scan" "with 0 errors"
}
log_must set_tunable32 EMBEDDED_SLOG_MIN_MS 99999
diff --git a/sys/modules/zfs/zfs_config.h b/sys/modules/zfs/zfs_config.h
index 03314cf89e35..b6e93c8eadf7 100644
--- a/sys/modules/zfs/zfs_config.h
+++ b/sys/modules/zfs/zfs_config.h
@@ -1113,7 +1113,7 @@
/* #undef ZFS_IS_GPL_COMPATIBLE */
/* Define the project alias string. */
-#define ZFS_META_ALIAS "zfs-2.2.99-257-FreeBSD_g450f2d0b0"
+#define ZFS_META_ALIAS "zfs-2.2.99-268-FreeBSD_g86e115e21"
/* Define the project author. */
#define ZFS_META_AUTHOR "OpenZFS"
@@ -1143,7 +1143,7 @@
#define ZFS_META_NAME "zfs"
/* Define the project release. */
-#define ZFS_META_RELEASE "257-FreeBSD_g450f2d0b0"
+#define ZFS_META_RELEASE "268-FreeBSD_g86e115e21"
/* Define the project version. */
#define ZFS_META_VERSION "2.2.99"
diff --git a/sys/modules/zfs/zfs_gitrev.h b/sys/modules/zfs/zfs_gitrev.h
index 2c3cbd2b99e7..f87735ca2dfe 100644
--- a/sys/modules/zfs/zfs_gitrev.h
+++ b/sys/modules/zfs/zfs_gitrev.h
@@ -1 +1 @@
-#define ZFS_META_GITREV "zfs-2.2.99-257-g450f2d0b0"
+#define ZFS_META_GITREV "zfs-2.2.99-268-g86e115e21"