]> git.proxmox.com Git - mirror_zfs.git/blob - tests/zfs-tests/tests/functional/bclone/bclone_common.kshlib
3b8eaea5bb5459e7a6e9c1bc0b8b878234b68793
[mirror_zfs.git] / tests / zfs-tests / tests / functional / bclone / bclone_common.kshlib
1 #
2 # CDDL HEADER START
3 #
4 # The contents of this file are subject to the terms of the
5 # Common Development and Distribution License (the "License").
6 # You may not use this file except in compliance with the License.
7 #
8 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 # or https://opensource.org/licenses/CDDL-1.0.
10 # See the License for the specific language governing permissions
11 # and limitations under the License.
12 #
13 # When distributing Covered Code, include this CDDL HEADER in each
14 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 # If applicable, add the following below this CDDL HEADER, with the
16 # fields enclosed by brackets "[]" replaced with your own identifying
17 # information: Portions Copyright [yyyy] [name of copyright owner]
18 #
19 # CDDL HEADER END
20 #
21
22 #
23 # Copyright (c) 2023 by Pawel Jakub Dawidek
24 #
25
26 . $STF_SUITE/tests/functional/bclone/bclone.cfg
27
28 export RECORDSIZE=$(zfs get -Hp -o value recordsize $TESTPOOL/$TESTFS)
29
30 MINBLKSIZE1=512
31 MINBLKSIZE2=1024
32
33 function verify_block_cloning
34 {
35 if is_linux && [[ $(linux_version) -lt $(linux_version "4.5") ]]; then
36 log_unsupported "copy_file_range not available before Linux 4.5"
37 fi
38 }
39
40 function verify_crossfs_block_cloning
41 {
42 if is_linux && [[ $(linux_version) -lt $(linux_version "5.3") ]]; then
43 log_unsupported "copy_file_range can't copy cross-filesystem before Linux 5.3"
44 fi
45
46 # Cross dataset block cloning only supported on FreeBSD 14+
47 # https://github.com/freebsd/freebsd-src/commit/969071be938c
48 if is_freebsd && [ $(freebsd_version) -lt $(freebsd_version 14.0) ] ; then
49 log_unsupported "Cloning across datasets not supported in $(uname -r)"
50 fi
51 }
52
53 # Unused.
54 function size_to_dsize
55 {
56 typeset -r size=$1
57 typeset -r dir=$2
58
59 typeset -r dataset=$(df $dir | tail -1 | awk '{print $1}')
60 typeset -r recordsize=$(get_prop recordsize $dataset)
61 typeset -r copies=$(get_prop copies $dataset)
62 typeset dsize
63
64 if [[ $size -le $recordsize ]]; then
65 dsize=$(( ((size - 1) / MINBLOCKSIZE + 1) * MINBLOCKSIZE ))
66 else
67 dsize=$(( ((size - 1) / recordsize + 1) * recordsize ))
68 fi
69 dsize=$((dsize*copies))
70
71 echo $dsize
72 }
73
74 function test_file_integrity
75 {
76 typeset -r original_checksum=$1
77 typeset -r clone=$2
78 typeset -r filesize=$3
79
80 typeset -r clone_checksum=$(sha256digest $clone)
81
82 if [[ $original_checksum != $clone_checksum ]]; then
83 log_fail "Clone $clone is corrupted with file size $filesize"
84 fi
85 }
86
87 function verify_pool_prop_eq
88 {
89 typeset -r prop=$1
90 typeset -r expected=$2
91
92 typeset -r value=$(get_pool_prop $prop $TESTPOOL)
93 if [[ $value != $expected ]]; then
94 log_fail "Pool property $prop is incorrect: expected $expected, got $value"
95 fi
96 }
97
98 function verify_pool_props
99 {
100 typeset -r dsize=$1
101 typeset -r ratio=$2
102
103 if [[ $dsize -eq 0 ]]; then
104 verify_pool_prop_eq bcloneused 0
105 verify_pool_prop_eq bclonesaved 0
106 verify_pool_prop_eq bcloneratio 1.00
107 else
108 if [[ $ratio -eq 1 ]]; then
109 verify_pool_prop_eq bcloneused 0
110 else
111 verify_pool_prop_eq bcloneused $dsize
112 fi
113 verify_pool_prop_eq bclonesaved $((dsize*(ratio-1)))
114 verify_pool_prop_eq bcloneratio "${ratio}.00"
115 fi
116 }
117
118 # Function to test file copying and integrity check.
119 function bclone_test
120 {
121 typeset -r datatype=$1
122 typeset filesize=$2
123 typeset -r embedded=$3
124 typeset -r srcdir=$4
125 typeset -r dstdir=$5
126 typeset dsize
127
128 typeset -r original="${srcdir}/original"
129 typeset -r clone="${dstdir}/clone"
130
131 log_note "Testing file copy with datatype $datatype, file size $filesize, embedded $embedded"
132
133 # Create a test file with known content.
134 case $datatype in
135 random|text)
136 sync_pool $TESTPOOL
137 if [[ $datatype = "random" ]]; then
138 dd if=/dev/urandom of=$original bs=$filesize count=1 2>/dev/null
139 else
140 filesize=$(((filesize/4)*4))
141 dd if=/dev/urandom bs=$(((filesize/4)*3)) count=1 | \
142 openssl base64 -A > $original
143 fi
144 sync_pool $TESTPOOL
145 clonefile -f $original "${clone}-tmp"
146 sync_pool $TESTPOOL
147 # It is hard to predict block sizes that will be used,
148 # so just do one clone and take it from bcloneused.
149 filesize=$(zpool get -Hp -o value bcloneused $TESTPOOL)
150 if [[ $embedded = "false" ]]; then
151 log_must test $filesize -gt 0
152 fi
153 rm -f "${clone}-tmp"
154 sync_pool $TESTPOOL
155 dsize=$filesize
156 ;;
157 hole)
158 log_must truncate_test -s $filesize -f $original
159 dsize=0
160 ;;
161 *)
162 log_fail "Unknown datatype $datatype"
163 ;;
164 esac
165 if [[ $embedded = "true" ]]; then
166 dsize=0
167 fi
168
169 typeset -r original_checksum=$(sha256digest $original)
170
171 sync_pool $TESTPOOL
172
173 # Create a first clone of the entire file.
174 clonefile -f $original "${clone}0"
175 # Try to clone the clone in the same transaction group.
176 clonefile -f "${clone}0" "${clone}2"
177
178 # Clone the original again...
179 clonefile -f $original "${clone}1"
180 # ...and overwrite it in the same transaction group.
181 clonefile -f $original "${clone}1"
182
183 # Clone the clone...
184 clonefile -f "${clone}1" "${clone}3"
185 sync_pool $TESTPOOL
186 # ...and overwrite in the new transaction group.
187 clonefile -f "${clone}1" "${clone}3"
188
189 sync_pool $TESTPOOL
190
191 # Test removal of the pending clones (before they are committed to disk).
192 clonefile -f $original "${clone}4"
193 clonefile -f "${clone}4" "${clone}5"
194 rm -f "${clone}4" "${clone}5"
195
196 # Clone into one file, but remove another file, but with the same data in
197 # the same transaction group.
198 clonefile -f $original "${clone}5"
199 sync_pool $TESTPOOL
200 clonefile -f $original "${clone}4"
201 rm -f "${clone}5"
202 test_file_integrity $original_checksum "${clone}4" $filesize
203 sync_pool $TESTPOOL
204 test_file_integrity $original_checksum "${clone}4" $filesize
205
206 clonefile -f "${clone}4" "${clone}5"
207 # Verify integrity of the cloned file before it is committed to disk.
208 test_file_integrity $original_checksum "${clone}5" $filesize
209
210 sync_pool $TESTPOOL
211
212 # Verify integrity in the new transaction group.
213 test_file_integrity $original_checksum "${clone}0" $filesize
214 test_file_integrity $original_checksum "${clone}1" $filesize
215 test_file_integrity $original_checksum "${clone}2" $filesize
216 test_file_integrity $original_checksum "${clone}3" $filesize
217 test_file_integrity $original_checksum "${clone}4" $filesize
218 test_file_integrity $original_checksum "${clone}5" $filesize
219
220 verify_pool_props $dsize 7
221
222 # Clear cache and test after fresh import.
223 log_must zpool export $TESTPOOL
224 log_must zpool import $TESTPOOL
225
226 # Cloned uncached file.
227 clonefile -f $original "${clone}6"
228 # Cloned uncached clone.
229 clonefile -f "${clone}6" "${clone}7"
230
231 # Cache the file.
232 cat $original >/dev/null
233 clonefile -f $original "${clone}8"
234 clonefile -f "${clone}8" "${clone}9"
235
236 test_file_integrity $original_checksum "${clone}6" $filesize
237 test_file_integrity $original_checksum "${clone}7" $filesize
238 test_file_integrity $original_checksum "${clone}8" $filesize
239 test_file_integrity $original_checksum "${clone}9" $filesize
240
241 sync_pool $TESTPOOL
242
243 verify_pool_props $dsize 11
244
245 log_must zpool export $TESTPOOL
246 log_must zpool import $TESTPOOL
247
248 test_file_integrity $original_checksum "${clone}0" $filesize
249 test_file_integrity $original_checksum "${clone}1" $filesize
250 test_file_integrity $original_checksum "${clone}2" $filesize
251 test_file_integrity $original_checksum "${clone}3" $filesize
252 test_file_integrity $original_checksum "${clone}4" $filesize
253 test_file_integrity $original_checksum "${clone}5" $filesize
254 test_file_integrity $original_checksum "${clone}6" $filesize
255 test_file_integrity $original_checksum "${clone}7" $filesize
256 test_file_integrity $original_checksum "${clone}8" $filesize
257 test_file_integrity $original_checksum "${clone}9" $filesize
258
259 rm -f $original
260 rm -f "${clone}1" "${clone}3" "${clone}5" "${clone}7"
261
262 sync_pool $TESTPOOL
263
264 test_file_integrity $original_checksum "${clone}0" $filesize
265 test_file_integrity $original_checksum "${clone}2" $filesize
266 test_file_integrity $original_checksum "${clone}4" $filesize
267 test_file_integrity $original_checksum "${clone}6" $filesize
268 test_file_integrity $original_checksum "${clone}8" $filesize
269 test_file_integrity $original_checksum "${clone}9" $filesize
270
271 verify_pool_props $dsize 6
272
273 rm -f "${clone}0" "${clone}2" "${clone}4" "${clone}8" "${clone}9"
274
275 sync_pool $TESTPOOL
276
277 test_file_integrity $original_checksum "${clone}6" $filesize
278
279 verify_pool_props $dsize 1
280
281 rm -f "${clone}6"
282
283 sync_pool $TESTPOOL
284
285 verify_pool_props $dsize 1
286 }