Skip to content

Commit f54052a

Browse files
amotinixhamza
authored andcommitted
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 <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Co-authored-by: Ameer Hamza <[email protected]> Signed-off-by: Alexander Motin <[email protected]> Sponsored by: iXsystems, Inc. Closes openzfs#16825
1 parent d874f27 commit f54052a

File tree

5 files changed

+95
-1
lines changed

5 files changed

+95
-1
lines changed

module/zfs/dmu_tx.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -800,6 +800,14 @@ dmu_tx_dirty_buf(dmu_tx_t *tx, dmu_buf_impl_t *db)
800800
case THT_CLONE:
801801
if (blkid >= beginblk && blkid <= endblk)
802802
match_offset = TRUE;
803+
/*
804+
* They might have to increase nlevels,
805+
* thus dirtying the new TLIBs. Or the
806+
* might have to change the block size,
807+
* thus dirying the new lvl=0 blk=0.
808+
*/
809+
if (blkid == 0)
810+
match_offset = TRUE;
803811
break;
804812
default:
805813
cmn_err(CE_PANIC, "bad txh_type %d",

tests/runfiles/common.run

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ tests = ['block_cloning_clone_mmap_cached',
8282
'block_cloning_copyfilerange_fallback_same_txg',
8383
'block_cloning_replay', 'block_cloning_replay_encrypted',
8484
'block_cloning_lwb_buffer_overflow', 'block_cloning_clone_mmap_write',
85-
'block_cloning_rlimit_fsize']
85+
'block_cloning_rlimit_fsize', 'block_cloning_large_offset']
8686
tags = ['functional', 'block_cloning']
8787

8888
[tests/functional/bootfs]

tests/test-runner/bin/zts-report.py.in

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,8 @@ elif sys.platform.startswith('linux'):
339339
['SKIP', cfr_reason],
340340
'block_cloning/block_cloning_rlimit_fsize':
341341
['SKIP', cfr_reason],
342+
'block_cloning/block_cloning_large_offset':
343+
['SKIP', cfr_reason],
342344
'cli_root/zfs_rename/zfs_rename_002_pos': ['FAIL', known_reason],
343345
'cli_root/zpool_reopen/zpool_reopen_003_pos': ['FAIL', known_reason],
344346
'cp_files/cp_files_002_pos': ['SKIP', cfr_reason],

tests/zfs-tests/tests/Makefile.am

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
482482
functional/block_cloning/block_cloning_replay_encrypted.ksh \
483483
functional/block_cloning/block_cloning_lwb_buffer_overflow.ksh \
484484
functional/block_cloning/block_cloning_rlimit_fsize.ksh \
485+
functional/block_cloning/block_cloning_large_offset.ksh \
485486
functional/bootfs/bootfs_001_pos.ksh \
486487
functional/bootfs/bootfs_002_neg.ksh \
487488
functional/bootfs/bootfs_003_pos.ksh \
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#!/bin/ksh -p
2+
#
3+
# CDDL HEADER START
4+
#
5+
# The contents of this file are subject to the terms of the
6+
# Common Development and Distribution License (the "License").
7+
# You may not use this file except in compliance with the License.
8+
#
9+
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10+
# or https://opensource.org/licenses/CDDL-1.0.
11+
# See the License for the specific language governing permissions
12+
# and limitations under the License.
13+
#
14+
# When distributing Covered Code, include this CDDL HEADER in each
15+
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16+
# If applicable, add the following below this CDDL HEADER, with the
17+
# fields enclosed by brackets "[]" replaced with your own identifying
18+
# information: Portions Copyright [yyyy] [name of copyright owner]
19+
#
20+
# CDDL HEADER END
21+
#
22+
23+
. $STF_SUITE/include/libtest.shlib
24+
. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib
25+
26+
#
27+
# DESCRIPTION:
28+
# Verify that cloning a file at a large offset is possible.
29+
#
30+
# STRATEGY:
31+
# 1. Create dataset.
32+
# 2. Populate the source file with 1024 blocks at 1024 block offset.
33+
# 3. Clone 1024 blocks at a 1024-block offset.
34+
# 4. Compare the cloned file with the original file.
35+
#
36+
37+
verify_runnable "global"
38+
39+
if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
40+
log_unsupported "copy_file_range not available before Linux 4.5"
41+
fi
42+
43+
claim="The first clone at a large offset is functional"
44+
45+
log_assert $claim
46+
47+
function cleanup
48+
{
49+
datasetexists $TESTPOOL && destroy_pool $TESTPOOL
50+
}
51+
52+
log_onexit cleanup
53+
54+
#
55+
# 1. Create dataset.
56+
#
57+
log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS
58+
sync_pool $TESTPOOL
59+
60+
#
61+
# 2. Populate the source file with 1024 blocks at 1024 block offset.
62+
#
63+
log_must dd if=/dev/urandom of=/$TESTPOOL/file1 \
64+
oflag=sync bs=128k count=1024 seek=1024
65+
sync_pool $TESTPOOL
66+
67+
#
68+
# 3. Clone 1024 blocks at a 1024-block offset.
69+
#
70+
log_must clonefile -f /$TESTPOOL/file1 /$TESTPOOL/file2 134217728 134217728 \
71+
134217728
72+
sync_pool $TESTPOOL
73+
74+
#
75+
# 4. Compare the cloned file with the original file.
76+
#
77+
log_must have_same_content /$TESTPOOL/file1 /$TESTPOOL/file2
78+
typeset blocks=$(get_same_blocks $TESTPOOL file1 $TESTPOOL file2)
79+
80+
# FreeBSD's seq(1) leaves a trailing space, remove it with sed(1).
81+
log_must [ "$blocks" = "$(seq -s " " 0 1023 | sed 's/ $//')" ]
82+
83+
log_pass $claim

0 commit comments

Comments
 (0)