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 28export RECORDSIZE=$(zfs get -Hp -o value recordsize $TESTPOOL/$TESTFS) 29 30MINBLKSIZE1=512 31MINBLKSIZE2=1024 32 33function 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 40function 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 47# Unused. 48function size_to_dsize 49{ 50 typeset -r size=$1 51 typeset -r dir=$2 52 53 typeset -r dataset=$(df $dir | tail -1 | awk '{print $1}') 54 typeset -r recordsize=$(get_prop recordsize $dataset) 55 typeset -r copies=$(get_prop copies $dataset) 56 typeset dsize 57 58 if [[ $size -le $recordsize ]]; then 59 dsize=$(( ((size - 1) / MINBLOCKSIZE + 1) * MINBLOCKSIZE )) 60 else 61 dsize=$(( ((size - 1) / recordsize + 1) * recordsize )) 62 fi 63 dsize=$((dsize*copies)) 64 65 echo $dsize 66} 67 68function test_file_integrity 69{ 70 typeset -r original_checksum=$1 71 typeset -r clone=$2 72 typeset -r filesize=$3 73 74 typeset -r clone_checksum=$(sha256digest $clone) 75 76 if [[ $original_checksum != $clone_checksum ]]; then 77 log_fail "Clone $clone is corrupted with file size $filesize" 78 fi 79} 80 81function verify_pool_prop_eq 82{ 83 typeset -r prop=$1 84 typeset -r expected=$2 85 86 typeset -r value=$(get_pool_prop $prop $TESTPOOL) 87 if [[ $value != $expected ]]; then 88 log_fail "Pool property $prop is incorrect: expected $expected, got $value" 89 fi 90} 91 92function verify_pool_props 93{ 94 typeset -r dsize=$1 95 typeset -r ratio=$2 96 97 if [[ $dsize -eq 0 ]]; then 98 verify_pool_prop_eq bcloneused 0 99 verify_pool_prop_eq bclonesaved 0 100 verify_pool_prop_eq bcloneratio 1.00 101 else 102 if [[ $ratio -eq 1 ]]; then 103 verify_pool_prop_eq bcloneused 0 104 else 105 verify_pool_prop_eq bcloneused $dsize 106 fi 107 verify_pool_prop_eq bclonesaved $((dsize*(ratio-1))) 108 verify_pool_prop_eq bcloneratio "${ratio}.00" 109 fi 110} 111 112# Function to test file copying and integrity check. 113function bclone_test 114{ 115 typeset -r datatype=$1 116 typeset filesize=$2 117 typeset -r embedded=$3 118 typeset -r srcdir=$4 119 typeset -r dstdir=$5 120 typeset dsize 121 122 typeset -r original="${srcdir}/original" 123 typeset -r clone="${dstdir}/clone" 124 125 log_note "Testing file copy with datatype $datatype, file size $filesize, embedded $embedded" 126 127 # Create a test file with known content. 128 case $datatype in 129 random|text) 130 sync_pool $TESTPOOL 131 if [[ $datatype = "random" ]]; then 132 dd if=/dev/urandom of=$original bs=$filesize count=1 2>/dev/null 133 else 134 filesize=$(((filesize/4)*4)) 135 dd if=/dev/urandom bs=$(((filesize/4)*3)) count=1 | \ 136 openssl base64 -A > $original 137 fi 138 sync_pool $TESTPOOL 139 clonefile -f $original "${clone}-tmp" 140 sync_pool $TESTPOOL 141 # It is hard to predict block sizes that will be used, 142 # so just do one clone and take it from bcloneused. 143 filesize=$(zpool get -Hp -o value bcloneused $TESTPOOL) 144 if [[ $embedded = "false" ]]; then 145 log_must test $filesize -gt 0 146 fi 147 rm -f "${clone}-tmp" 148 sync_pool $TESTPOOL 149 dsize=$filesize 150 ;; 151 hole) 152 log_must truncate_test -s $filesize -f $original 153 dsize=0 154 ;; 155 *) 156 log_fail "Unknown datatype $datatype" 157 ;; 158 esac 159 if [[ $embedded = "true" ]]; then 160 dsize=0 161 fi 162 163 typeset -r original_checksum=$(sha256digest $original) 164 165 sync_pool $TESTPOOL 166 167 # Create a first clone of the entire file. 168 clonefile -f $original "${clone}0" 169 # Try to clone the clone in the same transaction group. 170 clonefile -f "${clone}0" "${clone}2" 171 172 # Clone the original again... 173 clonefile -f $original "${clone}1" 174 # ...and overwrite it in the same transaction group. 175 clonefile -f $original "${clone}1" 176 177 # Clone the clone... 178 clonefile -f "${clone}1" "${clone}3" 179 sync_pool $TESTPOOL 180 # ...and overwrite in the new transaction group. 181 clonefile -f "${clone}1" "${clone}3" 182 183 sync_pool $TESTPOOL 184 185 # Test removal of the pending clones (before they are committed to disk). 186 clonefile -f $original "${clone}4" 187 clonefile -f "${clone}4" "${clone}5" 188 rm -f "${clone}4" "${clone}5" 189 190 # Clone into one file, but remove another file, but with the same data in 191 # the same transaction group. 192 clonefile -f $original "${clone}5" 193 sync_pool $TESTPOOL 194 clonefile -f $original "${clone}4" 195 rm -f "${clone}5" 196 test_file_integrity $original_checksum "${clone}4" $filesize 197 sync_pool $TESTPOOL 198 test_file_integrity $original_checksum "${clone}4" $filesize 199 200 clonefile -f "${clone}4" "${clone}5" 201 # Verify integrity of the cloned file before it is committed to disk. 202 test_file_integrity $original_checksum "${clone}5" $filesize 203 204 sync_pool $TESTPOOL 205 206 # Verify integrity in the new transaction group. 207 test_file_integrity $original_checksum "${clone}0" $filesize 208 test_file_integrity $original_checksum "${clone}1" $filesize 209 test_file_integrity $original_checksum "${clone}2" $filesize 210 test_file_integrity $original_checksum "${clone}3" $filesize 211 test_file_integrity $original_checksum "${clone}4" $filesize 212 test_file_integrity $original_checksum "${clone}5" $filesize 213 214 verify_pool_props $dsize 7 215 216 # Clear cache and test after fresh import. 217 log_must zpool export $TESTPOOL 218 log_must zpool import $TESTPOOL 219 220 # Cloned uncached file. 221 clonefile -f $original "${clone}6" 222 # Cloned uncached clone. 223 clonefile -f "${clone}6" "${clone}7" 224 225 # Cache the file. 226 cat $original >/dev/null 227 clonefile -f $original "${clone}8" 228 clonefile -f "${clone}8" "${clone}9" 229 230 test_file_integrity $original_checksum "${clone}6" $filesize 231 test_file_integrity $original_checksum "${clone}7" $filesize 232 test_file_integrity $original_checksum "${clone}8" $filesize 233 test_file_integrity $original_checksum "${clone}9" $filesize 234 235 sync_pool $TESTPOOL 236 237 verify_pool_props $dsize 11 238 239 log_must zpool export $TESTPOOL 240 log_must zpool import $TESTPOOL 241 242 test_file_integrity $original_checksum "${clone}0" $filesize 243 test_file_integrity $original_checksum "${clone}1" $filesize 244 test_file_integrity $original_checksum "${clone}2" $filesize 245 test_file_integrity $original_checksum "${clone}3" $filesize 246 test_file_integrity $original_checksum "${clone}4" $filesize 247 test_file_integrity $original_checksum "${clone}5" $filesize 248 test_file_integrity $original_checksum "${clone}6" $filesize 249 test_file_integrity $original_checksum "${clone}7" $filesize 250 test_file_integrity $original_checksum "${clone}8" $filesize 251 test_file_integrity $original_checksum "${clone}9" $filesize 252 253 rm -f $original 254 rm -f "${clone}1" "${clone}3" "${clone}5" "${clone}7" 255 256 sync_pool $TESTPOOL 257 258 test_file_integrity $original_checksum "${clone}0" $filesize 259 test_file_integrity $original_checksum "${clone}2" $filesize 260 test_file_integrity $original_checksum "${clone}4" $filesize 261 test_file_integrity $original_checksum "${clone}6" $filesize 262 test_file_integrity $original_checksum "${clone}8" $filesize 263 test_file_integrity $original_checksum "${clone}9" $filesize 264 265 verify_pool_props $dsize 6 266 267 rm -f "${clone}0" "${clone}2" "${clone}4" "${clone}8" "${clone}9" 268 269 sync_pool $TESTPOOL 270 271 test_file_integrity $original_checksum "${clone}6" $filesize 272 273 verify_pool_props $dsize 1 274 275 rm -f "${clone}6" 276 277 sync_pool $TESTPOOL 278 279 verify_pool_props $dsize 1 280} 281