diff --git a/sys/contrib/subrepo-openzfs/.gitrepo b/sys/contrib/subrepo-openzfs/.gitrepo index fb3cb23e4b42..46d2769ef2b9 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 = 6208619e08d3fb4ed51ccdbb32d8d30460f4f292 - parent = d8dcaab72cf3c8490fb711518adf5d0a685ec202 + commit = 64e6835be758b36ef129a1ee548a501e93a27dd0 + parent = b421b291504ade31a8ab0e240af5ca04af401e47 method = merge cmdver = 0.4.3 diff --git a/sys/contrib/subrepo-openzfs/cmd/zdb/zdb.c b/sys/contrib/subrepo-openzfs/cmd/zdb/zdb.c index 777032bf82f6..cd934b2ae9ad 100644 --- a/sys/contrib/subrepo-openzfs/cmd/zdb/zdb.c +++ b/sys/contrib/subrepo-openzfs/cmd/zdb/zdb.c @@ -8533,11 +8533,14 @@ zdb_decompress_block(abd_t *pabd, void *buf, void *lbuf, uint64_t lsize, } /* - * We randomize lbuf2, and decompress to both - * lbuf and lbuf2. This way, we will know if - * decompression fill exactly to lsize. + * We set lbuf to all zeros and lbuf2 to all + * ones, then decompress to both buffers and + * compare their contents. This way we can + * know if decompression filled exactly to + * lsize or if it left some bytes unwritten. */ - VERIFY0(random_get_pseudo_bytes(lbuf2, lsize)); + memset(lbuf, 0x00, lsize); + memset(lbuf2, 0xff, lsize); if (zio_decompress_data(*cfuncp, pabd, lbuf, psize, lsize, NULL) == 0 && diff --git a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed-functions.sh b/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed-functions.sh index 3a2519633d01..470739d16460 100644 --- a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed-functions.sh +++ b/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed-functions.sh @@ -209,6 +209,10 @@ zed_notify() [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) + zed_notify_gotify "${subject}" "${pathname}"; rv=$? + [ "${rv}" -eq 0 ] && num_success=$((num_success + 1)) + [ "${rv}" -eq 1 ] && num_failure=$((num_failure + 1)) + [ "${num_success}" -gt 0 ] && return 0 [ "${num_failure}" -gt 0 ] && return 1 return 2 @@ -624,6 +628,97 @@ zed_notify_ntfy() } +# zed_notify_gotify (subject, pathname) +# +# Send a notification via Gotify . +# The Gotify URL (ZED_GOTIFY_URL) defines a self-hosted Gotify location. +# The Gotify application token (ZED_GOTIFY_APPTOKEN) defines a +# Gotify application token which is associated with a message. +# The optional Gotify priority value (ZED_GOTIFY_PRIORITY) overrides the +# default or configured priority at the Gotify server for the application. +# +# Requires curl and sed executables to be installed in the standard PATH. +# +# References +# https://gotify.net/docs/index +# +# Arguments +# subject: notification subject +# pathname: pathname containing the notification message (OPTIONAL) +# +# Globals +# ZED_GOTIFY_URL +# ZED_GOTIFY_APPTOKEN +# ZED_GOTIFY_PRIORITY +# +# Return +# 0: notification sent +# 1: notification failed +# 2: not configured +# +zed_notify_gotify() +{ + local subject="$1" + local pathname="${2:-"/dev/null"}" + local msg_body + local msg_out + local msg_err + + [ -n "${ZED_GOTIFY_URL}" ] && [ -n "${ZED_GOTIFY_APPTOKEN}" ] || return 2 + local url="${ZED_GOTIFY_URL}/message?token=${ZED_GOTIFY_APPTOKEN}" + + if [ ! -r "${pathname}" ]; then + zed_log_err "gotify cannot read \"${pathname}\"" + return 1 + fi + + zed_check_cmd "curl" "sed" || return 1 + + # Read the message body in. + # + msg_body="$(cat "${pathname}")" + + if [ -z "${msg_body}" ] + then + msg_body=$subject + subject="" + fi + + # Send the POST request and check for errors. + # + if [ -n "${ZED_GOTIFY_PRIORITY}" ]; then + msg_out="$( \ + curl \ + --form-string "title=${subject}" \ + --form-string "message=${msg_body}" \ + --form-string "priority=${ZED_GOTIFY_PRIORITY}" \ + "${url}" \ + 2>/dev/null \ + )"; rv=$? + else + msg_out="$( \ + curl \ + --form-string "title=${subject}" \ + --form-string "message=${msg_body}" \ + "${url}" \ + 2>/dev/null \ + )"; rv=$? + fi + + if [ "${rv}" -ne 0 ]; then + zed_log_err "curl exit=${rv}" + return 1 + fi + msg_err="$(echo "${msg_out}" \ + | sed -n -e 's/.*"errors" *:.*\[\(.*\)\].*/\1/p')" + if [ -n "${msg_err}" ]; then + zed_log_err "gotify \"${msg_err}"\" + return 1 + fi + return 0 +} + + # zed_rate_limit (tag, [interval]) # 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 bc269b155d76..ec64ecfaa13c 100644 --- a/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed.rc +++ b/sys/contrib/subrepo-openzfs/cmd/zed/zed.d/zed.rc @@ -169,3 +169,24 @@ ZED_SYSLOG_SUBCLASS_EXCLUDE="history_event" # # https://ntfy.sh by default; uncomment to enable an alternative service url. #ZED_NTFY_URL="https://ntfy.sh" + +## +# Gotify server URL +# This defines a URL that the Gotify call will be directed toward. +# +# Disabled by default; uncomment to enable. +#ZED_GOTIFY_URL="" + +## +# Gotify application token +# This defines a Gotify application token which a message is associated with. +# This token is generated when an application is created on the Gotify server. +# Disabled by default; uncomment to enable. +#ZED_GOTIFY_APPTOKEN="" + +## +# Gotify priority (optional) +# If defined, this overrides the default priority of the +# Gotify application associated with ZED_GOTIFY_APPTOKEN. +# Value is an integer 0 and up. +#ZED_GOTIFY_PRIORITY="" diff --git a/sys/contrib/subrepo-openzfs/config/kernel-fpu.m4 b/sys/contrib/subrepo-openzfs/config/kernel-fpu.m4 index c6efebd8cf61..edfde1a02d30 100644 --- a/sys/contrib/subrepo-openzfs/config/kernel-fpu.m4 +++ b/sys/contrib/subrepo-openzfs/config/kernel-fpu.m4 @@ -79,6 +79,12 @@ AC_DEFUN([ZFS_AC_KERNEL_SRC_FPU], [ __kernel_fpu_end(); ], [], [ZFS_META_LICENSE]) + ZFS_LINUX_TEST_SRC([kernel_neon], [ + #include + ], [ + kernel_neon_begin(); + kernel_neon_end(); + ], [], [ZFS_META_LICENSE]) ]) AC_DEFUN([ZFS_AC_KERNEL_FPU], [ @@ -105,9 +111,20 @@ AC_DEFUN([ZFS_AC_KERNEL_FPU], [ AC_DEFINE(KERNEL_EXPORTS_X86_FPU, 1, [kernel exports FPU functions]) ],[ - AC_MSG_RESULT(internal) - AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1, - [kernel fpu internal]) + dnl # + dnl # ARM neon symbols (only on arm and arm64) + dnl # could be GPL-only on arm64 after Linux 6.2 + dnl # + ZFS_LINUX_TEST_RESULT([kernel_neon_license],[ + AC_MSG_RESULT(kernel_neon_*) + AC_DEFINE(HAVE_KERNEL_NEON, 1, + [kernel has kernel_neon_* functions]) + ],[ + # catch-all + AC_MSG_RESULT(internal) + AC_DEFINE(HAVE_KERNEL_FPU_INTERNAL, 1, + [kernel fpu internal]) + ]) ]) ]) ]) diff --git a/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_aarch64.h b/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_aarch64.h index 16276b08c759..123a0c72bc6a 100644 --- a/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_aarch64.h +++ b/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_aarch64.h @@ -71,9 +71,15 @@ #define ID_AA64PFR0_EL1 sys_reg(3, 0, 0, 1, 0) #define ID_AA64ISAR0_EL1 sys_reg(3, 0, 0, 6, 0) +#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON)) #define kfpu_allowed() 1 #define kfpu_begin() kernel_neon_begin() #define kfpu_end() kernel_neon_end() +#else +#define kfpu_allowed() 0 +#define kfpu_begin() do {} while (0) +#define kfpu_end() do {} while (0) +#endif #define kfpu_init() (0) #define kfpu_fini() do {} while (0) diff --git a/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_arm.h b/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_arm.h index c432a6d4abd1..bc70eaef3073 100644 --- a/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_arm.h +++ b/sys/contrib/subrepo-openzfs/include/os/linux/kernel/linux/simd_arm.h @@ -53,9 +53,15 @@ #include #include +#if (defined(HAVE_KERNEL_NEON) && defined(CONFIG_KERNEL_MODE_NEON)) #define kfpu_allowed() 1 #define kfpu_begin() kernel_neon_begin() #define kfpu_end() kernel_neon_end() +#else +#define kfpu_allowed() 0 +#define kfpu_begin() do {} while (0) +#define kfpu_end() do {} while (0) +#endif #define kfpu_init() (0) #define kfpu_fini() do {} while (0) diff --git a/sys/contrib/subrepo-openzfs/include/os/linux/zfs/sys/trace_zil.h b/sys/contrib/subrepo-openzfs/include/os/linux/zfs/sys/trace_zil.h index afa1a274e43c..ae1caa3ac473 100644 --- a/sys/contrib/subrepo-openzfs/include/os/linux/zfs/sys/trace_zil.h +++ b/sys/contrib/subrepo-openzfs/include/os/linux/zfs/sys/trace_zil.h @@ -51,7 +51,9 @@ __field(uint64_t, zl_parse_lr_seq) \ __field(uint64_t, zl_parse_blk_count) \ __field(uint64_t, zl_parse_lr_count) \ - __field(uint64_t, zl_cur_used) \ + __field(uint64_t, zl_cur_size) \ + __field(uint64_t, zl_cur_left) \ + __field(uint64_t, zl_cur_max) \ __field(clock_t, zl_replay_time) \ __field(uint64_t, zl_replay_blks) @@ -72,7 +74,9 @@ __entry->zl_parse_lr_seq = zilog->zl_parse_lr_seq; \ __entry->zl_parse_blk_count = zilog->zl_parse_blk_count;\ __entry->zl_parse_lr_count = zilog->zl_parse_lr_count; \ - __entry->zl_cur_used = zilog->zl_cur_used; \ + __entry->zl_cur_size = zilog->zl_cur_size; \ + __entry->zl_cur_left = zilog->zl_cur_left; \ + __entry->zl_cur_max = zilog->zl_cur_max; \ __entry->zl_replay_time = zilog->zl_replay_time; \ __entry->zl_replay_blks = zilog->zl_replay_blks; @@ -82,7 +86,8 @@ "replay %u stop_sync %u logbias %u sync %u " \ "parse_error %u parse_blk_seq %llu parse_lr_seq %llu " \ "parse_blk_count %llu parse_lr_count %llu " \ - "cur_used %llu replay_time %lu replay_blks %llu }" + "cur_size %llu cur_left %llu cur_max %llu replay_time %lu " \ + "replay_blks %llu }" #define ZILOG_TP_PRINTK_ARGS \ __entry->zl_lr_seq, __entry->zl_commit_lr_seq, \ @@ -92,7 +97,8 @@ __entry->zl_stop_sync, __entry->zl_logbias, __entry->zl_sync, \ __entry->zl_parse_error, __entry->zl_parse_blk_seq, \ __entry->zl_parse_lr_seq, __entry->zl_parse_blk_count, \ - __entry->zl_parse_lr_count, __entry->zl_cur_used, \ + __entry->zl_parse_lr_count, __entry->zl_cur_size, \ + __entry->zl_cur_left, __entry->zl_cur_max, \ __entry->zl_replay_time, __entry->zl_replay_blks #define ITX_TP_STRUCT_ENTRY \ diff --git a/sys/contrib/subrepo-openzfs/man/man7/zpoolprops.7 b/sys/contrib/subrepo-openzfs/man/man7/zpoolprops.7 index 7709d85226dc..5428ab8d3076 100644 --- a/sys/contrib/subrepo-openzfs/man/man7/zpoolprops.7 +++ b/sys/contrib/subrepo-openzfs/man/man7/zpoolprops.7 @@ -28,7 +28,7 @@ .\" Copyright (c) 2021, Colm Buckley .\" Copyright (c) 2023, Klara Inc. .\" -.Dd April 18, 2023 +.Dd January 2, 2024 .Dt ZPOOLPROPS 7 .Os . @@ -331,7 +331,7 @@ Specifies that the pool maintain compatibility with specific feature sets. When set to .Sy off (or unset) compatibility is disabled (all features may be enabled); when set to -.Sy legacy Ns +.Sy legacy no features may be enabled. When set to a comma-separated list of filenames (each filename may either be an absolute path, or relative to diff --git a/sys/contrib/subrepo-openzfs/module/zfs/dsl_deadlist.c b/sys/contrib/subrepo-openzfs/module/zfs/dsl_deadlist.c index 2832294b6974..e6c8d4be13b4 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/dsl_deadlist.c +++ b/sys/contrib/subrepo-openzfs/module/zfs/dsl_deadlist.c @@ -1000,8 +1000,6 @@ livelist_compare(const void *larg, const void *rarg) /* if vdevs are equal, sort by offsets. */ uint64_t l_dva0_offset = DVA_GET_OFFSET(&l->blk_dva[0]); uint64_t r_dva0_offset = DVA_GET_OFFSET(&r->blk_dva[0]); - if (l_dva0_offset == r_dva0_offset) - ASSERT3U(l->blk_birth, ==, r->blk_birth); return (TREE_CMP(l_dva0_offset, r_dva0_offset)); } @@ -1016,9 +1014,9 @@ struct livelist_iter_arg { * and used to match up ALLOC/FREE pairs. ALLOC'd blkptrs without a * corresponding FREE are stored in the supplied bplist. * - * Note that multiple FREE and ALLOC entries for the same blkptr may - * be encountered when dedup is involved. For this reason we keep a - * refcount for all the FREE entries of each blkptr and ensure that + * Note that multiple FREE and ALLOC entries for the same blkptr may be + * encountered when dedup or block cloning is involved. For this reason we + * keep a refcount for all the FREE entries of each blkptr and ensure that * each of those FREE entries has a corresponding ALLOC preceding it. */ static int @@ -1037,6 +1035,13 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed, livelist_entry_t node; node.le_bp = *bp; livelist_entry_t *found = avl_find(avl, &node, NULL); + if (found) { + ASSERT3U(BP_GET_PSIZE(bp), ==, BP_GET_PSIZE(&found->le_bp)); + ASSERT3U(BP_GET_CHECKSUM(bp), ==, + BP_GET_CHECKSUM(&found->le_bp)); + ASSERT3U(BP_PHYSICAL_BIRTH(bp), ==, + BP_PHYSICAL_BIRTH(&found->le_bp)); + } if (bp_freed) { if (found == NULL) { /* first free entry for this blkptr */ @@ -1046,10 +1051,10 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed, e->le_refcnt = 1; avl_add(avl, e); } else { - /* dedup block free */ - ASSERT(BP_GET_DEDUP(bp)); - ASSERT3U(BP_GET_CHECKSUM(bp), ==, - BP_GET_CHECKSUM(&found->le_bp)); + /* + * Deduped or cloned block free. We could assert D bit + * for dedup, but there is no such one for cloning. + */ ASSERT3U(found->le_refcnt + 1, >, found->le_refcnt); found->le_refcnt++; } @@ -1065,14 +1070,6 @@ dsl_livelist_iterate(void *arg, const blkptr_t *bp, boolean_t bp_freed, /* all tracked free pairs have been matched */ avl_remove(avl, found); kmem_free(found, sizeof (livelist_entry_t)); - } else { - /* - * This is definitely a deduped blkptr so - * let's validate it. - */ - ASSERT(BP_GET_DEDUP(bp)); - ASSERT3U(BP_GET_CHECKSUM(bp), ==, - BP_GET_CHECKSUM(&found->le_bp)); } } } diff --git a/sys/contrib/subrepo-openzfs/module/zfs/zfs_vnops.c b/sys/contrib/subrepo-openzfs/module/zfs/zfs_vnops.c index b2b7e36645b5..384cdf0dca97 100644 --- a/sys/contrib/subrepo-openzfs/module/zfs/zfs_vnops.c +++ b/sys/contrib/subrepo-openzfs/module/zfs/zfs_vnops.c @@ -1186,11 +1186,18 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp, inblksz = inzp->z_blksz; /* - * We cannot clone into files with different block size if we can't - * grow it (block size is already bigger or more than one block). + * We cannot clone into a file with different block size if we can't + * grow it (block size is already bigger, has more than one block, or + * not locked for growth). There are other possible reasons for the + * grow to fail, but we cover what we can before opening transaction + * and the rest detect after we try to do it. */ + if (inblksz < outzp->z_blksz) { + error = SET_ERROR(EINVAL); + goto unlock; + } if (inblksz != outzp->z_blksz && (outzp->z_size > outzp->z_blksz || - outzp->z_size > inblksz)) { + outlr->lr_length != UINT64_MAX)) { error = SET_ERROR(EINVAL); goto unlock; } @@ -1309,12 +1316,24 @@ zfs_clone_range(znode_t *inzp, uint64_t *inoffp, znode_t *outzp, } /* - * Copy source znode's block size. This only happens on the - * first iteration since zfs_rangelock_reduce() will shrink down - * lr_len to the appropriate size. + * Copy source znode's block size. This is done only if the + * whole znode is locked (see zfs_rangelock_cb()) and only + * on the first iteration since zfs_rangelock_reduce() will + * shrink down lr_length to the appropriate size. */ if (outlr->lr_length == UINT64_MAX) { zfs_grow_blocksize(outzp, inblksz, tx); + + /* + * Block growth may fail for many reasons we can not + * predict here. If it happen the cloning is doomed. + */ + if (inblksz != outzp->z_blksz) { + error = SET_ERROR(EINVAL); + dmu_tx_abort(tx); + break; + } + /* * Round range lock up to the block boundary, so we * prevent appends until we are done. diff --git a/sys/contrib/subrepo-openzfs/tests/Makefile.am b/sys/contrib/subrepo-openzfs/tests/Makefile.am index 2e633041ab59..12e9c9f9daf2 100644 --- a/sys/contrib/subrepo-openzfs/tests/Makefile.am +++ b/sys/contrib/subrepo-openzfs/tests/Makefile.am @@ -16,6 +16,7 @@ dist_scripts_test_runner_include_DATA = \ scripts_runfilesdir = $(datadir)/$(PACKAGE)/runfiles dist_scripts_runfiles_DATA = \ + %D%/runfiles/bclone.run \ %D%/runfiles/common.run \ %D%/runfiles/freebsd.run \ %D%/runfiles/linux.run \ diff --git a/sys/contrib/subrepo-openzfs/tests/runfiles/bclone.run b/sys/contrib/subrepo-openzfs/tests/runfiles/bclone.run new file mode 100644 index 000000000000..3d0f545d9226 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/runfiles/bclone.run @@ -0,0 +1,46 @@ +# +# 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. +# +# This run file contains all of the common functional tests. When +# adding a new test consider also adding it to the sanity.run file +# if the new test runs to completion in only a few seconds. +# +# Approximate run time: 5 hours +# + +[DEFAULT] +pre = setup +quiet = False +pre_user = root +user = root +timeout = 28800 +post_user = root +post = cleanup +failsafe_user = root +failsafe = callbacks/zfs_failsafe +outputdir = /var/tmp/test_results +tags = ['bclone'] + +[tests/functional/bclone] +tests = ['bclone_crossfs_corner_cases', + 'bclone_crossfs_data', + 'bclone_crossfs_embedded', + 'bclone_crossfs_hole', + 'bclone_diffprops_all', + 'bclone_diffprops_checksum', + 'bclone_diffprops_compress', + 'bclone_diffprops_copies', + 'bclone_diffprops_recordsize', + 'bclone_prop_sync', + 'bclone_samefs_corner_cases', + 'bclone_samefs_data', + 'bclone_samefs_embedded', + 'bclone_samefs_hole'] +tags = ['bclone'] diff --git a/sys/contrib/subrepo-openzfs/tests/runfiles/common.run b/sys/contrib/subrepo-openzfs/tests/runfiles/common.run index dbcead007173..646f71e4a181 100644 --- a/sys/contrib/subrepo-openzfs/tests/runfiles/common.run +++ b/sys/contrib/subrepo-openzfs/tests/runfiles/common.run @@ -53,6 +53,24 @@ tags = ['functional', 'arc'] tests = ['atime_001_pos', 'atime_002_neg', 'root_atime_off', 'root_atime_on'] tags = ['functional', 'atime'] +[tests/functional/bclone] +tests = ['bclone_crossfs_corner_cases_limited', + 'bclone_crossfs_data', + 'bclone_crossfs_embedded', + 'bclone_crossfs_hole', + 'bclone_diffprops_all', + 'bclone_diffprops_checksum', + 'bclone_diffprops_compress', + 'bclone_diffprops_copies', + 'bclone_diffprops_recordsize', + 'bclone_prop_sync', + 'bclone_samefs_corner_cases_limited', + 'bclone_samefs_data', + 'bclone_samefs_embedded', + 'bclone_samefs_hole'] +tags = ['functional', 'bclone'] +timeout = 7200 + [tests/functional/bootfs] tests = ['bootfs_001_pos', 'bootfs_002_neg', 'bootfs_003_pos', 'bootfs_004_neg', 'bootfs_005_neg', 'bootfs_006_pos', 'bootfs_007_pos', 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 708b7be91767..7bf4d05d542b 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 @@ -263,13 +263,50 @@ if sys.platform.startswith('freebsd'): 'cli_root/zpool_import/zpool_import_012_pos': ['FAIL', known_reason], 'delegate/zfs_allow_003_pos': ['FAIL', known_reason], 'inheritance/inherit_001_pos': ['FAIL', 11829], - 'resilver/resilver_restart_001': ['FAIL', known_reason], 'pool_checkpoint/checkpoint_big_rewind': ['FAIL', 12622], 'pool_checkpoint/checkpoint_indirect': ['FAIL', 12623], + 'resilver/resilver_restart_001': ['FAIL', known_reason], 'snapshot/snapshot_002_pos': ['FAIL', '14831'], }) elif sys.platform.startswith('linux'): maybe.update({ + 'bclone/bclone_crossfs_corner_cases': ['SKIP', cfr_cross_reason], + 'bclone/bclone_crossfs_corner_cases_limited': + ['SKIP', cfr_cross_reason], + 'bclone/bclone_crossfs_data': ['SKIP', cfr_cross_reason], + 'bclone/bclone_crossfs_embedded': ['SKIP', cfr_cross_reason], + 'bclone/bclone_crossfs_hole': ['SKIP', cfr_cross_reason], + 'bclone/bclone_diffprops_all': ['SKIP', cfr_cross_reason], + 'bclone/bclone_diffprops_checksum': ['SKIP', cfr_cross_reason], + 'bclone/bclone_diffprops_compress': ['SKIP', cfr_cross_reason], + 'bclone/bclone_diffprops_copies': ['SKIP', cfr_cross_reason], + 'bclone/bclone_diffprops_recordsize': ['SKIP', cfr_cross_reason], + 'bclone/bclone_prop_sync': ['SKIP', cfr_cross_reason], + 'bclone/bclone_samefs_corner_cases': ['SKIP', cfr_reason], + 'bclone/bclone_samefs_corner_cases_limited': ['SKIP', cfr_reason], + 'bclone/bclone_samefs_data': ['SKIP', cfr_reason], + 'bclone/bclone_samefs_embedded': ['SKIP', cfr_reason], + 'bclone/bclone_samefs_hole': ['SKIP', cfr_reason], + 'block_cloning/block_cloning_copyfilerange': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_copyfilerange_cross_dataset': + ['SKIP', cfr_cross_reason], + 'block_cloning/block_cloning_copyfilerange_fallback': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_copyfilerange_fallback_same_txg': + ['SKIP', cfr_cross_reason], + 'block_cloning/block_cloning_copyfilerange_partial': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_cross_enc_dataset': + ['SKIP', cfr_cross_reason], + 'block_cloning/block_cloning_disabled_copyfilerange': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_lwb_buffer_overflow': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_replay': + ['SKIP', cfr_reason], + 'block_cloning/block_cloning_replay_encrypted': + ['SKIP', cfr_reason], 'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason], 'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason], 'fault/auto_online_002_pos': ['FAIL', 11889], @@ -278,41 +315,21 @@ elif sys.platform.startswith('linux'): 'fault/auto_spare_multiple': ['FAIL', 11889], 'fault/auto_spare_shared': ['FAIL', 11889], 'fault/decompress_fault': ['FAIL', 11889], + 'idmap_mount/idmap_mount_001': ['SKIP', idmap_reason], + 'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason], + 'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason], + 'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason], + 'idmap_mount/idmap_mount_005': ['SKIP', idmap_reason], 'io/io_uring': ['SKIP', 'io_uring support required'], 'limits/filesystem_limit': ['SKIP', known_reason], 'limits/snapshot_limit': ['SKIP', known_reason], 'mmp/mmp_active_import': ['FAIL', known_reason], 'mmp/mmp_exported_import': ['FAIL', known_reason], 'mmp/mmp_inactive_import': ['FAIL', known_reason], - 'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', 12621], - 'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason], 'zvol/zvol_misc/zvol_misc_fua': ['SKIP', 14872], + 'zvol/zvol_misc/zvol_misc_snapdev': ['FAIL', 12621], 'zvol/zvol_misc/zvol_misc_trim': ['SKIP', 14872], - 'idmap_mount/idmap_mount_001': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_002': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_003': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_004': ['SKIP', idmap_reason], - 'idmap_mount/idmap_mount_005': ['SKIP', idmap_reason], - 'block_cloning/block_cloning_disabled_copyfilerange': - ['SKIP', cfr_reason], - 'block_cloning/block_cloning_copyfilerange': - ['SKIP', cfr_reason], - 'block_cloning/block_cloning_copyfilerange_partial': - ['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_lwb_buffer_overflow': - ['SKIP', cfr_reason], - 'block_cloning/block_cloning_copyfilerange_cross_dataset': - ['SKIP', cfr_cross_reason], - 'block_cloning/block_cloning_copyfilerange_fallback_same_txg': - ['SKIP', cfr_cross_reason], - 'block_cloning/block_cloning_cross_enc_dataset': - ['SKIP', cfr_cross_reason], + 'zvol/zvol_misc/zvol_misc_volmode': ['FAIL', known_reason], }) # Not all Github actions runners have scsi_debug module, so we may skip diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/Makefile.am b/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/Makefile.am index 5bc9a3391eb5..91a8acd450a6 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/Makefile.am +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/Makefile.am @@ -2,6 +2,7 @@ scripts_zfs_tests_bindir = $(datadir)/$(PACKAGE)/zfs-tests/bin scripts_zfs_tests_bin_PROGRAMS = %D%/chg_usr_exec +scripts_zfs_tests_bin_PROGRAMS += %D%/clonefile scripts_zfs_tests_bin_PROGRAMS += %D%/cp_files scripts_zfs_tests_bin_PROGRAMS += %D%/ctime scripts_zfs_tests_bin_PROGRAMS += %D%/dir_rd_update @@ -123,7 +124,6 @@ scripts_zfs_tests_bin_PROGRAMS += %D%/renameat2 scripts_zfs_tests_bin_PROGRAMS += %D%/xattrtest scripts_zfs_tests_bin_PROGRAMS += %D%/zed_fd_spill-zedlet scripts_zfs_tests_bin_PROGRAMS += %D%/idmap_util -scripts_zfs_tests_bin_PROGRAMS += %D%/clonefile %C%_idmap_util_LDADD = libspl.la diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/clonefile.c b/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/clonefile.c index 696dc471d8c3..d002cd9b587e 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/clonefile.c +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/cmd/clonefile.c @@ -59,6 +59,10 @@ #endif #endif /* __NR_copy_file_range */ +#ifdef __FreeBSD__ +#define loff_t off_t +#endif + ssize_t copy_file_range(int, loff_t *, int, loff_t *, size_t, unsigned int) __attribute__((weak)); @@ -140,7 +144,7 @@ usage(void) " FICLONERANGE:\n" " clonefile -r \n" " copy_file_range:\n" - " clonefile -f \n" + " clonefile -f [ ]\n" " FIDEDUPERANGE:\n" " clonefile -d \n"); return (1); @@ -179,13 +183,29 @@ main(int argc, char **argv) } } - if (mode == CF_MODE_NONE || (argc-optind) < 2 || - (mode != CF_MODE_CLONE && (argc-optind) < 5)) - return (usage()); + switch (mode) { + case CF_MODE_NONE: + return (usage()); + case CF_MODE_CLONE: + if ((argc-optind) != 2) + return (usage()); + break; + case CF_MODE_CLONERANGE: + case CF_MODE_DEDUPERANGE: + if ((argc-optind) != 5) + return (usage()); + break; + case CF_MODE_COPYFILERANGE: + if ((argc-optind) != 2 && (argc-optind) != 5) + return (usage()); + break; + default: + abort(); + } loff_t soff = 0, doff = 0; - size_t len = 0; - if (mode != CF_MODE_CLONE) { + size_t len = SSIZE_MAX; + if ((argc-optind) == 5) { soff = strtoull(argv[optind+2], NULL, 10); if (soff == ULLONG_MAX) { fprintf(stderr, "invalid source offset"); @@ -196,10 +216,15 @@ main(int argc, char **argv) fprintf(stderr, "invalid dest offset"); return (1); } - len = strtoull(argv[optind+4], NULL, 10); - if (len == ULLONG_MAX) { - fprintf(stderr, "invalid length"); - return (1); + if (mode == CF_MODE_COPYFILERANGE && + strcmp(argv[optind+4], "all") == 0) { + len = SSIZE_MAX; + } else { + len = strtoull(argv[optind+4], NULL, 10); + if (len == ULLONG_MAX) { + fprintf(stderr, "invalid length"); + return (1); + } } } @@ -237,13 +262,15 @@ main(int argc, char **argv) abort(); } - off_t spos = lseek(sfd, 0, SEEK_CUR); - off_t slen = lseek(sfd, 0, SEEK_END); - off_t dpos = lseek(dfd, 0, SEEK_CUR); - off_t dlen = lseek(dfd, 0, SEEK_END); + if (!quiet) { + off_t spos = lseek(sfd, 0, SEEK_CUR); + off_t slen = lseek(sfd, 0, SEEK_END); + off_t dpos = lseek(dfd, 0, SEEK_CUR); + off_t dlen = lseek(dfd, 0, SEEK_END); - fprintf(stderr, "file offsets: src=%lu/%lu; dst=%lu/%lu\n", spos, slen, - dpos, dlen); + fprintf(stderr, "file offsets: src=%lu/%lu; dst=%lu/%lu\n", + spos, slen, dpos, dlen); + } close(dfd); close(sfd); @@ -254,7 +281,8 @@ main(int argc, char **argv) int do_clone(int sfd, int dfd) { - fprintf(stderr, "using FICLONE\n"); + if (!quiet) + fprintf(stderr, "using FICLONE\n"); int err = ioctl(dfd, CF_FICLONE, sfd); if (err < 0) { fprintf(stderr, "ioctl(FICLONE): %s\n", strerror(errno)); @@ -266,7 +294,8 @@ do_clone(int sfd, int dfd) int do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) { - fprintf(stderr, "using FICLONERANGE\n"); + if (!quiet) + fprintf(stderr, "using FICLONERANGE\n"); cf_file_clone_range_t fcr = { .src_fd = sfd, .src_offset = soff, @@ -284,12 +313,22 @@ do_clonerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) int do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) { - fprintf(stderr, "using copy_file_range\n"); + if (!quiet) + fprintf(stderr, "using copy_file_range\n"); ssize_t copied = cf_copy_file_range(sfd, &soff, dfd, &doff, len, 0); if (copied < 0) { fprintf(stderr, "copy_file_range: %s\n", strerror(errno)); return (1); } + if (len == SSIZE_MAX) { + struct stat sb; + + if (fstat(sfd, &sb) < 0) { + fprintf(stderr, "fstat(sfd): %s\n", strerror(errno)); + return (1); + } + len = sb.st_size; + } if (copied != len) { fprintf(stderr, "copy_file_range: copied less than requested: " "requested=%lu; copied=%lu\n", len, copied); @@ -301,7 +340,8 @@ do_copyfilerange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) int do_deduperange(int sfd, int dfd, loff_t soff, loff_t doff, size_t len) { - fprintf(stderr, "using FIDEDUPERANGE\n"); + if (!quiet) + fprintf(stderr, "using FIDEDUPERANGE\n"); char buf[sizeof (cf_file_dedupe_range_t)+ sizeof (cf_file_dedupe_range_info_t)] = {0}; diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/commands.cfg b/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/commands.cfg index ecb193381bbe..222540c7ac2a 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/commands.cfg +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/commands.cfg @@ -98,7 +98,8 @@ export SYSTEM_FILES_COMMON='awk uname uniq vmstat - wc' + wc + xargs' export SYSTEM_FILES_FREEBSD='chflags compress diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/math.shlib b/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/math.shlib index da1e77e5fb97..2b5e60180f59 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/math.shlib +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/include/math.shlib @@ -123,10 +123,21 @@ function verify_ne # # # $1 lower bound # $2 upper bound +# [$3 how many] function random_int_between { typeset -i min=$1 typeset -i max=$2 + typeset -i count + typeset -i i - echo $(( (RANDOM % (max - min + 1)) + min )) + if [[ -z "$3" ]]; then + count=1 + else + count=$3 + fi + + for (( i = 0; i < $count; i++ )); do + echo $(( (RANDOM % (max - min + 1)) + min )) + done } 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 0a95a4f9f952..31659a1ef44c 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/Makefile.am @@ -90,6 +90,9 @@ nobase_dist_datadir_zfs_tests_tests_DATA += \ functional/alloc_class/alloc_class.kshlib \ functional/atime/atime.cfg \ functional/atime/atime_common.kshlib \ + functional/bclone/bclone.cfg \ + functional/bclone/bclone_common.kshlib \ + functional/bclone/bclone_corner_cases.kshlib \ functional/block_cloning/block_cloning.kshlib \ functional/cache/cache.cfg \ functional/cache/cache.kshlib \ @@ -510,6 +513,24 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/atime/root_atime_on.ksh \ functional/atime/root_relatime_on.ksh \ functional/atime/setup.ksh \ + functional/bclone/bclone_crossfs_corner_cases.ksh \ + functional/bclone/bclone_crossfs_corner_cases_limited.ksh \ + functional/bclone/bclone_crossfs_data.ksh \ + functional/bclone/bclone_crossfs_embedded.ksh \ + functional/bclone/bclone_crossfs_hole.ksh \ + functional/bclone/bclone_diffprops_all.ksh \ + functional/bclone/bclone_diffprops_checksum.ksh \ + functional/bclone/bclone_diffprops_compress.ksh \ + functional/bclone/bclone_diffprops_copies.ksh \ + functional/bclone/bclone_diffprops_recordsize.ksh \ + functional/bclone/bclone_prop_sync.ksh \ + functional/bclone/bclone_samefs_corner_cases.ksh \ + functional/bclone/bclone_samefs_corner_cases_limited.ksh \ + functional/bclone/bclone_samefs_data.ksh \ + functional/bclone/bclone_samefs_embedded.ksh \ + functional/bclone/bclone_samefs_hole.ksh \ + functional/bclone/cleanup.ksh \ + functional/bclone/setup.ksh \ functional/block_cloning/cleanup.ksh \ functional/block_cloning/setup.ksh \ functional/block_cloning/block_cloning_copyfilerange_cross_dataset.ksh \ diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/TODO b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/TODO new file mode 100644 index 000000000000..7cd4ee898fc4 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/TODO @@ -0,0 +1,4 @@ +- If dedup enabled, block_cloning uses dedup. +- check when block cloning doesn't suppose to work +- check block cloning between two different pools +- block cloning from a snapshot diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone.cfg b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone.cfg new file mode 100644 index 000000000000..f72d17c1beca --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone.cfg @@ -0,0 +1,32 @@ +# +# 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 Pawel Jakub Dawidek +# + +# TODO: We should calculate that based on ashift. +export MINBLOCKSIZE=512 + +export TESTSRCFS="$TESTPOOL/$TESTFS/src" +export TESTDSTFS="$TESTPOOL/$TESTFS/dst" +export TESTSRCDIR="$TESTDIR/src" +export TESTDSTDIR="$TESTDIR/dst" diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib new file mode 100644 index 000000000000..beba01c0ed26 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib @@ -0,0 +1,280 @@ +# +# 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 Pawel Jakub Dawidek +# + +. $STF_SUITE/tests/functional/bclone/bclone.cfg + +export RECORDSIZE=$(zfs get -Hp -o value recordsize $TESTPOOL/$TESTFS) + +MINBLKSIZE1=512 +MINBLKSIZE2=1024 + +function verify_block_cloning +{ + if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then + log_unsupported "copy_file_range not available before Linux 4.5" + fi +} + +function verify_crossfs_block_cloning +{ + if is_linux && [[ $(linux_version) -lt $(linux_version "5.3") ]]; then + log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3" + fi +} + +# Unused. +function size_to_dsize +{ + typeset -r size=$1 + typeset -r dir=$2 + + typeset -r dataset=$(df $dir | tail -1 | awk '{print $1}') + typeset -r recordsize=$(get_prop recordsize $dataset) + typeset -r copies=$(get_prop copies $dataset) + typeset dsize + + if [[ $size -le $recordsize ]]; then + dsize=$(( ((size - 1) / MINBLOCKSIZE + 1) * MINBLOCKSIZE )) + else + dsize=$(( ((size - 1) / recordsize + 1) * recordsize )) + fi + dsize=$((dsize*copies)) + + echo $dsize +} + +function test_file_integrity +{ + typeset -r original_checksum=$1 + typeset -r clone=$2 + typeset -r filesize=$3 + + typeset -r clone_checksum=$(sha256digest $clone) + + if [[ $original_checksum != $clone_checksum ]]; then + log_fail "Clone $clone is corrupted with file size $filesize" + fi +} + +function verify_pool_prop_eq +{ + typeset -r prop=$1 + typeset -r expected=$2 + + typeset -r value=$(get_pool_prop $prop $TESTPOOL) + if [[ $value != $expected ]]; then + log_fail "Pool property $prop is incorrect: expected $expected, got $value" + fi +} + +function verify_pool_props +{ + typeset -r dsize=$1 + typeset -r ratio=$2 + + if [[ $dsize -eq 0 ]]; then + verify_pool_prop_eq bcloneused 0 + verify_pool_prop_eq bclonesaved 0 + verify_pool_prop_eq bcloneratio 1.00 + else + if [[ $ratio -eq 1 ]]; then + verify_pool_prop_eq bcloneused 0 + else + verify_pool_prop_eq bcloneused $dsize + fi + verify_pool_prop_eq bclonesaved $((dsize*(ratio-1))) + verify_pool_prop_eq bcloneratio "${ratio}.00" + fi +} + +# Function to test file copying and integrity check. +function bclone_test +{ + typeset -r datatype=$1 + typeset filesize=$2 + typeset -r embedded=$3 + typeset -r srcdir=$4 + typeset -r dstdir=$5 + typeset dsize + + typeset -r original="${srcdir}/original" + typeset -r clone="${dstdir}/clone" + + log_note "Testing file copy with datatype $datatype, file size $filesize, embedded $embedded" + + # Create a test file with known content. + case $datatype in + random|text) + sync_pool $TESTPOOL + if [[ $datatype = "random" ]]; then + dd if=/dev/urandom of=$original bs=$filesize count=1 2>/dev/null + else + filesize=$(((filesize/4)*4)) + dd if=/dev/urandom bs=$(((filesize/4)*3)) count=1 | \ + openssl base64 -A > $original + fi + sync_pool $TESTPOOL + clonefile -f $original "${clone}-tmp" + sync_pool $TESTPOOL + # It is hard to predict block sizes that will be used, + # so just do one clone and take it from bcloneused. + filesize=$(zpool get -Hp -o value bcloneused $TESTPOOL) + if [[ $embedded = "false" ]]; then + log_must test $filesize -gt 0 + fi + rm -f "${clone}-tmp" + sync_pool $TESTPOOL + dsize=$filesize + ;; + hole) + log_must truncate_test -s $filesize -f $original + dsize=0 + ;; + *) + log_fail "Unknown datatype $datatype" + ;; + esac + if [[ $embedded = "true" ]]; then + dsize=0 + fi + + typeset -r original_checksum=$(sha256digest $original) + + sync_pool $TESTPOOL + + # Create a first clone of the entire file. + clonefile -f $original "${clone}0" + # Try to clone the clone in the same transaction group. + clonefile -f "${clone}0" "${clone}2" + + # Clone the original again... + clonefile -f $original "${clone}1" + # ...and overwrite it in the same transaction group. + clonefile -f $original "${clone}1" + + # Clone the clone... + clonefile -f "${clone}1" "${clone}3" + sync_pool $TESTPOOL + # ...and overwrite in the new transaction group. + clonefile -f "${clone}1" "${clone}3" + + sync_pool $TESTPOOL + + # Test removal of the pending clones (before they are committed to disk). + clonefile -f $original "${clone}4" + clonefile -f "${clone}4" "${clone}5" + rm -f "${clone}4" "${clone}5" + + # Clone into one file, but remove another file, but with the same data in + # the same transaction group. + clonefile -f $original "${clone}5" + sync_pool $TESTPOOL + clonefile -f $original "${clone}4" + rm -f "${clone}5" + test_file_integrity $original_checksum "${clone}4" $filesize + sync_pool $TESTPOOL + test_file_integrity $original_checksum "${clone}4" $filesize + + clonefile -f "${clone}4" "${clone}5" + # Verify integrity of the cloned file before it is committed to disk. + test_file_integrity $original_checksum "${clone}5" $filesize + + sync_pool $TESTPOOL + + # Verify integrity in the new transaction group. + test_file_integrity $original_checksum "${clone}0" $filesize + test_file_integrity $original_checksum "${clone}1" $filesize + test_file_integrity $original_checksum "${clone}2" $filesize + test_file_integrity $original_checksum "${clone}3" $filesize + test_file_integrity $original_checksum "${clone}4" $filesize + test_file_integrity $original_checksum "${clone}5" $filesize + + verify_pool_props $dsize 7 + + # Clear cache and test after fresh import. + log_must zpool export $TESTPOOL + log_must zpool import $TESTPOOL + + # Cloned uncached file. + clonefile -f $original "${clone}6" + # Cloned uncached clone. + clonefile -f "${clone}6" "${clone}7" + + # Cache the file. + cat $original >/dev/null + clonefile -f $original "${clone}8" + clonefile -f "${clone}8" "${clone}9" + + test_file_integrity $original_checksum "${clone}6" $filesize + test_file_integrity $original_checksum "${clone}7" $filesize + test_file_integrity $original_checksum "${clone}8" $filesize + test_file_integrity $original_checksum "${clone}9" $filesize + + sync_pool $TESTPOOL + + verify_pool_props $dsize 11 + + log_must zpool export $TESTPOOL + log_must zpool import $TESTPOOL + + test_file_integrity $original_checksum "${clone}0" $filesize + test_file_integrity $original_checksum "${clone}1" $filesize + test_file_integrity $original_checksum "${clone}2" $filesize + test_file_integrity $original_checksum "${clone}3" $filesize + test_file_integrity $original_checksum "${clone}4" $filesize + test_file_integrity $original_checksum "${clone}5" $filesize + test_file_integrity $original_checksum "${clone}6" $filesize + test_file_integrity $original_checksum "${clone}7" $filesize + test_file_integrity $original_checksum "${clone}8" $filesize + test_file_integrity $original_checksum "${clone}9" $filesize + + rm -f $original + rm -f "${clone}1" "${clone}3" "${clone}5" "${clone}7" + + sync_pool $TESTPOOL + + test_file_integrity $original_checksum "${clone}0" $filesize + test_file_integrity $original_checksum "${clone}2" $filesize + test_file_integrity $original_checksum "${clone}4" $filesize + test_file_integrity $original_checksum "${clone}6" $filesize + test_file_integrity $original_checksum "${clone}8" $filesize + test_file_integrity $original_checksum "${clone}9" $filesize + + verify_pool_props $dsize 6 + + rm -f "${clone}0" "${clone}2" "${clone}4" "${clone}8" "${clone}9" + + sync_pool $TESTPOOL + + test_file_integrity $original_checksum "${clone}6" $filesize + + verify_pool_props $dsize 1 + + rm -f "${clone}6" + + sync_pool $TESTPOOL + + verify_pool_props $dsize 1 +} diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib new file mode 100644 index 000000000000..ddfbfc999c4e --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_corner_cases.kshlib @@ -0,0 +1,315 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +function first_half_checksum +{ + typeset -r file=$1 + + dd if=$file bs=$HALFRECORDSIZE count=1 2>/dev/null | sha256digest +} + +function second_half_checksum +{ + typeset -r file=$1 + + dd if=$file bs=$HALFRECORDSIZE count=1 skip=1 2>/dev/null | sha256digest +} + +function bclone_corner_cases_init +{ + typeset -r srcdir=$1 + typeset -r dstdir=$2 + + export RECORDSIZE=4096 + export HALFRECORDSIZE=$((RECORDSIZE / 2)) + + export CLONE="$dstdir/clone0" + export ORIG0="$srcdir/orig0" + export ORIG1="$srcdir/orig1" + export ORIG2="$srcdir/orig2" + + # Create source files. + log_must dd if=/dev/urandom of="$ORIG0" bs=$RECORDSIZE count=1 + log_must dd if=/dev/urandom of="$ORIG1" bs=$RECORDSIZE count=1 + log_must dd if=/dev/urandom of="$ORIG2" bs=$RECORDSIZE count=1 + + export FIRST_HALF_ORIG0_CHECKSUM=$(first_half_checksum $ORIG0) + export FIRST_HALF_ORIG1_CHECKSUM=$(first_half_checksum $ORIG1) + export FIRST_HALF_ORIG2_CHECKSUM=$(first_half_checksum $ORIG2) + export SECOND_HALF_ORIG0_CHECKSUM=$(second_half_checksum $ORIG0) + export SECOND_HALF_ORIG1_CHECKSUM=$(second_half_checksum $ORIG1) + export SECOND_HALF_ORIG2_CHECKSUM=$(second_half_checksum $ORIG2) + export ZEROS_CHECKSUM=$(dd if=/dev/zero bs=$HALFRECORDSIZE count=1 | sha256digest) + export FIRST_HALF_CHECKSUM="" + export SECOND_HALF_CHECKSUM="" +} + +function cache_clone +{ + typeset -r cached=$1 + + case "$cached" in + "cached") + dd if=$CLONE of=/dev/null bs=$RECORDSIZE 2>/dev/null + ;; + "uncached") + ;; + *) + log_fail "invalid cached: $cached" + ;; + esac +} + +function create_existing +{ + typeset -r existing=$1 + + case "$existing" in + "no") + ;; + "small empty") + log_must truncate_test -s $HALFRECORDSIZE -f $CLONE + ;; + "full empty") + log_must truncate_test -s $RECORDSIZE -f $CLONE + ;; + "small data") + log_must dd if=/dev/urandom of=$CLONE bs=$HALFRECORDSIZE count=1 \ + 2>/dev/null + ;; + "full data") + log_must dd if=/dev/urandom of=$CLONE bs=$RECORDSIZE count=1 2>/dev/null + ;; + *) + log_fail "invalid existing: $existing" + ;; + esac +} + +function create_clone +{ + typeset -r clone=$1 + typeset -r file=$2 + + case "$clone" in + "no") + ;; + "yes") + clonefile -f $file $CLONE + case "$file" in + $ORIG0) + FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG0_CHECKSUM + SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG0_CHECKSUM + ;; + $ORIG2) + FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG2_CHECKSUM + SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG2_CHECKSUM + ;; + *) + log_fail "invalid file: $file" + ;; + esac + ;; + *) + log_fail "invalid clone: $clone" + ;; + esac +} + +function overwrite_clone +{ + typeset -r overwrite=$1 + + case "$overwrite" in + "no") + ;; + "free") + log_must truncate_test -s 0 -f $CLONE + log_must truncate_test -s $RECORDSIZE -f $CLONE + FIRST_HALF_CHECKSUM=$ZEROS_CHECKSUM + SECOND_HALF_CHECKSUM=$ZEROS_CHECKSUM + ;; + "full") + log_must dd if=$ORIG1 of=$CLONE bs=$RECORDSIZE count=1 2>/dev/null + FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG1_CHECKSUM + SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG1_CHECKSUM + ;; + "first half") + log_must dd if=$ORIG1 of=$CLONE bs=$HALFRECORDSIZE skip=0 seek=0 \ + count=1 conv=notrunc 2>/dev/null + FIRST_HALF_CHECKSUM=$FIRST_HALF_ORIG1_CHECKSUM + ;; + "second half") + log_must dd if=$ORIG1 of=$CLONE bs=$HALFRECORDSIZE skip=1 seek=1 \ + count=1 conv=notrunc 2>/dev/null + SECOND_HALF_CHECKSUM=$SECOND_HALF_ORIG1_CHECKSUM + ;; + *) + log_fail "invalid overwrite: $overwrite" + ;; + esac +} + +function checksum_compare +{ + typeset -r compare=$1 + typeset first_half_calculated_checksum second_half_calculated_checksum + + case "$compare" in + "no") + ;; + "yes") + first_half_calculated_checksum=$(first_half_checksum $CLONE) + second_half_calculated_checksum=$(second_half_checksum $CLONE) + + if [[ $first_half_calculated_checksum != $FIRST_HALF_CHECKSUM ]] || \ + [[ $second_half_calculated_checksum != $SECOND_HALF_CHECKSUM ]]; then + return 1 + fi + ;; + *) + log_fail "invalid compare: $compare" + ;; + esac +} + +function bclone_corner_cases_test +{ + typeset cached existing + typeset first_clone first_overwrite + typeset read_after read_before + typeset second_clone second_overwrite + typeset -r srcdir=$1 + typeset -r dstdir=$2 + typeset limit=$3 + typeset -i count=0 + + if [[ $srcdir != "count" ]]; then + if [[ -n "$limit" ]]; then + typeset -r total_count=$(bclone_corner_cases_test count) + limit=$(random_int_between 1 $total_count $((limit*2)) | sort -nu | head -n $limit | xargs) + fi + bclone_corner_cases_init $srcdir $dstdir + fi + + # + # (create) / (cache) / (clone) / (overwrite) / (read) / (clone) / (overwrite) / (read) / read next txg + # + for existing in "no" "small empty" "full empty" "small data" "full data"; do + for cached in "uncached" "cached"; do + for first_clone in "no" "yes"; do + for first_overwrite in "no" "free" "full" "first half" "second half"; do + for read_before in "no" "yes"; do + for second_clone in "no" "yes"; do + for second_overwrite in "no" "free" "full" "first half" "second half"; do + for read_after in "no" "yes"; do + if [[ $first_clone = "no" ]] && \ + [[ $second_clone = "no" ]]; then + continue + fi + if [[ $first_clone = "no" ]] && \ + [[ $read_before = "yes" ]]; then + continue + fi + if [[ $second_clone = "no" ]] && \ + [[ $read_before = "yes" ]] && \ + [[ $read_after = "yes" ]]; then + continue + fi + + count=$((count+1)) + + if [[ $srcdir = "count" ]]; then + # Just counting. + continue + fi + + if [[ -n "$limit" ]]; then + if ! echo " $limit " | grep -q " $count "; then + continue + fi + fi + + FIRST_HALF_CHECKSUM="" + SECOND_HALF_CHECKSUM="" + + log_must zpool export $TESTPOOL + log_must zpool import $TESTPOOL + + create_existing "$existing" + + log_must zpool export $TESTPOOL + log_must zpool import $TESTPOOL + + cache_clone "$cached" + + create_clone "$first_clone" "$ORIG0" + + overwrite_clone "$first_overwrite" + + if checksum_compare $read_before; then + log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before" + else + log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before" + fi + + create_clone "$second_clone" "$ORIG2" + + overwrite_clone "$second_overwrite" + + if checksum_compare $read_after; then + log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / read_after: $read_after" + else + log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / read_after: $read_after" + fi + + log_must zpool export $TESTPOOL + log_must zpool import $TESTPOOL + + if checksum_compare "yes"; then + log_note "existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / read_after: $read_after / read_next_txg" + else + log_fail "FAIL: existing: $existing / cached: $cached / first_clone: $first_clone / first_overwrite: $first_overwrite / read_before: $read_before / second_clone: $second_clone / read_after: $read_after / read_next_txg" + fi + + rm -f "$CLONE" + done + done + done + done + done + done + done + done + + if [[ $srcdir = "count" ]]; then + echo $count + fi +} diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh new file mode 100755 index 000000000000..35188cddb063 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases.ksh @@ -0,0 +1,45 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify various corner cases in block cloning across datasets" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS +log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS +log_must zfs set recordsize=$RECORDSIZE $TESTDSTFS + +bclone_corner_cases_test $TESTSRCDIR $TESTDSTDIR + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh new file mode 100755 index 000000000000..1fc1bbd07fd9 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_corner_cases_limited.ksh @@ -0,0 +1,45 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify various corner cases in block cloning across datasets" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS +log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS +log_must zfs set recordsize=$RECORDSIZE $TESTDSTFS + +bclone_corner_cases_test $TESTSRCDIR $TESTDSTDIR 100 + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh new file mode 100755 index 000000000000..e2fe25d451dd --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_data.ksh @@ -0,0 +1,46 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning properly clones regular files across datasets" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS + +for filesize in 1 107 113 511 512 513 4095 4096 4097 131071 131072 131073 \ + 1048575 1048576 1048577 4194303 4194304 4194305; do + bclone_test random $filesize false $TESTSRCDIR $TESTDSTDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh new file mode 100755 index 000000000000..6a6fe1d309a9 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_embedded.ksh @@ -0,0 +1,50 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning properly clones small files (with embedded blocks) across datasets" + +# Enable ZLE compression to make sure what is the maximum amount of data we +# can store in BP. +log_must zfs set compress=zle $TESTSRCFS +log_must zfs set compress=zle $TESTDSTFS + +# Test BP_IS_EMBEDDED(). +# Maximum embedded payload size is 112 bytes, but the buffer is extended to +# 512 bytes first and then compressed. 107 random bytes followed by 405 zeros +# gives exactly 112 bytes after compression with ZLE. +for filesize in 1 2 4 8 16 32 64 96 107; do + bclone_test random $filesize true $TESTSRCDIR $TESTDSTDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh new file mode 100755 index 000000000000..d4c33d6da30f --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_crossfs_hole.ksh @@ -0,0 +1,45 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning properly clones sparse files (files with holes) across datasets" + +# Compression doesn't matter here. + +# Test BP_IS_HOLE(). +for filesize in 1 511 512 513 4095 4096 4097 131071 131072 131073 \ + 1048575 1048576 1048577 4194303 4194304 4194305; do + bclone_test hole $filesize false $TESTSRCDIR $TESTDSTDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh new file mode 100755 index 000000000000..a5e7282fe6a8 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_all.ksh @@ -0,0 +1,86 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning across datasets with different properties" + +log_must zfs set checksum=off $TESTSRCFS +log_must zfs set compress=off $TESTSRCFS +log_must zfs set copies=1 $TESTSRCFS +log_must zfs set recordsize=131072 $TESTSRCFS +log_must zfs set checksum=fletcher2 $TESTDSTFS +log_must zfs set compress=lz4 $TESTDSTFS +log_must zfs set copies=3 $TESTDSTFS +log_must zfs set recordsize=8192 $TESTDSTFS + +FILESIZE=$(random_int_between 2 32767) +FILESIZE=$((FILESIZE * 64)) +bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR + +log_must zfs set checksum=sha256 $TESTSRCFS +log_must zfs set compress=zstd $TESTSRCFS +log_must zfs set copies=2 $TESTSRCFS +log_must zfs set recordsize=262144 $TESTSRCFS +log_must zfs set checksum=off $TESTDSTFS +log_must zfs set compress=off $TESTDSTFS +log_must zfs set copies=1 $TESTDSTFS +log_must zfs set recordsize=131072 $TESTDSTFS + +FILESIZE=$(random_int_between 2 32767) +FILESIZE=$((FILESIZE * 64)) +bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR + +log_must zfs set checksum=sha512 $TESTSRCFS +log_must zfs set compress=gzip $TESTSRCFS +log_must zfs set copies=2 $TESTSRCFS +log_must zfs set recordsize=512 $TESTSRCFS +log_must zfs set checksum=fletcher4 $TESTDSTFS +log_must zfs set compress=lzjb $TESTDSTFS +log_must zfs set copies=3 $TESTDSTFS +log_must zfs set recordsize=16384 $TESTDSTFS + +FILESIZE=$(random_int_between 2 32767) +FILESIZE=$((FILESIZE * 64)) +bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR + +log_must zfs inherit checksum $TESTSRCFS +log_must zfs inherit compress $TESTSRCFS +log_must zfs inherit copies $TESTSRCFS +log_must zfs inherit recordsize $TESTSRCFS +log_must zfs inherit checksum $TESTDSTFS +log_must zfs inherit compress $TESTDSTFS +log_must zfs inherit copies $TESTDSTFS +log_must zfs inherit recordsize $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh new file mode 100755 index 000000000000..7e064a0dfd73 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_checksum.ksh @@ -0,0 +1,62 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/include/properties.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning across datasets with different checksum properties" + +log_must zfs set compress=off $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS + +for srcprop in "${checksum_prop_vals[@]}"; do + for dstprop in "${checksum_prop_vals[@]}"; do + if [[ $srcprop == $dstprop ]]; then + continue + fi + log_must zfs set checksum=$srcprop $TESTSRCFS + log_must zfs set checksum=$dstprop $TESTDSTFS + # 15*8=120, which is greater than 113, so we are sure the data won't + # be embedded into BP. + # 32767*8=262136, which is larger than a single default recordsize of + # 131072. + FILESIZE=$(random_int_between 15 32767) + FILESIZE=$((FILESIZE * 8)) + bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR + done +done + +log_must zfs inherit checksum $TESTSRCFS +log_must zfs inherit checksum $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh new file mode 100755 index 000000000000..e1d6e5949218 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_compress.ksh @@ -0,0 +1,59 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/include/properties.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning across datasets with different compression properties" + +for srcprop in "${compress_prop_vals[@]}"; do + for dstprop in "${compress_prop_vals[@]}"; do + if [[ $srcprop == $dstprop ]]; then + continue + fi + log_must zfs set compress=$srcprop $TESTSRCFS + log_must zfs set compress=$dstprop $TESTDSTFS + # 15*8=120, which is greater than 113, so we are sure the data won't + # be embedded into BP. + # 32767*8=262136, which is larger than a single default recordsize of + # 131072. + FILESIZE=$(random_int_between 15 32767) + FILESIZE=$((FILESIZE * 8)) + bclone_test text $FILESIZE false $TESTSRCDIR $TESTDSTDIR + done +done + +log_must zfs inherit compress $TESTSRCFS +log_must zfs inherit compress $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh new file mode 100755 index 000000000000..ac823e1ec394 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_copies.ksh @@ -0,0 +1,59 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/include/properties.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning across datasets with different copies properties" + +log_must zfs set compress=off $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS + +for srcprop in "${copies_prop_vals[@]}"; do + for dstprop in "${copies_prop_vals[@]}"; do + log_must zfs set copies=$srcprop $TESTSRCFS + log_must zfs set copies=$dstprop $TESTDSTFS + # 15*8=120, which is greater than 113, so we are sure the data won't + # be embedded into BP. + # 32767*8=262136, which is larger than a single default recordsize of + # 131072. + FILESIZE=$(random_int_between 15 32767) + FILESIZE=$((FILESIZE * 8)) + bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR + done +done + +log_must zfs inherit copies $TESTSRCFS +log_must zfs inherit copies $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh new file mode 100755 index 000000000000..d833e6123106 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_diffprops_recordsize.ksh @@ -0,0 +1,65 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/include/properties.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning across datasets with different recordsize properties" + +log_must zfs set compress=off $TESTSRCFS +log_must zfs set compress=off $TESTDSTFS + +# recsize_prop_vals[] array contains too many entries and the tests take too +# long. Let's use only a subset of them. +typeset -a bclone_recsize_prop_vals=('512' '4096' '131072' '1048576') + +for srcprop in "${bclone_recsize_prop_vals[@]}"; do + for dstprop in "${bclone_recsize_prop_vals[@]}"; do + if [[ $srcprop == $dstprop ]]; then + continue + fi + log_must zfs set recordsize=$srcprop $TESTSRCFS + log_must zfs set recordsize=$dstprop $TESTDSTFS + # 2*64=128, which is greater than 113, so we are sure the data won't + # be embedded into BP. + # 32767*64=2097088, which is larger than the largest recordsize (1MB). + FILESIZE=$(random_int_between 2 32767) + FILESIZE=$((FILESIZE * 64)) + bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR + done +done + +log_must zfs inherit recordsize $TESTSRCFS +log_must zfs inherit recordsize $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh new file mode 100755 index 000000000000..f8aa1c875c60 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_prop_sync.ksh @@ -0,0 +1,66 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/include/math.shlib +. $STF_SUITE/include/properties.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning +verify_crossfs_block_cloning + +log_assert "Verify block cloning with all sync property settings" + +log_must zfs set compress=zle $TESTSRCFS +log_must zfs set compress=zle $TESTDSTFS + +for prop in "${sync_prop_vals[@]}"; do + log_must zfs set sync=$prop $TESTSRCFS + # 32767*8=262136, which is larger than a single default recordsize of + # 131072. + FILESIZE=$(random_int_between 1 32767) + FILESIZE=$((FILESIZE * 8)) + bclone_test random $FILESIZE false $TESTSRCDIR $TESTSRCDIR +done + +for srcprop in "${sync_prop_vals[@]}"; do + log_must zfs set sync=$srcprop $TESTSRCFS + for dstprop in "${sync_prop_vals[@]}"; do + log_must zfs set sync=$dstprop $TESTDSTFS + # 32767*8=262136, which is larger than a single default recordsize of + # 131072. + FILESIZE=$(random_int_between 1 32767) + FILESIZE=$((FILESIZE * 8)) + bclone_test random $FILESIZE false $TESTSRCDIR $TESTDSTDIR + done +done + +log_must zfs inherit sync $TESTSRCFS +log_must zfs inherit sync $TESTDSTFS + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh new file mode 100755 index 000000000000..4aa2914da299 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases.ksh @@ -0,0 +1,42 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib + +verify_runnable "both" + +verify_block_cloning + +log_assert "Verify various corner cases in block cloning within the same dataset" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS +log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS + +bclone_corner_cases_test $TESTSRCDIR $TESTSRCDIR + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh new file mode 100755 index 000000000000..b4737700eb7d --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_corner_cases_limited.ksh @@ -0,0 +1,42 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_corner_cases.kshlib + +verify_runnable "both" + +verify_block_cloning + +log_assert "Verify various corner cases in block cloning within the same dataset" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS +log_must zfs set recordsize=$RECORDSIZE $TESTSRCFS + +bclone_corner_cases_test $TESTSRCDIR $TESTSRCDIR 100 + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh new file mode 100755 index 000000000000..e964f7bbf641 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_data.ksh @@ -0,0 +1,44 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning + +log_assert "Verify block cloning properly clones regular files within the same dataset" + +# Disable compression to make sure we won't use embedded blocks. +log_must zfs set compress=off $TESTSRCFS + +for filesize in 1 107 113 511 512 513 4095 4096 4097 131071 131072 131073 \ + 1048575 1048576 1048577 4194303 4194304 4194305; do + bclone_test random $filesize false $TESTSRCDIR $TESTSRCDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh new file mode 100755 index 000000000000..df393a878015 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_embedded.ksh @@ -0,0 +1,48 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning + +log_assert "Verify block cloning properly clones small files (with embedded blocks) within the same dataset" + +# Enable ZLE compression to make sure what is the maximum amount of data we +# can store in BP. +log_must zfs set compress=zle $TESTSRCFS + +# Test BP_IS_EMBEDDED(). +# Maximum embedded payload size is 112 bytes, but the buffer is extended to +# 512 bytes first and then compressed. 107 random bytes followed by 405 zeros +# gives exactly 112 bytes after compression with ZLE. +for filesize in 1 2 4 8 16 32 64 96 107; do + bclone_test random $filesize true $TESTSRCDIR $TESTSRCDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh new file mode 100755 index 000000000000..3c6e345e6e64 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/bclone_samefs_hole.ksh @@ -0,0 +1,44 @@ +#! /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 Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib + +verify_runnable "both" + +verify_block_cloning + +log_assert "Verify block cloning properly clones sparse files (files with holes) within the same dataset" + +# Compression doesn't matter here. + +# Test BP_IS_HOLE(). +for filesize in 1 511 512 513 4095 4096 4097 131071 131072 131073 \ + 1048575 1048576 1048577 4194303 4194304 4194305; do + bclone_test hole $filesize false $TESTSRCDIR $TESTSRCDIR +done + +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/cleanup.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/cleanup.ksh new file mode 100755 index 000000000000..df6d9c08fece --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/cleanup.ksh @@ -0,0 +1,37 @@ +#!/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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2013 by Delphix. All rights reserved. +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone.cfg + +log_must zfs destroy $TESTSRCFS +log_must zfs destroy $TESTDSTFS +default_cleanup diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/setup.ksh b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/setup.ksh new file mode 100755 index 000000000000..c68719ee72a2 --- /dev/null +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/bclone/setup.ksh @@ -0,0 +1,45 @@ +#!/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 2007 Sun Microsystems, Inc. All rights reserved. +# Use is subject to license terms. +# + +# +# Copyright (c) 2023 by Pawel Jakub Dawidek +# + +. $STF_SUITE/include/libtest.shlib +. $STF_SUITE/tests/functional/bclone/bclone.cfg + +if ! command -v clonefile > /dev/null ; then + log_unsupported "clonefile program required to test block cloning" +fi + +DISK=${DISKS%% *} + +default_setup_noexit $DISK "true" +log_must zpool set feature@block_cloning=enabled $TESTPOOL +log_must zfs create $TESTSRCFS +log_must zfs create $TESTDSTFS +log_pass diff --git a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib index 30818050a07a..297c6a073bb9 100644 --- a/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib +++ b/sys/contrib/subrepo-openzfs/tests/zfs-tests/tests/functional/redundancy/redundancy.kshlib @@ -44,28 +44,6 @@ function cleanup done } -# -# Get random number between min and max number. -# -# $1 Minimal value -# $2 Maximal value -# -function random -{ - typeset -i min=$1 - typeset -i max=$2 - typeset -i value - - while true; do - ((value = RANDOM % (max + 1))) - if ((value >= min)); then - break - fi - done - - echo $value -} - # # Get the number of checksum errors for the pool. #