From e184e3d70a6e4b756622d77a6a1f7e22d1a0c5cc Mon Sep 17 00:00:00 2001 From: John Baldwin Date: Tue, 12 Mar 2024 11:22:42 -0700 Subject: [PATCH] git subrepo pull --force sys/contrib/subrepo-openzfs subrepo: subdir: "sys/contrib/subrepo-openzfs" merged: "256817ec444a" upstream: origin: "https://github.com/CTSRD-CHERI/zfs.git" branch: "cheri-hybrid" commit: "256817ec444a" git-subrepo: version: "0.4.3" origin: "???" commit: "???" --- sys/contrib/subrepo-openzfs/.gitrepo | 4 +- .../cmd/zed/zed.d/statechange-slot_off.sh | 6 +- .../subrepo-openzfs/cmd/zed/zed.d/zed.rc | 2 +- .../subrepo-openzfs/include/sys/dbuf.h | 1 + sys/contrib/subrepo-openzfs/module/zfs/dbuf.c | 20 +- sys/contrib/subrepo-openzfs/module/zfs/dmu.c | 2 +- .../subrepo-openzfs/module/zfs/dnode.c | 8 + .../subrepo-openzfs/module/zfs/dnode_sync.c | 9 +- .../subrepo-openzfs/tests/runfiles/common.run | 2 +- .../subrepo-openzfs/tests/runfiles/linux.run | 3 +- .../tests/test-runner/bin/zts-report.py.in | 5 +- .../tests/zfs-tests/Makefile.am | 3 + .../tests/zfs-tests/tests/Makefile.am | 4 + .../block_cloning/block_cloning.kshlib | 2 +- .../block_cloning/block_cloning_replay.ksh | 131 +++++++++++++ .../block_cloning_replay_encrypted.ksh | 133 +++++++++++++ .../tests/functional/cp_files/.gitignore | 1 + .../tests/functional/cp_files/cp_stress.ksh | 73 +++++++ .../tests/functional/cp_files/seekflood.c | 180 ++++++++++++++++++ .../tests/functional/io/io_uring.ksh | 7 + .../functional/raidz/raidz_expand_005_pos.ksh | 2 +- 21 files changed, 581 insertions(+), 17 deletions(-) create mode 100755 sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh create mode 100755 sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh create mode 100644 sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore create mode 100755 sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh create mode 100644 sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c diff --git a/sys/contrib/subrepo-openzfs/.gitrepo b/sys/contrib/subrepo-openzfs/.gitrepo index e290668d4f65..306bffde0ec8 100644 --- a/sys/contrib/subrepo-openzfs/.gitrepo +++ b/sys/contrib/subrepo-openzfs/.gitrepo @@ -6,7 +6,7 @@ [subrepo] remote = https://github.com/CTSRD-CHERI/zfs.git branch = cheri-hybrid - commit = 3f36e91fa8d5269772a9813a1d26e711a378b747 - parent = 91348b413355aa92802a5f94b84a7229030910e1 + commit = 256817ec444af1bf0846397835e955e8418a3b73 + parent = 0b9521aeecf670e0fda710dc5e8aaf1d98e60f11 method = merge cmdver = 0.4.3 diff --git a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/statechange-slot_off.sh b/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/statechange-slot_off.sh index 150012abe71a..06acce93b8aa 100755 --- a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/statechange-slot_off.sh +++ b/sys/contrib/subrepo-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///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/subrepo-openzfs/cmd/zed/zed.d/zed.rc b/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed.rc index acdfabc8ded2..bc269b155d76 100644 --- a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed.rc +++ b/sys/contrib/subrepo-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/subrepo-openzfs/include/sys/dbuf.h b/sys/contrib/subrepo-openzfs/include/sys/dbuf.h index 1800a7e31da0..2ff0bc72b270 100644 --- a/sys/contrib/subrepo-openzfs/include/sys/dbuf.h +++ b/sys/contrib/subrepo-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/subrepo-openzfs/module/zfs/dbuf.c b/sys/contrib/subrepo-openzfs/module/zfs/dbuf.c index c5ccd4cd1e0c..03c97941d6d3 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/dbuf.c +++ b/sys/contrib/subrepo-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/subrepo-openzfs/module/zfs/dmu.c b/sys/contrib/subrepo-openzfs/module/zfs/dmu.c index 6cf7f3c3b12e..f5a5d0fc437f 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/dmu.c +++ b/sys/contrib/subrepo-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/subrepo-openzfs/module/zfs/dnode.c b/sys/contrib/subrepo-openzfs/module/zfs/dnode.c index 7ae74ad1318d..ba28aa06a91f 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/dnode.c +++ b/sys/contrib/subrepo-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/subrepo-openzfs/module/zfs/dnode_sync.c b/sys/contrib/subrepo-openzfs/module/zfs/dnode_sync.c index 8cffbdb9d20b..f67dad002319 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/dnode_sync.c +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/runfiles/common.run b/sys/contrib/subrepo-openzfs/tests/runfiles/common.run index ac12d44d7ce8..dbcead007173 100644 --- a/sys/contrib/subrepo-openzfs/tests/runfiles/common.run +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/runfiles/linux.run b/sys/contrib/subrepo-openzfs/tests/runfiles/linux.run index fb78d96fb52d..17ba23352422 100644 --- a/sys/contrib/subrepo-openzfs/tests/runfiles/linux.run +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/test-runner/bin/zts-report.py.in b/sys/contrib/subrepo-openzfs/tests/test-runner/bin/zts-report.py.in index b188a101c257..3b5eeacb6bad 100755 --- a/sys/contrib/subrepo-openzfs/tests/test-runner/bin/zts-report.py.in +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/zfs-tests/Makefile.am b/sys/contrib/subrepo-openzfs/tests/zfs-tests/Makefile.am index f8166352489e..3dd1a6452728 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/Makefile.am +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am index c87b84de67a8..06d3ff065e0e 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am @@ -524,6 +524,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 \ @@ -1185,6 +1187,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 \ @@ -1438,6 +1441,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/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib index 526bd54a2bf3..50f3a3d262c0 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning.kshlib +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay.ksh new file mode 100755 index 000000000000..1fdf379ed2d2 --- /dev/null +++ b/sys/contrib/subrepo-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 +# +# 6. Remount TESTFS +# 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 +# +# 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/subrepo-openzfs/tests/zfs-tests/tests/functional/block_cloning/block_cloning_replay_encrypted.ksh b/sys/contrib/subrepo-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/subrepo-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 +# +# 6. Remount encrypted TESTFS +# 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 +# +# 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/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore new file mode 100644 index 000000000000..d15225ac8429 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/.gitignore @@ -0,0 +1 @@ +seekflood diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/cp_stress.ksh new file mode 100755 index 000000000000..43bb8ab572d2 --- /dev/null +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c new file mode 100644 index 000000000000..02c2c8e6eca5 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/cp_files/seekflood.c @@ -0,0 +1,180 @@ +/* + * SPDX-License-Identifier: MIT + * + * Copyright (c) 2023, Rob Norris + * + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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 \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/subrepo-openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh index 47e439d0f4d5..2fa146556358 100755 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/io/io_uring.ksh +++ b/sys/contrib/subrepo-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/subrepo-openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh index a31a7d254bfe..56ee3e9be67c 100755 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/raidz/raidz_expand_005_pos.ksh @@ -113,7 +113,7 @@ function test_replace # 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