mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-04-28 13:20:02 +00:00
Fix false assertion in dmu_tx_dirty_buf() on cloning
Same as writes block cloning can increase block size and number of indirection levels. That means it can dirty block 0 at level 0 or at new top indirection level without explicitly holding them. A block cloning test case for large offsets has been added. Reviewed-by: Rob Norris <robn@despairlabs.com> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Co-authored-by: Ameer Hamza <ahamza@ixsystems.com> Signed-off-by: Alexander Motin <mav@FreeBSD.org> Sponsored by: iXsystems, Inc. Closes #16825
This commit is contained in:
parent
44446dccdb
commit
e8b333e4d3
@ -800,6 +800,14 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
|
||||
case THT_CLONE:
|
||||
if (blkid >= beginblk && blkid <= endblk)
|
||||
match_offset = TRUE;
|
||||
/*
|
||||
* They might have to increase nlevels,
|
||||
* thus dirtying the new TLIBs. Or the
|
||||
* might have to change the block size,
|
||||
* thus dirying the new lvl=0 blk=0.
|
||||
*/
|
||||
if (blkid == 0)
|
||||
match_offset = TRUE;
|
||||
break;
|
||||
default:
|
||||
cmn_err(CE_PANIC, "bad txh_type %d",
|
||||
|
@ -82,7 +82,7 @@ tests = ['block_cloning_clone_mmap_cached',
|
||||
'block_cloning_copyfilerange_fallback_same_txg',
|
||||
'block_cloning_replay', 'block_cloning_replay_encrypted',
|
||||
'block_cloning_lwb_buffer_overflow', 'block_cloning_clone_mmap_write',
|
||||
'block_cloning_rlimit_fsize']
|
||||
'block_cloning_rlimit_fsize', 'block_cloning_large_offset']
|
||||
tags = ['functional', 'block_cloning']
|
||||
|
||||
[tests/functional/bootfs]
|
||||
|
@ -339,6 +339,8 @@ elif sys.platform.startswith('linux'):
|
||||
['SKIP', cfr_reason],
|
||||
'block_cloning/block_cloning_rlimit_fsize':
|
||||
['SKIP', cfr_reason],
|
||||
'block_cloning/block_cloning_large_offset':
|
||||
['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],
|
||||
'cp_files/cp_files_002_pos': ['SKIP', cfr_reason],
|
||||
|
@ -482,6 +482,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
|
||||
functional/block_cloning/block_cloning_replay_encrypted.ksh \
|
||||
functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh \
|
||||
functional/block_cloning/block_cloning_rlimit_fsize.ksh \
|
||||
functional/block_cloning/block_cloning_large_offset.ksh \
|
||||
functional/bootfs/bootfs_001_pos.ksh \
|
||||
functional/bootfs/bootfs_002_neg.ksh \
|
||||
functional/bootfs/bootfs_003_pos.ksh \
|
||||
|
@ -0,0 +1,83 @@
|
||||
#!/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 that cloning a file at a large offset is possible.
|
||||
#
|
||||
# STRATEGY:
|
||||
# 1. Create dataset.
|
||||
# 2. Populate the source file with 1024 blocks at 1024 block offset.
|
||||
# 3. Clone 1024 blocks at a 1024-block offset.
|
||||
# 4. Compare the cloned file with the original file.
|
||||
#
|
||||
|
||||
verify_runnable "global"
|
||||
|
||||
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
|
||||
log_unsupported "copy_file_range not available before Linux 4.5"
|
||||
fi
|
||||
|
||||
claim="The first clone at a large offset is functional"
|
||||
|
||||
log_assert $claim
|
||||
|
||||
function cleanup
|
||||
{
|
||||
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
|
||||
}
|
||||
|
||||
log_onexit cleanup
|
||||
|
||||
#
|
||||
# 1. Create dataset.
|
||||
#
|
||||
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
|
||||
sync_pool $TESTPOOL
|
||||
|
||||
#
|
||||
# 2. Populate the source file with 1024 blocks at 1024 block offset.
|
||||
#
|
||||
log_must dd if=/dev/urandom of=/$TESTPOOL/file1 \
|
||||
oflag=sync bs=128k count=1024 seek=1024
|
||||
sync_pool $TESTPOOL
|
||||
|
||||
#
|
||||
# 3. Clone 1024 blocks at a 1024-block offset.
|
||||
#
|
||||
log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 134217728 134217728 \
|
||||
134217728
|
||||
sync_pool $TESTPOOL
|
||||
|
||||
#
|
||||
# 4. Compare the cloned file with the original file.
|
||||
#
|
||||
log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
|
||||
typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
|
||||
|
||||
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
|
||||
log_must [ "$blocks" = "$(seq -s " " 0 1023 | sed 's/ $//')" ]
|
||||
|
||||
log_pass $claim
|
Loading…
Reference in New Issue
Block a user